summaryrefslogtreecommitdiffstats
path: root/Doc/library/unittest.rst
blob: 66ed10c1a9fac030605005baf25ef3f5f69cbb78 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
:mod:`unittest` --- Unit testing framework
==========================================

.. module:: unittest
   :synopsis: Unit testing framework for Python.
.. moduleauthor:: Steve Purcell <stephen_purcell@yahoo.com>
.. sectionauthor:: Steve Purcell <stephen_purcell@yahoo.com>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. sectionauthor:: Raymond Hettinger <python@rcn.com>


The Python unit testing framework, sometimes referred to as "PyUnit," is a
Python language version of JUnit, by Kent Beck and Erich Gamma. JUnit is, in
turn, a Java version of Kent's Smalltalk testing framework.  Each is the de
facto standard unit testing framework for its respective language.

:mod:`unittest` supports test automation, sharing of setup and shutdown code for
tests, aggregation of tests into collections, and independence of the tests from
the reporting framework.  The :mod:`unittest` module provides classes that make
it easy to support these qualities for a set of tests.

To achieve this, :mod:`unittest` supports some important concepts:

test fixture
   A :dfn:`test fixture` represents the preparation needed to perform one or more
   tests, and any associate cleanup actions.  This may involve, for example,
   creating temporary or proxy databases, directories, or starting a server
   process.

test case
   A :dfn:`test case` is the smallest unit of testing.  It checks for a specific
   response to a particular set of inputs.  :mod:`unittest` provides a base class,
   :class:`TestCase`, which may be used to create new test cases.

test suite
   A :dfn:`test suite` is a collection of test cases, test suites, or both.  It is
   used to aggregate tests that should be executed together.

test runner
   A :dfn:`test runner` is a component which orchestrates the execution of tests
   and provides the outcome to the user.  The runner may use a graphical interface,
   a textual interface, or return a special value to indicate the results of
   executing the tests.

The test case and test fixture concepts are supported through the
:class:`TestCase` and :class:`FunctionTestCase` classes; the former should be
used when creating new tests, and the latter can be used when integrating
existing test code with a :mod:`unittest`\ -driven framework. When building test
fixtures using :class:`TestCase`, the :meth:`~TestCase.setUp` and
:meth:`~TestCase.tearDown` methods can be overridden to provide initialization
and cleanup for the fixture.  With :class:`FunctionTestCase`, existing functions
can be passed to the constructor for these purposes.  When the test is run, the
fixture initialization is run first; if it succeeds, the cleanup method is run
after the test has been executed, regardless of the outcome of the test.  Each
instance of the :class:`TestCase` will only be used to run a single test method,
so a new fixture is created for each test.

Test suites are implemented by the :class:`TestSuite` class.  This class allows
individual tests and test suites to be aggregated; when the suite is executed,
all tests added directly to the suite and in "child" test suites are run.

A test runner is an object that provides a single method,
:meth:`~TestRunner.run`, which accepts a :class:`TestCase` or :class:`TestSuite`
object as a parameter, and returns a result object.  The class
:class:`TestResult` is provided for use as the result object. :mod:`unittest`
provides the :class:`TextTestRunner` as an example test runner which reports
test results on the standard error stream by default.  Alternate runners can be
implemented for other environments (such as graphical environments) without any
need to derive from a specific class.


.. seealso::

   Module :mod:`doctest`
      Another test-support module with a very different flavor.

   `unittest2: A backport of new unittest features for Python 2.4-2.6 <http://pypi.python.org/pypi/unittest2>`_
      Many new features were added to unittest in Python 2.7, including test
      discovery. unittest2 allows you to use these features with earlier
      versions of Python.

   `Simple Smalltalk Testing: With Patterns <http://www.XProgramming.com/testfram.htm>`_
      Kent Beck's original paper on testing frameworks using the pattern shared
      by :mod:`unittest`.

   `Nose <http://code.google.com/p/python-nose/>`_ and `py.test <http://pytest.org>`_
      Third-party unittest frameworks with a lighter-weight syntax for writing
      tests.  For example, ``assert func(10) == 42``.

   `The Python Testing Tools Taxonomy <http://pycheesecake.org/wiki/PythonTestingToolsTaxonomy>`_
      An extensive list of Python testing tools including functional testing
      frameworks and mock object libraries.

   `Testing in Python Mailing List <http://lists.idyll.org/listinfo/testing-in-python>`_
      A special-interest-group for discussion of testing, and testing tools,
      in Python.

.. _unittest-minimal-example:

Basic example
-------------

The :mod:`unittest` module provides a rich set of tools for constructing and
running tests.  This section demonstrates that a small subset of the tools
suffice to meet the needs of most users.

Here is a short script to test three functions from the :mod:`random` module::

   import random
   import unittest

   class TestSequenceFunctions(unittest.TestCase):

       def setUp(self):
           self.seq = list(range(10))

       def test_shuffle(self):
           # make sure the shuffled sequence does not lose any elements
           random.shuffle(self.seq)
           self.seq.sort()
           self.assertEqual(self.seq, list(range(10)))

           # should raise an exception for an immutable sequence
           self.assertRaises(TypeError, random.shuffle, (1,2,3))

       def test_choice(self):
           element = random.choice(self.seq)
           self.assertTrue(element in self.seq)

       def test_sample(self):
           with self.assertRaises(ValueError):
               random.sample(self.seq, 20)
           for element in random.sample(self.seq, 5):
               self.assertTrue(element in self.seq)

   if __name__ == '__main__':
       unittest.main()

A testcase is created by subclassing :class:`unittest.TestCase`.  The three
individual tests are defined with methods whose names start with the letters
``test``.  This naming convention informs the test runner about which methods
represent tests.

The crux of each test is a call to :meth:`~TestCase.assertEqual` to check for an
expected result; :meth:`~TestCase.assertTrue` to verify a condition; or
:meth:`~TestCase.assertRaises` to verify that an expected exception gets raised.
These methods are used instead of the :keyword:`assert` statement so the test
runner can accumulate all test results and produce a report.

When a :meth:`~TestCase.setUp` method is defined, the test runner will run that
method prior to each test.  Likewise, if a :meth:`~TestCase.tearDown` method is
defined, the test runner will invoke that method after each test.  In the
example, :meth:`~TestCase.setUp` was used to create a fresh sequence for each
test.

The final block shows a simple way to run the tests. :func:`unittest.main`
provides a command line interface to the test script.  When run from the command
line, the above script produces an output that looks like this::

   ...
   ----------------------------------------------------------------------
   Ran 3 tests in 0.000s

   OK

Instead of :func:`unittest.main`, there are other ways to run the tests with a
finer level of control, less terse output, and no requirement to be run from the
command line.  For example, the last two lines may be replaced with::

   suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
   unittest.TextTestRunner(verbosity=2).run(suite)

Running the revised script from the interpreter or another script produces the
following output::

   test_choice (__main__.TestSequenceFunctions) ... ok
   test_sample (__main__.TestSequenceFunctions) ... ok
   test_shuffle (__main__.TestSequenceFunctions) ... ok

   ----------------------------------------------------------------------
   Ran 3 tests in 0.110s

   OK

The above examples show the most commonly used :mod:`unittest` features which
are sufficient to meet many everyday testing needs.  The remainder of the
documentation explores the full feature set from first principles.


.. _unittest-command-line-interface:

Command Line Interface
----------------------

The unittest module can be used from the command line to run tests from
modules, classes or even individual test methods::

   python -m unittest test_module1 test_module2
   python -m unittest test_module.TestClass
   python -m unittest test_module.TestClass.test_method

You can pass in a list with any combination of module names, and fully
qualified class or method names.

You can run tests with more detail (higher verbosity) by passing in the -v flag::

   python -m unittest -v test_module

For a list of all the command line options::

   python -m unittest -h

.. versionchanged:: 3.2
   In earlier versions it was only possible to run individual test methods and
   not modules or classes.


failfast, catch and buffer command line options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

unittest supports three command options.

* :option:`-b` / :option:`--buffer`

  The standard output and standard error streams are buffered during the test
  run. Output during a passing test is discarded. Output is echoed normally
  on test fail or error and is added to the failure messages.

* :option:`-c` / :option:`--catch`

  Control-C during the test run waits for the current test to end and then
  reports all the results so far. A second control-C raises the normal
  :exc:`KeyboardInterrupt` exception.

  See `Signal Handling`_ for the functions that provide this functionality.

* :option:`-f` / :option:`--failfast`

  Stop the test run on the first error or failure.

.. versionadded:: 3.2
   The command line options ``-c``, ``-b`` and ``-f`` were added.

The command line can also be used for test discovery, for running all of the
tests in a project or just a subset.


.. _unittest-test-discovery:

Test Discovery
--------------

.. versionadded:: 3.2

Unittest supports simple test discovery. For a project's tests to be
compatible with test discovery they must all be importable from the top level
directory of the project (in other words, they must all be in Python packages).

Test discovery is implemented in :meth:`TestLoader.discover`, but can also be
used from the command line. The basic command line usage is::

   cd project_directory
   python -m unittest discover

The ``discover`` sub-command has the following options:

   -v, --verbose    Verbose output
   -s directory     Directory to start discovery ('.' default)
   -p pattern       Pattern to match test files ('test*.py' default)
   -t directory     Top level directory of project (default to
                    start directory)

The :option:`-s`, :option:`-p`, and :option:`-t` options can be passed in
as positional arguments in that order. The following two command lines
are equivalent::

   python -m unittest discover -s project_directory -p '*_test.py'
   python -m unittest discover project_directory '*_test.py'

As well as being a path it is possible to pass a package name, for example
``myproject.subpackage.test``, as the start directory. The package name you
supply will then be imported and its location on the filesystem will be used
as the start directory.

.. caution::

    Test discovery loads tests by importing them. Once test discovery has
    found all the test files from the start directory you specify it turns the
    paths into package names to import. For example `foo/bar/baz.py` will be
    imported as ``foo.bar.baz``.

    If you have a package installed globally and attempt test discovery on
    a different copy of the package then the import *could* happen from the
    wrong place. If this happens test discovery will warn you and exit.

    If you supply the start directory as a package name rather than a
    path to a directory then discover assumes that whichever location it
    imports from is the location you intended, so you will not get the
    warning.

Test modules and packages can customize test loading and discovery by through
the `load_tests protocol`_.


.. _organizing-tests:

Organizing test code
--------------------

The basic building blocks of unit testing are :dfn:`test cases` --- single
scenarios that must be set up and checked for correctness.  In :mod:`unittest`,
test cases are represented by instances of :mod:`unittest`'s :class:`TestCase`
class. To make your own test cases you must write subclasses of
:class:`TestCase`, or use :class:`FunctionTestCase`.

An instance of a :class:`TestCase`\ -derived class is an object that can
completely run a single test method, together with optional set-up and tidy-up
code.

The testing code of a :class:`TestCase` instance should be entirely self
contained, such that it can be run either in isolation or in arbitrary
combination with any number of other test cases.

The simplest :class:`TestCase` subclass will simply override the
:meth:`~TestCase.runTest` method in order to perform specific testing code::

   import unittest

   class DefaultWidgetSizeTestCase(unittest.TestCase):
       def runTest(self):
           widget = Widget('The widget')
           self.assertEqual(widget.size(), (50, 50), 'incorrect default size')

Note that in order to test something, we use the one of the :meth:`assert\*`
methods provided by the :class:`TestCase` base class.  If the test fails, an
exception will be raised, and :mod:`unittest` will identify the test case as a
:dfn:`failure`.  Any other exceptions will be treated as :dfn:`errors`. This
helps you identify where the problem is: :dfn:`failures` are caused by incorrect
results - a 5 where you expected a 6. :dfn:`Errors` are caused by incorrect
code - e.g., a :exc:`TypeError` caused by an incorrect function call.

The way to run a test case will be described later.  For now, note that to
construct an instance of such a test case, we call its constructor without
arguments::

   testCase = DefaultWidgetSizeTestCase()

Now, such test cases can be numerous, and their set-up can be repetitive.  In
the above case, constructing a :class:`Widget` in each of 100 Widget test case
subclasses would mean unsightly duplication.

Luckily, we can factor out such set-up code by implementing a method called
:meth:`~TestCase.setUp`, which the testing framework will automatically call for
us when we run the test::

   import unittest

   class SimpleWidgetTestCase(unittest.TestCase):
       def setUp(self):
           self.widget = Widget('The widget')

   class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
       def runTest(self):
           self.assertEqual(self.widget.size(), (50,50),
                            'incorrect default size')

   class WidgetResizeTestCase(SimpleWidgetTestCase):
       def runTest(self):
           self.widget.resize(100,150)
           self.assertEqual(self.widget.size(), (100,150),
                            'wrong size after resize')

If the :meth:`~TestCase.setUp` method raises an exception while the test is
running, the framework will consider the test to have suffered an error, and the
:meth:`~TestCase.runTest` method will not be executed.

Similarly, we can provide a :meth:`~TestCase.tearDown` method that tidies up
after the :meth:`~TestCase.runTest` method has been run::

   import unittest

   class SimpleWidgetTestCase(unittest.TestCase):
       def setUp(self):
           self.widget = Widget('The widget')

       def tearDown(self):
           self.widget.dispose()
           self.widget = None

If :meth:`~TestCase.setUp` succeeded, the :meth:`~TestCase.tearDown` method will
be run whether :meth:`~TestCase.runTest` succeeded or not.

Such a working environment for the testing code is called a :dfn:`fixture`.

Often, many small test cases will use the same fixture.  In this case, we would
end up subclassing :class:`SimpleWidgetTestCase` into many small one-method
classes such as :class:`DefaultWidgetSizeTestCase`.  This is time-consuming and
discouraging, so in the same vein as JUnit, :mod:`unittest` provides a simpler
mechanism::

   import unittest

   class WidgetTestCase(unittest.TestCase):
       def setUp(self):
           self.widget = Widget('The widget')

       def tearDown(self):
           self.widget.dispose()
           self.widget = None

       def test_default_size(self):
           self.assertEqual(self.widget.size(), (50,50),
                            'incorrect default size')

       def test_resize(self):
           self.widget.resize(100,150)
           self.assertEqual(self.widget.size(), (100,150),
                            'wrong size after resize')

Here we have not provided a :meth:`~TestCase.runTest` method, but have instead
provided two different test methods.  Class instances will now each run one of
the :meth:`test_\*` methods, with ``self.widget`` created and destroyed
separately for each instance.  When creating an instance we must specify the
test method it is to run.  We do this by passing the method name in the
constructor::

   defaultSizeTestCase = WidgetTestCase('test_default_size')
   resizeTestCase = WidgetTestCase('test_resize')

Test case instances are grouped together according to the features they test.
:mod:`unittest` provides a mechanism for this: the :dfn:`test suite`,
represented by :mod:`unittest`'s :class:`TestSuite` class::

   widgetTestSuite = unittest.TestSuite()
   widgetTestSuite.addTest(WidgetTestCase('test_default_size'))
   widgetTestSuite.addTest(WidgetTestCase('test_resize'))

For the ease of running tests, as we will see later, it is a good idea to
provide in each test module a callable object that returns a pre-built test
suite::

   def suite():
       suite = unittest.TestSuite()
       suite.addTest(WidgetTestCase('test_default_size'))
       suite.addTest(WidgetTestCase('test_resize'))
       return suite

or even::

   def suite():
       tests = ['test_default_size', 'test_resize']

       return unittest.TestSuite(map(WidgetTestCase, tests))

Since it is a common pattern to create a :class:`TestCase` subclass with many
similarly named test functions, :mod:`unittest` provides a :class:`TestLoader`
class that can be used to automate the process of creating a test suite and
populating it with individual tests. For example, ::

   suite = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)

will create a test suite that will run ``WidgetTestCase.test_default_size()`` and
``WidgetTestCase.test_resize``. :class:`TestLoader` uses the ``'test'`` method
name prefix to identify test methods automatically.

Note that the order in which the various test cases will be run is
determined by sorting the test function names with respect to the
built-in ordering for strings.

Often it is desirable to group suites of test cases together, so as to run tests
for the whole system at once.  This is easy, since :class:`TestSuite` instances
can be added to a :class:`TestSuite` just as :class:`TestCase` instances can be
added to a :class:`TestSuite`::

   suite1 = module1.TheTestSuite()
   suite2 = module2.TheTestSuite()
   alltests = unittest.TestSuite([suite1, suite2])

You can place the definitions of test cases and test suites in the same modules
as the code they are to test (such as :file:`widget.py`), but there are several
advantages to placing the test code in a separate module, such as
:file:`test_widget.py`:

* The test module can be run standalone from the command line.

* The test code can more easily be separated from shipped code.

* There is less temptation to change test code to fit the code it tests without
  a good reason.

* Test code should be modified much less frequently than the code it tests.

* Tested code can be refactored more easily.

* Tests for modules written in C must be in separate modules anyway, so why not
  be consistent?

* If the testing strategy changes, there is no need to change the source code.


.. _legacy-unit-tests:

Re-using old test code
----------------------

Some users will find that they have existing test code that they would like to
run from :mod:`unittest`, without converting every old test function to a
:class:`TestCase` subclass.

For this reason, :mod:`unittest` provides a :class:`FunctionTestCase` class.
This subclass of :class:`TestCase` can be used to wrap an existing test
function.  Set-up and tear-down functions can also be provided.

Given the following test function::

   def testSomething():
       something = makeSomething()
       assert something.name is not None
       # ...

one can create an equivalent test case instance as follows::

   testcase = unittest.FunctionTestCase(testSomething)

If there are additional set-up and tear-down methods that should be called as
part of the test case's operation, they can also be provided like so::

   testcase = unittest.FunctionTestCase(testSomething,
                                        setUp=makeSomethingDB,
                                        tearDown=deleteSomethingDB)

To make migrating existing test suites easier, :mod:`unittest` supports tests
raising :exc:`AssertionError` to indicate test failure. However, it is
recommended that you use the explicit :meth:`TestCase.fail\*` and
:meth:`TestCase.assert\*` methods instead, as future versions of :mod:`unittest`
may treat :exc:`AssertionError` differently.

.. note::

   Even though :class:`FunctionTestCase` can be used to quickly convert an
   existing test base over to a :mod:`unittest`\ -based system, this approach is
   not recommended.  Taking the time to set up proper :class:`TestCase`
   subclasses will make future test refactorings infinitely easier.

In some cases, the existing tests may have been written using the :mod:`doctest`
module.  If so, :mod:`doctest` provides a :class:`DocTestSuite` class that can
automatically build :class:`unittest.TestSuite` instances from the existing
:mod:`doctest`\ -based tests.


.. _unittest-skipping:

Skipping tests and expected failures
------------------------------------

.. versionadded:: 3.1

Unittest supports skipping individual test methods and even whole classes of
tests.  In addition, it supports marking a test as a "expected failure," a test
that is broken and will fail, but shouldn't be counted as a failure on a
:class:`TestResult`.

Skipping a test is simply a matter of using the :func:`skip` :term:`decorator`
or one of its conditional variants.

Basic skipping looks like this: ::

   class MyTestCase(unittest.TestCase):

       @unittest.skip("demonstrating skipping")
       def test_nothing(self):
           self.fail("shouldn't happen")

       @unittest.skipIf(mylib.__version__ < (1, 3),
                        "not supported in this library version")
       def test_format(self):
           # Tests that work for only a certain version of the library.
           pass

       @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
       def test_windows_support(self):
           # windows specific testing code
           pass

This is the output of running the example above in verbose mode: ::

   test_format (__main__.MyTestCase) ... skipped 'not supported in this library version'
   test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping'
   test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows'

   ----------------------------------------------------------------------
   Ran 3 tests in 0.005s

   OK (skipped=3)

Classes can be skipped just like methods: ::

   @skip("showing class skipping")
   class MySkippedTestCase(unittest.TestCase):
       def test_not_run(self):
           pass

:meth:`TestCase.setUp` can also skip the test.  This is useful when a resource
that needs to be set up is not available.

Expected failures use the :func:`expectedFailure` decorator. ::

   class ExpectedFailureTestCase(unittest.TestCase):
       @unittest.expectedFailure
       def test_fail(self):
           self.assertEqual(1, 0, "broken")

It's easy to roll your own skipping decorators by making a decorator that calls
:func:`skip` on the test when it wants it to be skipped.  This decorator skips
the test unless the passed object has a certain attribute: ::

   def skipUnlessHasattr(obj, attr):
       if hasattr(obj, attr):
           return lambda func: func
       return unittest.skip("{0!r} doesn't have {1!r}".format(obj, attr))

The following decorators implement test skipping and expected failures:

.. decorator:: skip(reason)

   Unconditionally skip the decorated test.  *reason* should describe why the
   test is being skipped.

.. decorator:: skipIf(condition, reason)

   Skip the decorated test if *condition* is true.

.. decorator:: skipUnless(condition, reason)

   Skip the decoratored test unless *condition* is true.

.. decorator:: expectedFailure

   Mark the test as an expected failure.  If the test fails when run, the test
   is not counted as a failure.

Skipped tests will not have :meth:`setUp` or :meth:`tearDown` run around them.
Skipped classes will not have :meth:`setUpClass` or :meth:`tearDownClass` run.


.. _unittest-contents:

Classes and functions
---------------------

This section describes in depth the API of :mod:`unittest`.


.. _testcase-objects:

Test cases
~~~~~~~~~~

.. class:: TestCase(methodName='runTest')

   Instances of the :class:`TestCase` class represent the smallest testable units
   in the :mod:`unittest` universe.  This class is intended to be used as a base
   class, with specific tests being implemented by concrete subclasses.  This class
   implements the interface needed by the test runner to allow it to drive the
   test, and methods that the test code can use to check for and report various
   kinds of failure.

   Each instance of :class:`TestCase` will run a single test method: the method
   named *methodName*.  If you remember, we had an earlier example that went
   something like this::

      def suite():
          suite = unittest.TestSuite()
          suite.addTest(WidgetTestCase('test_default_size'))
          suite.addTest(WidgetTestCase('test_resize'))
          return suite

   Here, we create two instances of :class:`WidgetTestCase`, each of which runs a
   single test.

   *methodName* defaults to :meth:`runTest`.

   :class:`TestCase` instances provide three groups of methods: one group used
   to run the test, another used by the test implementation to check conditions
   and report failures, and some inquiry methods allowing information about the
   test itself to be gathered.

   Methods in the first group (running the test) are:


   .. method:: setUp()

      Method called to prepare the test fixture.  This is called immediately
      before calling the test method; any exception raised by this method will
      be considered an error rather than a test failure. The default
      implementation does nothing.


   .. method:: tearDown()

      Method called immediately after the test method has been called and the
      result recorded.  This is called even if the test method raised an
      exception, so the implementation in subclasses may need to be particularly
      careful about checking internal state.  Any exception raised by this
      method will be considered an error rather than a test failure.  This
      method will only be called if the :meth:`setUp` succeeds, regardless of
      the outcome of the test method. The default implementation does nothing.


   .. method:: setUpClass()

      A class method called before tests in an individual class run.
      ``setUpClass`` is called with the class as the only argument
      and must be decorated as a :func:`classmethod`::

        @classmethod
        def setUpClass(cls):
            ...

      See `Class and Module Fixtures`_ for more details.

      .. versionadded:: 3.2


   .. method:: tearDownClass()

      A class method called after tests in an individual class have run.
      ``tearDownClass`` is called with the class as the only argument
      and must be decorated as a :meth:`classmethod`::

        @classmethod
        def tearDownClass(cls):
            ...

      See `Class and Module Fixtures`_ for more details.

      .. versionadded:: 3.2


   .. method:: run(result=None)

      Run the test, collecting the result into the test result object passed as
      *result*.  If *result* is omitted or :const:`None`, a temporary result
      object is created (by calling the :meth:`defaultTestResult` method) and
      used. The result object is not returned to :meth:`run`'s caller.

      The same effect may be had by simply calling the :class:`TestCase`
      instance.


   .. method:: skipTest(reason)

      Calling this during a test method or :meth:`setUp` skips the current
      test.  See :ref:`unittest-skipping` for more information.

      .. versionadded:: 3.1


   .. method:: debug()

      Run the test without collecting the result.  This allows exceptions raised
      by the test to be propagated to the caller, and can be used to support
      running tests under a debugger.

   The test code can use any of the following methods to check for and report
   failures.


   .. method:: assertTrue(expr, msg=None)
               assert_(expr, msg=None)
               failUnless(expr, msg=None)

      Signal a test failure if *expr* is false; the explanation for the failure
      will be *msg* if given, otherwise it will be :const:`None`.

      .. deprecated:: 3.1
         :meth:`failUnless` and :meth:`assert_`; use :meth:`assertTrue`.


   .. method:: assertEqual(first, second, msg=None)
               failUnlessEqual(first, second, msg=None)

      Test that *first* and *second* are equal.  If the values do not compare
      equal, the test will fail with the explanation given by *msg*, or
      :const:`None`.  Note that using :meth:`assertEqual` improves upon
      doing the comparison as the first parameter to :meth:`assertTrue`: the
      default value for *msg* include representations of both *first* and
      *second*.

      In addition, if *first* and *second* are the exact same type and one of
      list, tuple, dict, set, frozenset or str or any type that a subclass
      registers with :meth:`addTypeEqualityFunc` the type specific equality
      function will be called in order to generate a more useful default
      error message.

      .. versionchanged:: 3.1
         Added the automatic calling of type specific equality function.

      .. versionchanged:: 3.2
         :meth:`assertMultiLineEqual` added as the default type equality
         function for comparing strings.

      .. deprecated:: 3.1
         :meth:`failUnlessEqual`; use :meth:`assertEqual`.


   .. method:: assertNotEqual(first, second, msg=None)
               failIfEqual(first, second, msg=None)

      Test that *first* and *second* are not equal.  If the values do compare
      equal, the test will fail with the explanation given by *msg*, or
      :const:`None`.  Note that using :meth:`assertNotEqual` improves upon doing
      the comparison as the first parameter to :meth:`assertTrue` is that the
      default value for *msg* can be computed to include representations of both
      *first* and *second*.

      .. deprecated:: 3.1
         :meth:`failIfEqual`; use :meth:`assertNotEqual`.


   .. method:: assertAlmostEqual(first, second, *, places=7, msg=None, delta=None)
               failUnlessAlmostEqual(first, second, *, places=7, msg=None, delta=None)

      Test that *first* and *second* are approximately equal by computing the
      difference, rounding to the given number of decimal *places* (default 7),
      and comparing to zero.

      Note that comparing a given number of decimal places is not the same as
      comparing a given number of significant digits. If the values do not
      compare equal, the test will fail with the explanation given by *msg*, or
      :const:`None`.

      If *delta* is supplied instead of *places* then the difference
      between *first* and *second* must be less than *delta*.

      Supplying both *delta* and *places* raises a ``TypeError``.

      .. versionchanged:: 3.2
         Objects that compare equal are automatically almost equal.
         Added the ``delta`` keyword argument.

      .. deprecated:: 3.1
         :meth:`failUnlessAlmostEqual`; use :meth:`assertAlmostEqual`.


   .. method:: assertNotAlmostEqual(first, second, *, places=7, msg=None, delta=None)
               failIfAlmostEqual(first, second, *, places=7, msg=None, delta=None)

      Test that *first* and *second* are not approximately equal by computing
      the difference, rounding to the given number of decimal *places* (default
      7), and comparing to zero.

      Note that comparing a given number of decimal places is not the same as
      comparing a given number of significant digits. If the values do not
      compare equal, the test will fail with the explanation given by *msg*, or
      :const:`None`.

      If *delta* is supplied instead of *places* then the difference
      between *first* and *second* must be more than *delta*.

      Supplying both *delta* and *places* raises a ``TypeError``.

      .. versionchanged:: 3.2
         Objects that compare equal automatically fail.  Added the ``delta``
         keyword argument.

      .. deprecated:: 3.1
         :meth:`failIfAlmostEqual`; use :meth:`assertNotAlmostEqual`.


   .. method:: assertGreater(first, second, msg=None)
               assertGreaterEqual(first, second, msg=None)
               assertLess(first, second, msg=None)
               assertLessEqual(first, second, msg=None)

      Test that *first* is respectively >, >=, < or <= than *second* depending
      on the method name.  If not, the test will fail with an explanation
      or with the explanation given by *msg*::

         >>> self.assertGreaterEqual(3, 4)
         AssertionError: "3" unexpectedly not greater than or equal to "4"

      .. versionadded:: 3.1


   .. method:: assertMultiLineEqual(self, first, second, msg=None)

      Test that the multiline string *first* is equal to the string *second*.
      When not equal a diff of the two strings highlighting the differences
      will be included in the error message. This method is used by default
      when comparing strings with :meth:`assertEqual`.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.1


   .. method:: assertRegexpMatches(text, regexp, msg=None)

      Verifies that a *regexp* search matches *text*.  Fails with an error
      message including the pattern and the *text*.  *regexp* may be
      a regular expression object or a string containing a regular expression
      suitable for use by :func:`re.search`.

      .. versionadded:: 3.1


   .. method:: assertNotRegexpMatches(text, regexp, msg=None)

      Verifies that a *regexp* search does not match *text*.  Fails with an error
      message including the pattern and the part of *text* that matches.  *regexp*
      may be a regular expression object or a string containing a regular
      expression suitable for use by :func:`re.search`.

      .. versionadded:: 3.2


   .. method:: assertIn(first, second, msg=None)
               assertNotIn(first, second, msg=None)

      Tests that *first* is or is not in *second* with an explanatory error
      message as appropriate.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.1


   .. method:: assertSameElements(actual, expected, msg=None)

      Test that sequence *expected* contains the same elements as *actual*,
      regardless of their order. When they don't, an error message listing
      the differences between the sequences will be generated.

      Duplicate elements are ignored when comparing *actual* and *expected*.
      It is the equivalent of ``assertEqual(set(expected), set(actual))``
      but it works with sequences of unhashable objects as well. Because
      duplicates are ignored, this method has been deprecated in favour of
      :meth:`assertItemsEqual`.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.1
      .. deprecated:: 3.2


   .. method:: assertItemsEqual(actual, expected, msg=None)

      Test that sequence *expected* contains the same elements as *actual*,
      regardless of their order. When they don't, an error message listing the
      differences between the sequences will be generated.

      Duplicate elements are *not* ignored when comparing *actual* and
      *expected*. It verifies if each element has the same count in both
      sequences. It is the equivalent of ``assertEqual(sorted(expected),
      sorted(actual))`` but it works with sequences of unhashable objects as
      well.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.2


   .. method:: assertSetEqual(set1, set2, msg=None)

      Tests that two sets are equal.  If not, an error message is constructed
      that lists the differences between the sets.  This method is used by
      default when comparing sets or frozensets with :meth:`assertEqual`.

      Fails if either of *set1* or *set2* does not have a :meth:`set.difference`
      method.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.1


   .. method:: assertDictEqual(expected, actual, msg=None)

      Test that two dictionaries are equal.  If not, an error message is
      constructed that shows the differences in the dictionaries. This
      method will be used by default to compare dictionaries in
      calls to :meth:`assertEqual`.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.1


   .. method:: assertDictContainsSubset(expected, actual, msg=None)

      Tests whether the key/value pairs in dictionary *actual* are a
      superset of those in *expected*.  If not, an error message listing
      the missing keys and mismatched values is generated.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.1


   .. method:: assertListEqual(list1, list2, msg=None)
               assertTupleEqual(tuple1, tuple2, msg=None)

      Tests that two lists or tuples are equal.  If not an error message is
      constructed that shows only the differences between the two.  An error
      is also raised if either of the parameters are of the wrong type.
      These methods are used by default when comparing lists or tuples with
      :meth:`assertEqual`.

      If specified, *msg* will be used as the error message on failure.

      .. versionadded:: 3.1


   .. method:: assertSequenceEqual(seq1, seq2, msg=None, seq_type=None)

      Tests that two sequences are equal.  If a *seq_type* is supplied, both
      *seq1* and *seq2* must be instances of *seq_type* or a failure will
      be raised.  If the sequences are different an error message is
      constructed that shows the difference between the two.

      If specified, *msg* will be used as the error message on failure.

      This method is used to implement :meth:`assertListEqual` and
      :meth:`assertTupleEqual`.

      .. versionadded:: 3.1


   .. method:: assertRaises(exception, callable, *args, **kwds)
               failUnlessRaises(exception, callable, *args, **kwds)
               assertRaises(exception)
               failUnlessRaises(exception)

      Test that an exception is raised when *callable* is called with any
      positional or keyword arguments that are also passed to
      :meth:`assertRaises`.  The test passes if *exception* is raised, is an
      error if another exception is raised, or fails if no exception is raised.
      To catch any of a group of exceptions, a tuple containing the exception
      classes may be passed as *exception*.

      If only the *exception* argument is given, returns a context manager so
      that the code under test can be written inline rather than as a function::

         with self.assertRaises(SomeException):
             do_something()

      The context manager will store the caught exception object in its
      :attr:`exception` attribute.  This can be useful if the intention
      is to perform additional checks on the exception raised::

         with self.assertRaises(SomeException) as cm:
             do_something()

         the_exception = cm.exception
         self.assertEqual(the_exception.error_code, 3)

      .. versionchanged:: 3.1
         Added the ability to use :meth:`assertRaises` as a context manager.

      .. versionchanged:: 3.2
         Added the :attr:`exception` attribute.

      .. deprecated:: 3.1
         :meth:`failUnlessRaises`; use :meth:`assertRaises`.


   .. method:: assertRaisesRegexp(exception, regexp[, callable, ...])

      Like :meth:`assertRaises` but also tests that *regexp* matches
      on the string representation of the raised exception.  *regexp* may be
      a regular expression object or a string containing a regular expression
      suitable for use by :func:`re.search`.  Examples::

         self.assertRaisesRegexp(ValueError, 'invalid literal for.*XYZ$',
                                 int, 'XYZ')

      or::

         with self.assertRaisesRegexp(ValueError, 'literal'):
            int('XYZ')

      .. versionadded:: 3.1


   .. method:: assertWarns(warning, callable, *args, **kwds)
               assertWarns(warning)

      Test that a warning is triggered when *callable* is called with any
      positional or keyword arguments that are also passed to
      :meth:`assertWarns`.  The test passes if *warning* is triggered and
      fails if it isn't.  Also, any unexpected exception is an error.
      To catch any of a group of warnings, a tuple containing the warning
      classes may be passed as *warnings*.

      If only the *warning* argument is given, returns a context manager so
      that the code under test can be written inline rather than as a function::

         with self.assertWarns(SomeWarning):
             do_something()

      The context manager will store the caught warning object in its
      :attr:`warning` attribute, and the source line which triggered the
      warnings in the :attr:`filename` and :attr:`lineno` attributes.
      This can be useful if the intention is to perform additional checks
      on the exception raised::

         with self.assertWarns(SomeWarning) as cm:
             do_something()

         self.assertIn('myfile.py', cm.filename)
         self.assertEqual(320, cm.lineno)

      This method works regardless of the warning filters in place when it
      is called.

      .. versionadded:: 3.2


   .. method:: assertWarnsRegexp(warning, regexp[, callable, ...])

      Like :meth:`assertWarns` but also tests that *regexp* matches on the
      message of the triggered warning.  *regexp* may be a regular expression
      object or a string containing a regular expression suitable for use
      by :func:`re.search`.  Example::

         self.assertWarnsRegexp(DeprecationWarning,
                                r'legacy_function\(\) is deprecated',
                                legacy_function, 'XYZ')

      or::

         with self.assertWarnsRegexp(RuntimeWarning, 'unsafe frobnicating'):
             frobnicate('/etc/passwd')

      .. versionadded:: 3.2


   .. method:: assertIsNone(expr, msg=None)

      This signals a test failure if *expr* is not None.

      .. versionadded:: 3.1


   .. method:: assertIsNotNone(expr, msg=None)

      The inverse of the :meth:`assertIsNone` method.
      This signals a test failure if *expr* is None.

      .. versionadded:: 3.1


   .. method:: assertIs(expr1, expr2, msg=None)

      This signals a test failure if *expr1* and *expr2* don't evaluate to the same
      object.

      .. versionadded:: 3.1


   .. method:: assertIsNot(expr1, expr2, msg=None)

      The inverse of the :meth:`assertIs` method.
      This signals a test failure if *expr1* and *expr2* evaluate to the same
      object.

      .. versionadded:: 3.1


   .. method:: assertIsInstance(obj, cls[, msg])

      This signals a test failure if *obj* is not an instance of *cls* (which
      can be a class or a tuple of classes, as supported by :func:`isinstance`).

      .. versionadded:: 3.2


   .. method:: assertNotIsInstance(obj, cls[, msg])

      The inverse of the :meth:`assertIsInstance` method.  This signals a test
      failure if *obj* is an instance of *cls*.

      .. versionadded:: 3.2


   .. method:: assertFalse(expr, msg=None)
               failIf(expr, msg=None)

      The inverse of the :meth:`assertTrue` method is the :meth:`assertFalse` method.
      This signals a test failure if *expr* is true, with *msg* or :const:`None`
      for the error message.

      .. deprecated:: 3.1
         :meth:`failIf`; use :meth:`assertFalse`.


   .. method:: fail(msg=None)

      Signals a test failure unconditionally, with *msg* or :const:`None` for
      the error message.


   .. attribute:: failureException

      This class attribute gives the exception raised by the test method.  If a
      test framework needs to use a specialized exception, possibly to carry
      additional information, it must subclass this exception in order to "play
      fair" with the framework.  The initial value of this attribute is
      :exc:`AssertionError`.


   .. attribute:: longMessage

      If set to True then any explicit failure message you pass in to the
      assert methods will be appended to the end of the normal failure message.
      The normal messages contain useful information about the objects involved,
      for example the message from assertEqual shows you the repr of the two
      unequal objects. Setting this attribute to True allows you to have a
      custom error message in addition to the normal one.

      This attribute defaults to False, meaning that a custom message passed
      to an assert method will silence the normal message.

      The class setting can be overridden in individual tests by assigning an
      instance attribute to True or False before calling the assert methods.

      .. versionadded:: 3.1


   .. attribute:: maxDiff

      This attribute controls the maximum length of diffs output by assert
      methods that report diffs on failure. It defaults to 80*8 characters.
      Assert methods affected by this attribute are
      :meth:`assertSequenceEqual` (including all the sequence comparison
      methods that delegate to it), :meth:`assertDictEqual` and
      :meth:`assertMultiLineEqual`.

      Setting ``maxDiff`` to None means that there is no maximum length of
      diffs.

      .. versionadded:: 3.2


   Testing frameworks can use the following methods to collect information on
   the test:


   .. method:: countTestCases()

      Return the number of tests represented by this test object.  For
      :class:`TestCase` instances, this will always be ``1``.


   .. method:: defaultTestResult()

      Return an instance of the test result class that should be used for this
      test case class (if no other result instance is provided to the
      :meth:`run` method).

      For :class:`TestCase` instances, this will always be an instance of
      :class:`TestResult`; subclasses of :class:`TestCase` should override this
      as necessary.


   .. method:: id()

      Return a string identifying the specific test case.  This is usually the
      full name of the test method, including the module and class name.


   .. method:: shortDescription()

      Returns a description of the test, or :const:`None` if no description
      has been provided.  The default implementation of this method
      returns the first line of the test method's docstring, if available,
      or :const:`None`.

      .. versionchanged:: 3.1,3.2
         In 3.1 this was changed to add the test name to the short description
         even in the presence of a docstring. This caused compatibility issues
         with unittest extensions and adding the test name was moved to the
         :class:`TextTestResult`.

   .. method:: addTypeEqualityFunc(typeobj, function)

      Registers a type specific :meth:`assertEqual` equality checking
      function to be called by :meth:`assertEqual` when both objects it has
      been asked to compare are exactly *typeobj* (not subclasses).
      *function* must take two positional arguments and a third msg=None
      keyword argument just as :meth:`assertEqual` does.  It must raise
      ``self.failureException`` when inequality between the first two
      parameters is detected.

      One good use of custom equality checking functions for a type
      is to raise ``self.failureException`` with an error message useful
      for debugging the problem by explaining the inequalities in detail.

      .. versionadded:: 3.1


   .. method:: addCleanup(function, *args, **kwargs)

      Add a function to be called after :meth:`tearDown` to cleanup resources
      used during the test. Functions will be called in reverse order to the
      order they are added (LIFO). They are called with any arguments and
      keyword arguments passed into :meth:`addCleanup` when they are
      added.

      If :meth:`setUp` fails, meaning that :meth:`tearDown` is not called,
      then any cleanup functions added will still be called.

      .. versionadded:: 3.2


   .. method:: doCleanups()

      This method is called unconditionally after :meth:`tearDown`, or
      after :meth:`setUp` if :meth:`setUp` raises an exception.

      It is responsible for calling all the cleanup functions added by
      :meth:`addCleanup`. If you need cleanup functions to be called
      *prior* to :meth:`tearDown` then you can call :meth:`doCleanups`
      yourself.

      :meth:`doCleanups` pops methods off the stack of cleanup
      functions one at a time, so it can be called at any time.

      .. versionadded:: 3.2


.. class:: FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)

   This class implements the portion of the :class:`TestCase` interface which
   allows the test runner to drive the test, but does not provide the methods
   which test code can use to check and report errors.  This is used to create
   test cases using legacy test code, allowing it to be integrated into a
   :mod:`unittest`-based test framework.


.. _testsuite-objects:

Grouping tests
~~~~~~~~~~~~~~

.. class:: TestSuite(tests=())

   This class represents an aggregation of individual tests cases and test suites.
   The class presents the interface needed by the test runner to allow it to be run
   as any other test case.  Running a :class:`TestSuite` instance is the same as
   iterating over the suite, running each test individually.

   If *tests* is given, it must be an iterable of individual test cases or other
   test suites that will be used to build the suite initially. Additional methods
   are provided to add test cases and suites to the collection later on.

   :class:`TestSuite` objects behave much like :class:`TestCase` objects, except
   they do not actually implement a test.  Instead, they are used to aggregate
   tests into groups of tests that should be run together. Some additional
   methods are available to add tests to :class:`TestSuite` instances:


   .. method:: TestSuite.addTest(test)

      Add a :class:`TestCase` or :class:`TestSuite` to the suite.


   .. method:: TestSuite.addTests(tests)

      Add all the tests from an iterable of :class:`TestCase` and :class:`TestSuite`
      instances to this test suite.

      This is equivalent to iterating over *tests*, calling :meth:`addTest` for
      each element.

   :class:`TestSuite` shares the following methods with :class:`TestCase`:


   .. method:: run(result)

      Run the tests associated with this suite, collecting the result into the
      test result object passed as *result*.  Note that unlike
      :meth:`TestCase.run`, :meth:`TestSuite.run` requires the result object to
      be passed in.


   .. method:: debug()

      Run the tests associated with this suite without collecting the
      result. This allows exceptions raised by the test to be propagated to the
      caller and can be used to support running tests under a debugger.


   .. method:: countTestCases()

      Return the number of tests represented by this test object, including all
      individual tests and sub-suites.


   .. method:: __iter__()

      Tests grouped by a :class:`TestSuite` are always accessed by iteration.
      Subclasses can lazily provide tests by overriding :meth:`__iter__`. Note
      that this method maybe called several times on a single suite
      (for example when counting tests or comparing for equality)
      so the tests returned must be the same for repeated iterations.

      .. versionchanged:: 3.2
         In earlier versions the :class:`TestSuite` accessed tests directly rather
         than through iteration, so overriding :meth:`__iter__` wasn't sufficient
         for providing tests.

   In the typical usage of a :class:`TestSuite` object, the :meth:`run` method
   is invoked by a :class:`TestRunner` rather than by the end-user test harness.


Loading and running tests
~~~~~~~~~~~~~~~~~~~~~~~~~

.. class:: TestLoader()

   The :class:`TestLoader` class is used to create test suites from classes and
   modules.  Normally, there is no need to create an instance of this class; the
   :mod:`unittest` module provides an instance that can be shared as
   ``unittest.defaultTestLoader``. Using a subclass or instance, however, allows
   customization of some configurable properties.

   :class:`TestLoader` objects have the following methods:

a
   .. method:: loadTestsFromTestCase(testCaseClass)

      Return a suite of all tests cases contained in the :class:`TestCase`\ -derived
      :class:`testCaseClass`.


   .. method:: loadTestsFromModule(module)

      Return a suite of all tests cases contained in the given module. This
      method searches *module* for classes derived from :class:`TestCase` and
      creates an instance of the class for each test method defined for the
      class.

      .. note::

         While using a hierarchy of :class:`TestCase`\ -derived classes can be
         convenient in sharing fixtures and helper functions, defining test
         methods on base classes that are not intended to be instantiated
         directly does not play well with this method.  Doing so, however, can
         be useful when the fixtures are different and defined in subclasses.

      If a module provides a ``load_tests`` function it will be called to
      load the tests. This allows modules to customize test loading.
      This is the `load_tests protocol`_.

      .. versionchanged:: 3.2
         Support for ``load_tests`` added.


   .. method:: loadTestsFromName(name, module=None)

      Return a suite of all tests cases given a string specifier.

      The specifier *name* is a "dotted name" that may resolve either to a
      module, a test case class, a test method within a test case class, a
      :class:`TestSuite` instance, or a callable object which returns a
      :class:`TestCase` or :class:`TestSuite` instance.  These checks are
      applied in the order listed here; that is, a method on a possible test
      case class will be picked up as "a test method within a test case class",
      rather than "a callable object".

      For example, if you have a module :mod:`SampleTests` containing a
      :class:`TestCase`\ -derived class :class:`SampleTestCase` with three test
      methods (:meth:`test_one`, :meth:`test_two`, and :meth:`test_three`), the
      specifier ``'SampleTests.SampleTestCase'`` would cause this method to
      return a suite which will run all three test methods. Using the specifier
      ``'SampleTests.SampleTestCase.test_two'`` would cause it to return a test
      suite which will run only the :meth:`test_two` test method. The specifier
      can refer to modules and packages which have not been imported; they will
      be imported as a side-effect.

      The method optionally resolves *name* relative to the given *module*.


   .. method:: loadTestsFromNames(names, module=None)

      Similar to :meth:`loadTestsFromName`, but takes a sequence of names rather
      than a single name.  The return value is a test suite which supports all
      the tests defined for each name.


   .. method:: getTestCaseNames(testCaseClass)

      Return a sorted sequence of method names found within *testCaseClass*;
      this should be a subclass of :class:`TestCase`.


   .. method:: discover(start_dir, pattern='test*.py', top_level_dir=None)

      Find and return all test modules from the specified start directory,
      recursing into subdirectories to find them. Only test files that match
      *pattern* will be loaded. (Using shell style pattern matching.) Only
      module names that are importable (i.e. are valid Python identifiers) will
      be loaded.

      All test modules must be importable from the top level of the project. If
      the start directory is not the top level directory then the top level
      directory must be specified separately.

      If importing a module fails, for example due to a syntax error, then this
      will be recorded as a single error and discovery will continue.

      If a test package name (directory with :file:`__init__.py`) matches the
      pattern then the package will be checked for a ``load_tests``
      function. If this exists then it will be called with *loader*, *tests*,
      *pattern*.

      If load_tests exists then discovery does *not* recurse into the package,
      ``load_tests`` is responsible for loading all tests in the package.

      The pattern is deliberately not stored as a loader attribute so that
      packages can continue discovery themselves. *top_level_dir* is stored so
      ``load_tests`` does not need to pass this argument in to
      ``loader.discover()``.

      *start_dir* can be a dotted module name as well as a directory.

      .. versionadded:: 3.2


   The following attributes of a :class:`TestLoader` can be configured either by
   subclassing or assignment on an instance:


   .. attribute:: testMethodPrefix

      String giving the prefix of method names which will be interpreted as test
      methods.  The default value is ``'test'``.

      This affects :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*`
      methods.


   .. attribute:: sortTestMethodsUsing

      Function to be used to compare method names when sorting them in
      :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` methods.


   .. attribute:: suiteClass

      Callable object that constructs a test suite from a list of tests. No
      methods on the resulting object are needed.  The default value is the
      :class:`TestSuite` class.

      This affects all the :meth:`loadTestsFrom\*` methods.


.. class:: TestResult

   This class is used to compile information about which tests have succeeded
   and which have failed.

   A :class:`TestResult` object stores the results of a set of tests.  The
   :class:`TestCase` and :class:`TestSuite` classes ensure that results are
   properly recorded; test authors do not need to worry about recording the
   outcome of tests.

   Testing frameworks built on top of :mod:`unittest` may want access to the
   :class:`TestResult` object generated by running a set of tests for reporting
   purposes; a :class:`TestResult` instance is returned by the
   :meth:`TestRunner.run` method for this purpose.

   :class:`TestResult` instances have the following attributes that will be of
   interest when inspecting the results of running a set of tests:


   .. attribute:: errors

      A list containing 2-tuples of :class:`TestCase` instances and strings
      holding formatted tracebacks. Each tuple represents a test which raised an
      unexpected exception.

   .. attribute:: failures

      A list containing 2-tuples of :class:`TestCase` instances and strings
      holding formatted tracebacks. Each tuple represents a test where a failure
      was explicitly signalled using the :meth:`TestCase.fail\*` or
      :meth:`TestCase.assert\*` methods.

   .. attribute:: skipped

      A list containing 2-tuples of :class:`TestCase` instances and strings
      holding the reason for skipping the test.

      .. versionadded:: 3.1

   .. attribute:: expectedFailures

      A list contaning 2-tuples of :class:`TestCase` instances and strings
      holding formatted tracebacks.  Each tuple represents a expected failures
      of the test case.

   .. attribute:: unexpectedSuccesses

      A list containing :class:`TestCase` instances that were marked as expected
      failures, but succeeded.

   .. attribute:: shouldStop

      Set to ``True`` when the execution of tests should stop by :meth:`stop`.


   .. attribute:: testsRun

      The total number of tests run so far.


   .. attribute:: buffer

      If set to true, ``sys.stdout`` and ``sys.stderr`` will be buffered in between
      :meth:`startTest` and :meth:`stopTest` being called. Collected output will
      only be echoed onto the real ``sys.stdout`` and ``sys.stderr`` if the test
      fails or errors. Any output is also attached to the failure / error message.

      .. versionadded:: 3.2


   .. attribute:: failfast

      If set to true :meth:`stop` will be called on the first failure or error,
      halting the test run.

      .. versionadded:: 3.2


   .. method:: wasSuccessful()

      Return :const:`True` if all tests run so far have passed, otherwise returns
      :const:`False`.


   .. method:: stop()

      This method can be called to signal that the set of tests being run should
      be aborted by setting the :attr:`shouldStop` attribute to :const:`True`.
      :class:`TestRunner` objects should respect this flag and return without
      running any additional tests.

      For example, this feature is used by the :class:`TextTestRunner` class to
      stop the test framework when the user signals an interrupt from the
      keyboard.  Interactive tools which provide :class:`TestRunner`
      implementations can use this in a similar manner.

   The following methods of the :class:`TestResult` class are used to maintain
   the internal data structures, and may be extended in subclasses to support
   additional reporting requirements.  This is particularly useful in building
   tools which support interactive reporting while tests are being run.


   .. method:: startTest(test)

      Called when the test case *test* is about to be run.

   .. method:: stopTest(test)

      Called after the test case *test* has been executed, regardless of the
      outcome.

   .. method:: startTestRun(test)

      Called once before any tests are executed.

      .. versionadded:: 3.2


   .. method:: stopTestRun(test)

      Called once after all tests are executed.

      .. versionadded:: 3.2


   .. method:: addError(test, err)

      Called when the test case *test* raises an unexpected exception *err* is a
      tuple of the form returned by :func:`sys.exc_info`: ``(type, value,
      traceback)``.

      The default implementation appends a tuple ``(test, formatted_err)`` to
      the instance's :attr:`errors` attribute, where *formatted_err* is a
      formatted traceback derived from *err*.


   .. method:: addFailure(test, err)

      Called when the test case *test* signals a failure. *err* is a tuple of
      the form returned by :func:`sys.exc_info`: ``(type, value, traceback)``.

      The default implementation appends a tuple ``(test, formatted_err)`` to
      the instance's :attr:`failures` attribute, where *formatted_err* is a
      formatted traceback derived from *err*.


   .. method:: addSuccess(test)

      Called when the test case *test* succeeds.

      The default implementation does nothing.


   .. method:: addSkip(test, reason)

      Called when the test case *test* is skipped.  *reason* is the reason the
      test gave for skipping.

      The default implementation appends a tuple ``(test, reason)`` to the
      instance's :attr:`skipped` attribute.


   .. method:: addExpectedFailure(test, err)

      Called when the test case *test* fails, but was marked with the
      :func:`expectedFailure` decorator.

      The default implementation appends a tuple ``(test, formatted_err)`` to
      the instance's :attr:`expectedFailures` attribute, where *formatted_err*
      is a formatted traceback derived from *err*.


   .. method:: addUnexpectedSuccess(test)

      Called when the test case *test* was marked with the
      :func:`expectedFailure` decorator, but succeeded.

      The default implementation appends the test to the instance's
      :attr:`unexpectedSuccesses` attribute.


.. class:: TextTestResult(stream, descriptions, verbosity)

   A concrete implementation of :class:`TestResult` used by the
   :class:`TextTestRunner`.

   .. versionadded:: 3.2
      This class was previously named ``_TextTestResult``. The old name still
      exists as an alias but is deprecated.


.. data:: defaultTestLoader

   Instance of the :class:`TestLoader` class intended to be shared.  If no
   customization of the :class:`TestLoader` is needed, this instance can be used
   instead of repeatedly creating new instances.


.. class:: TextTestRunner(stream=sys.stderr, descriptions=True, verbosity=1, runnerclass=None)

   A basic test runner implementation which prints results on standard error.  It
   has a few configurable parameters, but is essentially very simple.  Graphical
   applications which run test suites should provide alternate implementations.

   .. method:: _makeResult()

      This method returns the instance of ``TestResult`` used by :meth:`run`.
      It is not intended to be called directly, but can be overridden in
      subclasses to provide a custom ``TestResult``.

      ``_makeResult()`` instantiates the class or callable passed in the
      ``TextTestRunner`` constructor as the ``resultclass`` argument. It
      defaults to :class:`TextTestResult` if no ``resultclass`` is provided.
      The result class is instantiated with the following arguments::

        stream, descriptions, verbosity

.. function:: main(module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=unittest.loader.defaultTestLoader, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None)

   A command-line program that runs a set of tests; this is primarily for making
   test modules conveniently executable.  The simplest use for this function is to
   include the following line at the end of a test script::

      if __name__ == '__main__':
          unittest.main()

   You can run tests with more detailed information by passing in the verbosity
   argument::

      if __name__ == '__main__':
          unittest.main(verbosity=2)

   The *testRunner* argument can either be a test runner class or an already
   created instance of it. By default ``main`` calls :func:`sys.exit` with
   an exit code indicating success or failure of the tests run.

   ``main`` supports being used from the interactive interpreter by passing in the
   argument ``exit=False``. This displays the result on standard output without
   calling :func:`sys.exit`::

      >>> from unittest import main
      >>> main(module='test_module', exit=False)

   The ``failfast``, ``catchbreak`` and ``buffer`` parameters have the same
   effect as the `failfast, catch and buffer command line options`_.

   Calling ``main`` actually returns an instance of the ``TestProgram`` class.
   This stores the result of the tests run as the ``result`` attribute.

   .. versionchanged:: 3.2
      The ``exit``, ``verbosity``, ``failfast``, ``catchbreak`` and ``buffer``
      parameters were added.


load_tests Protocol
###################


.. versionadded:: 3.2


Modules or packages can customize how tests are loaded from them during normal
test runs or test discovery by implementing a function called ``load_tests``.

If a test module defines ``load_tests`` it will be called by
:meth:`TestLoader.loadTestsFromModule` with the following arguments::

    load_tests(loader, standard_tests, None)

It should return a :class:`TestSuite`.

*loader* is the instance of :class:`TestLoader` doing the loading.
*standard_tests* are the tests that would be loaded by default from the
module. It is common for test modules to only want to add or remove tests
from the standard set of tests.
The third argument is used when loading packages as part of test discovery.

A typical ``load_tests`` function that loads tests from a specific set of
:class:`TestCase` classes may look like::

    test_cases = (TestCase1, TestCase2, TestCase3)

    def load_tests(loader, tests, pattern):
        suite = TestSuite()
        for test_class in test_cases:
            tests = loader.loadTestsFromTestCase(test_class)
            suite.addTests(tests)
        return suite

If discovery is started, either from the command line or by calling
:meth:`TestLoader.discover`, with a pattern that matches a package
name then the package :file:`__init__.py` will be checked for ``load_tests``.

.. note::

   The default pattern is 'test*.py'. This matches all Python files
   that start with 'test' but *won't* match any test directories.

   A pattern like 'test*' will match test packages as well as
   modules.

If the package :file:`__init__.py` defines ``load_tests`` then it will be
called and discovery not continued into the package. ``load_tests``
is called with the following arguments::

    load_tests(loader, standard_tests, pattern)

This should return a :class:`TestSuite` representing all the tests
from the package. (``standard_tests`` will only contain tests
collected from :file:`__init__.py`.)

Because the pattern is passed into ``load_tests`` the package is free to
continue (and potentially modify) test discovery. A 'do nothing'
``load_tests`` function for a test package would look like::

    def load_tests(loader, standard_tests, pattern):
        # top level directory cached on loader instance
        this_dir = os.path.dirname(__file__)
        package_tests = loader.discover(start_dir=this_dir, pattern=pattern)
        standard_tests.addTests(package_tests)
        return standard_tests


Class and Module Fixtures
-------------------------

Class and module level fixtures are implemented in :class:`TestSuite`. When
the test suite encounters a test from a new class then :meth:`tearDownClass`
from the previous class (if there is one) is called, followed by
:meth:`setUpClass` from the new class.

Similarly if a test is from a different module from the previous test then
``tearDownModule`` from the previous module is run, followed by
``setUpModule`` from the new module.

After all the tests have run the final ``tearDownClass`` and
``tearDownModule`` are run.

Note that shared fixtures do not play well with [potential] features like test
parallelization and they break test isolation. They should be used with care.

The default ordering of tests created by the unittest test loaders is to group
all tests from the same modules and classes together. This will lead to
``setUpClass`` / ``setUpModule`` (etc) being called exactly once per class and
module. If you randomize the order, so that tests from different modules and
classes are adjacent to each other, then these shared fixture functions may be
called multiple times in a single test run.

Shared fixtures are not intended to work with suites with non-standard
ordering. A ``BaseTestSuite`` still exists for frameworks that don't want to
support shared fixtures.

If there are any exceptions raised during one of the shared fixture functions
the test is reported as an error. Because there is no corresponding test
instance an ``_ErrorHolder`` object (that has the same interface as a
:class:`TestCase`) is created to represent the error. If you are just using
the standard unittest test runner then this detail doesn't matter, but if you
are a framework author it may be relevant.


setUpClass and tearDownClass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

These must be implemented as class methods::

    import unittest

    class Test(unittest.TestCase):
        @classmethod
        def setUpClass(cls):
            cls._connection = createExpensiveConnectionObject()

        @classmethod
        def tearDownClass(cls):
            cls._connection.destroy()

If you want the ``setUpClass`` and ``tearDownClass`` on base classes called
then you must call up to them yourself. The implementations in
:class:`TestCase` are empty.

If an exception is raised during a ``setUpClass`` then the tests in the class
are not run and the ``tearDownClass`` is not run. Skipped classes will not
have ``setUpClass`` or ``tearDownClass`` run. If the exception is a
``SkipTest`` exception then the class will be reported as having been skipped
instead of as an error.


setUpModule and tearDownModule
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

These should be implemented as functions::

    def setUpModule():
        createConnection()

    def tearDownModule():
        closeConnection()

If an exception is raised in a ``setUpModule`` then none of the tests in the
module will be run and the ``tearDownModule`` will not be run. If the exception is a
``SkipTest`` exception then the module will be reported as having been skipped
instead of as an error.


Signal Handling
---------------

The :option:`-c`/:option:`--catch` command line option to unittest, along with the ``catchbreak``
parameter to :func:`unittest.main()`, provide more friendly handling of
control-C during a test run. With catch break behavior enabled control-C will
allow the currently running test to complete, and the test run will then end
and report all the results so far. A second control-c will raise a
:exc:`KeyboardInterrupt` in the usual way.

The control-c handling signal handler attempts to remain compatible with code or
tests that install their own :const:`signal.SIGINT` handler. If the ``unittest``
handler is called but *isn't* the installed :const:`signal.SIGINT` handler,
i.e. it has been replaced by the system under test and delegated to, then it
calls the default handler. This will normally be the expected behavior by code
that replaces an installed handler and delegates to it. For individual tests
that need ``unittest`` control-c handling disabled the :func:`removeHandler`
decorator can be used.

There are a few utility functions for framework authors to enable control-c
handling functionality within test frameworks.

.. function:: installHandler()

   Install the control-c handler. When a :const:`signal.SIGINT` is received
   (usually in response to the user pressing control-c) all registered results
   have :meth:`~TestResult.stop` called.

   .. versionadded:: 3.2

.. function:: registerResult(result)

   Register a :class:`TestResult` object for control-c handling. Registering a
   result stores a weak reference to it, so it doesn't prevent the result from
   being garbage collected.

   Registering a :class:`TestResult` object has no side-effects if control-c
   handling is not enabled, so test frameworks can unconditionally register
   all results they create independently of whether or not handling is enabled.

   .. versionadded:: 3.2

.. function:: removeResult(result)

   Remove a registered result. Once a result has been removed then
   :meth:`~TestResult.stop` will no longer be called on that result object in
   response to a control-c.

   .. versionadded:: 3.2

.. function:: removeHandler(function=None)

   When called without arguments this function removes the control-c handler
   if it has been installed. This function can also be used as a test decorator
   to temporarily remove the handler whilst the test is being executed::

      @unittest.removeHandler
      def test_signal_handling(self):
          ...

   .. versionadded:: 3.2

&id=0010cbdd14ce167857ae9eb8f539ad7b1205542a'>examples/declarative/border-image/content/colors.pngbin0 -> 1655 bytes-rw-r--r--examples/declarative/clocks/clocks.qml15
-rw-r--r--examples/declarative/clocks/content/Clock.qml80
-rw-r--r--examples/declarative/clocks/content/background.pngbin0 -> 46895 bytes-rwxr-xr-xexamples/declarative/clocks/content/center.pngbin0 -> 765 bytes-rwxr-xr-xexamples/declarative/clocks/content/clock-night.pngbin0 -> 23359 bytes-rwxr-xr-xexamples/declarative/clocks/content/clock.pngbin0 -> 20653 bytes-rwxr-xr-xexamples/declarative/clocks/content/hour.pngbin0 -> 625 bytes-rwxr-xr-xexamples/declarative/clocks/content/minute.pngbin0 -> 625 bytes-rwxr-xr-xexamples/declarative/clocks/content/second.pngbin0 -> 303 bytes-rw-r--r--examples/declarative/connections/connections.qml31
-rw-r--r--examples/declarative/connections/content/Button.qml12
-rw-r--r--examples/declarative/connections/content/bg1.jpgbin0 -> 23771 bytes-rw-r--r--examples/declarative/connections/content/rotate-left.pngbin0 -> 3061 bytes-rw-r--r--examples/declarative/connections/content/rotate-right.pngbin0 -> 3115 bytes-rw-r--r--examples/declarative/dial/content/Dial.qml37
-rw-r--r--examples/declarative/dial/content/background.pngbin0 -> 35876 bytes-rw-r--r--examples/declarative/dial/content/needle.pngbin0 -> 342 bytes-rw-r--r--examples/declarative/dial/content/needle_shadow.pngbin0 -> 632 bytes-rw-r--r--examples/declarative/dial/content/overlay.pngbin0 -> 3564 bytes-rw-r--r--examples/declarative/dial/dial.qml35
-rw-r--r--examples/declarative/dynamic/dynamic.qml117
-rw-r--r--examples/declarative/dynamic/images/NOTE1
-rw-r--r--examples/declarative/dynamic/images/face-smile.pngbin0 -> 15408 bytes-rw-r--r--examples/declarative/dynamic/images/moon.pngbin0 -> 1757 bytes-rw-r--r--examples/declarative/dynamic/images/rabbit_brown.pngbin0 -> 1245 bytes-rw-r--r--examples/declarative/dynamic/images/rabbit_bw.pngbin0 -> 1759 bytes-rw-r--r--examples/declarative/dynamic/images/star.pngbin0 -> 349 bytes-rw-r--r--examples/declarative/dynamic/images/sun.pngbin0 -> 8153 bytes-rw-r--r--examples/declarative/dynamic/images/tree_s.pngbin0 -> 3406 bytes-rw-r--r--examples/declarative/dynamic/qml/Button.qml24
-rw-r--r--examples/declarative/dynamic/qml/GenericItem.qml13
-rw-r--r--examples/declarative/dynamic/qml/PaletteItem.qml13
-rw-r--r--examples/declarative/dynamic/qml/PerspectiveItem.qml15
-rw-r--r--examples/declarative/dynamic/qml/Sun.qml24
-rw-r--r--examples/declarative/dynamic/qml/itemCreation.js82
-rw-r--r--examples/declarative/effects/effects.qml60
-rw-r--r--examples/declarative/effects/pic.pngbin0 -> 12933 bytes-rw-r--r--examples/declarative/extending/adding/adding.pro11
-rw-r--r--examples/declarative/extending/adding/adding.qrc5
-rw-r--r--examples/declarative/extending/adding/example.qml8
-rw-r--r--examples/declarative/extending/adding/main.cpp62
-rw-r--r--examples/declarative/extending/adding/person.cpp70
-rw-r--r--examples/declarative/extending/adding/person.h67
-rw-r--r--examples/declarative/extending/attached/attached.pro13
-rw-r--r--examples/declarative/extending/attached/attached.qrc5
-rw-r--r--examples/declarative/extending/attached/birthdayparty.cpp85
-rw-r--r--examples/declarative/extending/attached/birthdayparty.h87
-rw-r--r--examples/declarative/extending/attached/example.qml29
-rw-r--r--examples/declarative/extending/attached/main.cpp84
-rw-r--r--examples/declarative/extending/attached/person.cpp123
-rw-r--r--examples/declarative/extending/attached/person.h107
-rw-r--r--examples/declarative/extending/binding/binding.pro15
-rw-r--r--examples/declarative/extending/binding/binding.qrc5
-rw-r--r--examples/declarative/extending/binding/birthdayparty.cpp106
-rw-r--r--examples/declarative/extending/binding/birthdayparty.h103
-rw-r--r--examples/declarative/extending/binding/example.qml37
-rw-r--r--examples/declarative/extending/binding/happybirthday.cpp87
-rw-r--r--examples/declarative/extending/binding/happybirthday.h76
-rw-r--r--examples/declarative/extending/binding/main.cpp85
-rw-r--r--examples/declarative/extending/binding/person.cpp143
-rw-r--r--examples/declarative/extending/binding/person.h115
-rw-r--r--examples/declarative/extending/coercion/birthdayparty.cpp63
-rw-r--r--examples/declarative/extending/coercion/birthdayparty.h69
-rw-r--r--examples/declarative/extending/coercion/coercion.pro13
-rw-r--r--examples/declarative/extending/coercion/coercion.qrc5
-rw-r--r--examples/declarative/extending/coercion/example.qml15
-rw-r--r--examples/declarative/extending/coercion/main.cpp70
-rw-r--r--examples/declarative/extending/coercion/person.cpp86
-rw-r--r--examples/declarative/extending/coercion/person.h81
-rw-r--r--examples/declarative/extending/default/birthdayparty.cpp63
-rw-r--r--examples/declarative/extending/default/birthdayparty.h70
-rw-r--r--examples/declarative/extending/default/default.pro13
-rw-r--r--examples/declarative/extending/default/default.qrc5
-rw-r--r--examples/declarative/extending/default/example.qml14
-rw-r--r--examples/declarative/extending/default/main.cpp70
-rw-r--r--examples/declarative/extending/default/person.cpp82
-rw-r--r--examples/declarative/extending/default/person.h79
-rw-r--r--examples/declarative/extending/extended/example.qml7
-rw-r--r--examples/declarative/extending/extended/extended.pro11
-rw-r--r--examples/declarative/extending/extended/extended.qrc5
-rw-r--r--examples/declarative/extending/extended/lineedit.cpp106
-rw-r--r--examples/declarative/extending/extended/lineedit.h74
-rw-r--r--examples/declarative/extending/extended/main.cpp62
-rw-r--r--examples/declarative/extending/grouped/birthdayparty.cpp63
-rw-r--r--examples/declarative/extending/grouped/birthdayparty.h68
-rw-r--r--examples/declarative/extending/grouped/example.qml33
-rw-r--r--examples/declarative/extending/grouped/grouped.pro13
-rw-r--r--examples/declarative/extending/grouped/grouped.qrc5
-rw-r--r--examples/declarative/extending/grouped/main.cpp80
-rw-r--r--examples/declarative/extending/grouped/person.cpp123
-rw-r--r--examples/declarative/extending/grouped/person.h109
-rw-r--r--examples/declarative/extending/properties/birthdayparty.cpp65
-rw-r--r--examples/declarative/extending/properties/birthdayparty.h75
-rw-r--r--examples/declarative/extending/properties/example.qml15
-rw-r--r--examples/declarative/extending/properties/main.cpp66
-rw-r--r--examples/declarative/extending/properties/person.cpp68
-rw-r--r--examples/declarative/extending/properties/person.h65
-rw-r--r--examples/declarative/extending/properties/properties.pro13
-rw-r--r--examples/declarative/extending/properties/properties.qrc5
-rw-r--r--examples/declarative/extending/signal/birthdayparty.cpp91
-rw-r--r--examples/declarative/extending/signal/birthdayparty.h94
-rw-r--r--examples/declarative/extending/signal/example.qml32
-rw-r--r--examples/declarative/extending/signal/main.cpp85
-rw-r--r--examples/declarative/extending/signal/person.cpp123
-rw-r--r--examples/declarative/extending/signal/person.h107
-rw-r--r--examples/declarative/extending/signal/signal.pro13
-rw-r--r--examples/declarative/extending/signal/signal.qrc5
-rw-r--r--examples/declarative/extending/valuesource/birthdayparty.cpp101
-rw-r--r--examples/declarative/extending/valuesource/birthdayparty.h99
-rw-r--r--examples/declarative/extending/valuesource/example.qml36
-rw-r--r--examples/declarative/extending/valuesource/happybirthday.cpp82
-rw-r--r--examples/declarative/extending/valuesource/happybirthday.h79
-rw-r--r--examples/declarative/extending/valuesource/main.cpp85
-rw-r--r--examples/declarative/extending/valuesource/person.cpp123
-rw-r--r--examples/declarative/extending/valuesource/person.h107
-rw-r--r--examples/declarative/extending/valuesource/valuesource.pro15
-rw-r--r--examples/declarative/extending/valuesource/valuesource.qrc5
-rw-r--r--examples/declarative/fillmode/face.pngbin0 -> 905 bytes-rw-r--r--examples/declarative/fillmode/fillmode.qml41
-rw-r--r--examples/declarative/focusscope/test.qml76
-rw-r--r--examples/declarative/focusscope/test2.qml40
-rw-r--r--examples/declarative/focusscope/test3.qml52
-rw-r--r--examples/declarative/focusscope/test4.qml75
-rw-r--r--examples/declarative/fonts/banner.qml18
-rw-r--r--examples/declarative/fonts/fonts.qml69
-rw-r--r--examples/declarative/fonts/fonts/tarzeau_ocr_a.ttfbin0 -> 24544 bytes-rw-r--r--examples/declarative/fonts/hello.qml27
-rw-r--r--examples/declarative/gridview/gridview.qml38
-rw-r--r--examples/declarative/gridview/pics/AddressBook_48.pngbin0 -> 3350 bytes-rw-r--r--examples/declarative/gridview/pics/AudioPlayer_48.pngbin0 -> 3806 bytes-rw-r--r--examples/declarative/gridview/pics/Camera_48.pngbin0 -> 3540 bytes-rw-r--r--examples/declarative/gridview/pics/DateBook_48.pngbin0 -> 2610 bytes-rw-r--r--examples/declarative/gridview/pics/EMail_48.pngbin0 -> 3655 bytes-rw-r--r--examples/declarative/gridview/pics/TodoList_48.pngbin0 -> 3429 bytes-rw-r--r--examples/declarative/gridview/pics/VideoPlayer_48.pngbin0 -> 4151 bytes-rw-r--r--examples/declarative/layouts/Button.qml22
-rw-r--r--examples/declarative/layouts/add.pngbin0 -> 1577 bytes-rw-r--r--examples/declarative/layouts/del.pngbin0 -> 1661 bytes-rw-r--r--examples/declarative/layouts/layouts.qml31
-rw-r--r--examples/declarative/layouts/positioners.qml163
-rw-r--r--examples/declarative/listview/content/ClickAutoRepeating.qml30
-rw-r--r--examples/declarative/listview/content/MediaButton.qml35
-rw-r--r--examples/declarative/listview/content/pics/add.pngbin0 -> 1577 bytes-rw-r--r--examples/declarative/listview/content/pics/archive-insert.pngbin0 -> 896 bytes-rw-r--r--examples/declarative/listview/content/pics/archive-remove.pngbin0 -> 1074 bytes-rw-r--r--examples/declarative/listview/content/pics/button-pressed.pngbin0 -> 571 bytes-rw-r--r--examples/declarative/listview/content/pics/button.pngbin0 -> 564 bytes-rw-r--r--examples/declarative/listview/content/pics/del.pngbin0 -> 1661 bytes-rw-r--r--examples/declarative/listview/content/pics/fruit-salad.jpgbin0 -> 17952 bytes-rw-r--r--examples/declarative/listview/content/pics/go-down.pngbin0 -> 892 bytes-rw-r--r--examples/declarative/listview/content/pics/go-up.pngbin0 -> 929 bytes-rw-r--r--examples/declarative/listview/content/pics/hamburger.jpgbin0 -> 8572 bytes-rw-r--r--examples/declarative/listview/content/pics/lemonade.jpgbin0 -> 6645 bytes-rw-r--r--examples/declarative/listview/content/pics/list-add.pngbin0 -> 907 bytes-rw-r--r--examples/declarative/listview/content/pics/list-remove.pngbin0 -> 498 bytes-rw-r--r--examples/declarative/listview/content/pics/moreDown.pngbin0 -> 217 bytes-rw-r--r--examples/declarative/listview/content/pics/moreUp.pngbin0 -> 212 bytes-rw-r--r--examples/declarative/listview/content/pics/pancakes.jpgbin0 -> 9163 bytes-rw-r--r--examples/declarative/listview/content/pics/trash.pngbin0 -> 989 bytes-rw-r--r--examples/declarative/listview/content/pics/vegetable-soup.jpgbin0 -> 8639 bytes-rw-r--r--examples/declarative/listview/dummydata/MyPetsModel.qml61
-rw-r--r--examples/declarative/listview/dummydata/Recipes.qml90
-rw-r--r--examples/declarative/listview/dynamic.qml160
-rw-r--r--examples/declarative/listview/highlight.qml57
-rw-r--r--examples/declarative/listview/itemlist.qml60
-rw-r--r--examples/declarative/listview/listview.qml77
-rw-r--r--examples/declarative/listview/recipes.qml140
-rw-r--r--examples/declarative/listview/sections.qml67
-rw-r--r--examples/declarative/mouseregion/mouse.qml40
-rw-r--r--examples/declarative/objectlistmodel/dataobject.cpp73
-rw-r--r--examples/declarative/objectlistmodel/dataobject.h69
-rw-r--r--examples/declarative/objectlistmodel/main.cpp78
-rw-r--r--examples/declarative/objectlistmodel/objectlistmodel.pro11
-rw-r--r--examples/declarative/objectlistmodel/objectlistmodel.qrc5
-rw-r--r--examples/declarative/objectlistmodel/view.qml16
-rw-r--r--examples/declarative/parallax/parallax.qml41
-rw-r--r--examples/declarative/parallax/pics/background.jpgbin0 -> 209814 bytes-rw-r--r--examples/declarative/parallax/pics/face-smile.pngbin0 -> 15408 bytes-rw-r--r--examples/declarative/parallax/pics/home-page.svg445
-rw-r--r--examples/declarative/parallax/pics/shadow.pngbin0 -> 425 bytes-rw-r--r--examples/declarative/parallax/pics/yast-joystick.pngbin0 -> 2723 bytes-rw-r--r--examples/declarative/parallax/pics/yast-wol.pngbin0 -> 3769 bytes-rw-r--r--examples/declarative/parallax/qml/ParallaxView.qml83
-rw-r--r--examples/declarative/parallax/qml/Smiley.qml47
-rw-r--r--examples/declarative/plugins/README9
-rw-r--r--examples/declarative/plugins/files/Clock.qml50
-rw-r--r--examples/declarative/plugins/files/center.pngbin0 -> 765 bytes-rw-r--r--examples/declarative/plugins/files/clock.pngbin0 -> 20653 bytes-rw-r--r--examples/declarative/plugins/files/hour.pngbin0 -> 625 bytes-rw-r--r--examples/declarative/plugins/files/minute.pngbin0 -> 625 bytes-rw-r--r--examples/declarative/plugins/plugin.cpp161
-rw-r--r--examples/declarative/plugins/plugins.pro15
-rw-r--r--examples/declarative/plugins/plugins.qml12
-rw-r--r--examples/declarative/progressbar/content/ProgressBar.qml36
-rw-r--r--examples/declarative/progressbar/content/background.pngbin0 -> 426 bytes-rw-r--r--examples/declarative/progressbar/progressbars.qml24
-rw-r--r--examples/declarative/scrollbar/ScrollBar.qml31
-rw-r--r--examples/declarative/scrollbar/display.qml57
-rw-r--r--examples/declarative/scrollbar/pics/niagara_falls.jpgbin0 -> 604121 bytes-rw-r--r--examples/declarative/searchbox/SearchBox.qml60
-rw-r--r--examples/declarative/searchbox/images/edit-clear-locationbar-rtl.pngbin0 -> 429 bytes-rw-r--r--examples/declarative/searchbox/images/lineedit-bg-focus.pngbin0 -> 526 bytes-rw-r--r--examples/declarative/searchbox/images/lineedit-bg.pngbin0 -> 426 bytes-rw-r--r--examples/declarative/searchbox/main.qml13
-rw-r--r--examples/declarative/slideswitch/content/Switch.qml73
-rw-r--r--examples/declarative/slideswitch/content/background.svg23
-rw-r--r--examples/declarative/slideswitch/content/knob.svg867
-rw-r--r--examples/declarative/slideswitch/slideswitch.qml11
-rw-r--r--examples/declarative/snow/ImageBatch.qml72
-rw-r--r--examples/declarative/snow/Loading.qml8
-rw-r--r--examples/declarative/snow/create.js12
-rw-r--r--examples/declarative/snow/pics/loading.pngbin0 -> 761 bytes-rw-r--r--examples/declarative/snow/snow.qml69
-rw-r--r--examples/declarative/sql/hello.qml31
-rw-r--r--examples/declarative/states/states.qml50
-rw-r--r--examples/declarative/states/transitions.qml70
-rw-r--r--examples/declarative/states/user.pngbin0 -> 4886 bytes-rw-r--r--examples/declarative/tabwidget/TabWidget.qml42
-rw-r--r--examples/declarative/tabwidget/tabs.qml29
-rw-r--r--examples/declarative/tic-tac-toe/content/TicTac.qml20
-rw-r--r--examples/declarative/tic-tac-toe/content/pics/board.pngbin0 -> 5524 bytes-rw-r--r--examples/declarative/tic-tac-toe/content/pics/o.pngbin0 -> 1470 bytes-rw-r--r--examples/declarative/tic-tac-toe/content/pics/x.pngbin0 -> 1331 bytes-rw-r--r--examples/declarative/tic-tac-toe/tic-tac-toe.qml115
-rw-r--r--examples/declarative/tutorials/helloworld/Cell.qml32
-rw-r--r--examples/declarative/tutorials/helloworld/tutorial1.qml22
-rw-r--r--examples/declarative/tutorials/helloworld/tutorial2.qml31
-rw-r--r--examples/declarative/tutorials/helloworld/tutorial3.qml51
-rw-r--r--examples/declarative/tutorials/samegame/samegame1/Block.qml12
-rw-r--r--examples/declarative/tutorials/samegame/samegame1/Button.qml27
-rw-r--r--examples/declarative/tutorials/samegame/samegame1/pics/background.pngbin0 -> 313930 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame1/pics/redStone.pngbin0 -> 2902 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame1/samegame.qml40
-rw-r--r--examples/declarative/tutorials/samegame/samegame2/Block.qml10
-rw-r--r--examples/declarative/tutorials/samegame/samegame2/Button.qml25
-rw-r--r--examples/declarative/tutorials/samegame/samegame2/pics/background.pngbin0 -> 313930 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame2/pics/redStone.pngbin0 -> 2902 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame2/samegame.js61
-rw-r--r--examples/declarative/tutorials/samegame/samegame2/samegame.qml43
-rw-r--r--examples/declarative/tutorials/samegame/samegame3/Block.qml21
-rw-r--r--examples/declarative/tutorials/samegame/samegame3/Button.qml25
-rw-r--r--examples/declarative/tutorials/samegame/samegame3/Dialog.qml23
-rw-r--r--examples/declarative/tutorials/samegame/samegame3/pics/background.pngbin0 -> 313930 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame3/pics/blueStone.pngbin0 -> 3054 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame3/pics/greenStone.pngbin0 -> 2932 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame3/pics/redStone.pngbin0 -> 2902 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame3/samegame.js189
-rw-r--r--examples/declarative/tutorials/samegame/samegame3/samegame.qml62
-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/BoomBlock.qml63
-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/Button.qml25
-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml21
-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/background.pngbin0 -> 313930 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/blueStar.pngbin0 -> 278 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/blueStone.pngbin0 -> 3054 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/greenStar.pngbin0 -> 273 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/greenStone.pngbin0 -> 2932 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/redStar.pngbin0 -> 274 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/redStone.pngbin0 -> 2902 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/star.pngbin0 -> 262 bytes-rw-r--r--examples/declarative/tutorials/samegame/samegame4/content/pics/yellowStone.pngbin0 -> 3056 bytes-rwxr-xr-xexamples/declarative/tutorials/samegame/samegame4/content/samegame.js249
-rw-r--r--examples/declarative/tutorials/samegame/samegame4/highscores/README1
-rwxr-xr-xexamples/declarative/tutorials/samegame/samegame4/highscores/score_data.xml2
-rwxr-xr-xexamples/declarative/tutorials/samegame/samegame4/highscores/score_style.xsl28
-rwxr-xr-xexamples/declarative/tutorials/samegame/samegame4/highscores/scores.php34
-rw-r--r--examples/declarative/tutorials/samegame/samegame4/samegame.qml77
-rw-r--r--examples/declarative/tvtennis/click.wavbin0 -> 3056 bytes-rw-r--r--examples/declarative/tvtennis/paddle.wavbin0 -> 5320 bytes-rw-r--r--examples/declarative/tvtennis/tvtennis.qml74
-rw-r--r--examples/declarative/velocity/Day.qml78
-rw-r--r--examples/declarative/velocity/cork.jpgbin0 -> 88766 bytes-rw-r--r--examples/declarative/velocity/sticky.pngbin0 -> 15319 bytes-rw-r--r--examples/declarative/velocity/tack.pngbin0 -> 7282 bytes-rw-r--r--examples/declarative/velocity/velocity.qml108
-rw-r--r--examples/declarative/webview/autosize.qml60
-rw-r--r--examples/declarative/webview/content/FieldText.qml161
-rw-r--r--examples/declarative/webview/content/Mapping/Map.qml20
-rwxr-xr-xexamples/declarative/webview/content/Mapping/map.html47
-rw-r--r--examples/declarative/webview/content/SpinSquare.qml25
-rw-r--r--examples/declarative/webview/content/pics/cancel.pngbin0 -> 1038 bytes-rw-r--r--examples/declarative/webview/content/pics/ok.pngbin0 -> 655 bytes-rw-r--r--examples/declarative/webview/evalandattach.html31
-rw-r--r--examples/declarative/webview/evalandattach.qml54
-rw-r--r--examples/declarative/webview/googleMaps.qml31
-rw-r--r--examples/declarative/webview/inline-html.qml14
-rw-r--r--examples/declarative/webview/newwindows.html3
-rw-r--r--examples/declarative/webview/newwindows.qml30
-rw-r--r--examples/declarative/webview/qml-in-html.qml32
-rw-r--r--examples/declarative/webview/transparent.qml13
-rw-r--r--examples/declarative/workerscript/workerscript.js15
-rw-r--r--examples/declarative/workerscript/workerscript.qml47
-rw-r--r--examples/declarative/xmldata/daringfireball.qml45
-rw-r--r--examples/declarative/xmldata/yahoonews.qml79
-rw-r--r--examples/declarative/xmlhttprequest/test.qml36
-rw-r--r--examples/declarative/xmlhttprequest/test.xml5
-rw-r--r--examples/draganddrop/draggabletext/dragwidget.cpp2
-rw-r--r--examples/examples.pro1
-rw-r--r--examples/multimedia/audioinput/audioinput.cpp3
-rw-r--r--examples/multimedia/audiooutput/audiooutput.cpp3
-rw-r--r--mkspecs/common/symbian/symbian.conf22
-rw-r--r--mkspecs/features/moc.prf2
-rw-r--r--mkspecs/features/qttest_p4.prf26
-rw-r--r--mkspecs/features/symbian/def_files.prf48
-rw-r--r--mkspecs/features/symbian/def_files_disabled.prf12
-rw-r--r--mkspecs/linux-g++-x11egl/qmake.conf30
-rw-r--r--mkspecs/linux-g++-x11egl/qplatformdefs.h164
-rw-r--r--mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf20
-rw-r--r--mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h42
-rw-r--r--mkspecs/win32-icc/qmake.conf2
-rw-r--r--mkspecs/win32-msvc.net/qmake.conf89
-rw-r--r--mkspecs/win32-msvc.net/qplatformdefs.h140
-rw-r--r--mkspecs/win32-msvc/features/incremental.prf2
-rw-r--r--mkspecs/win32-msvc/features/incremental_off.prf2
-rw-r--r--mkspecs/win32-msvc/qmake.conf86
-rw-r--r--mkspecs/win32-msvc/qplatformdefs.h138
-rw-r--r--mkspecs/win32-msvc2002/qmake.conf88
-rw-r--r--mkspecs/win32-msvc2002/qplatformdefs.h42
-rw-r--r--qmake/Makefile.unix5
-rw-r--r--qmake/Makefile.win326
-rw-r--r--qmake/Makefile.win32-g++5
-rw-r--r--qmake/Makefile.win32-g++-sh5
-rw-r--r--qmake/generators/makefile.cpp22
-rw-r--r--qmake/generators/metamakefile.cpp10
-rw-r--r--qmake/generators/symbian/initprojectdeploy_symbian.cpp2
-rw-r--r--qmake/generators/symbian/symmake.cpp149
-rw-r--r--qmake/generators/symbian/symmake_abld.cpp17
-rw-r--r--qmake/generators/unix/unixmake.cpp6
-rw-r--r--qmake/generators/win32/msvc_dsp.cpp1207
-rw-r--r--qmake/generators/win32/msvc_dsp.h122
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp3
-rw-r--r--qmake/option.cpp7
-rw-r--r--qmake/option.h2
-rw-r--r--qmake/project.cpp20
-rw-r--r--qmake/property.cpp2
-rw-r--r--qmake/qmake.pri4
-rw-r--r--qmake/qmake.pro14
-rw-r--r--src/3rdparty/phonon/ds9/videowidget.cpp3
-rw-r--r--src/3rdparty/phonon/mmf/environmentalreverb.cpp53
-rw-r--r--src/3rdparty/s60/eiksoftkeyimage.h95
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/ChangeLog13
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp4
-rw-r--r--src/3rdparty/webkit/VERSION2
-rw-r--r--src/3rdparty/webkit/WebCore/ChangeLog50
-rw-r--r--src/3rdparty/webkit/WebCore/WebCore.pro4
-rw-r--r--src/3rdparty/webkit/WebCore/platform/qt/KURLQt.cpp6
-rw-r--r--src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp29
-rw-r--r--src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h10
-rw-r--r--src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.cpp22
-rw-r--r--src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.h8
-rw-r--r--src/corelib/arch/sparc/arch.pri2
-rw-r--r--src/corelib/codecs/qsimplecodec.cpp2
-rw-r--r--src/corelib/codecs/qtextcodec.cpp50
-rw-r--r--src/corelib/corelib.pro2
-rw-r--r--src/corelib/global/qglobal.cpp2
-rw-r--r--src/corelib/global/qglobal.h3
-rw-r--r--src/corelib/global/qnamespace.h5
-rw-r--r--src/corelib/global/qnamespace.qdoc15
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp2
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp2
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp5
-rw-r--r--src/corelib/tools/qdatetime.cpp60
-rw-r--r--src/corelib/tools/qpoint.cpp2
-rw-r--r--src/corelib/tools/qstring.h2
-rw-r--r--src/corelib/tools/qstringbuilder.h2
-rw-r--r--src/declarative/3rdparty/3rdparty.pri7
-rw-r--r--src/declarative/3rdparty/qlistmodelinterface.cpp109
-rw-r--r--src/declarative/3rdparty/qlistmodelinterface_p.h85
-rw-r--r--src/declarative/QmlChanges.txt122
-rw-r--r--src/declarative/debugger/debugger.pri15
-rw-r--r--src/declarative/debugger/qmldebug.cpp934
-rw-r--r--src/declarative/debugger/qmldebug_p.h366
-rw-r--r--src/declarative/debugger/qmldebugclient.cpp207
-rw-r--r--src/declarative/debugger/qmldebugclient_p.h99
-rw-r--r--src/declarative/debugger/qmldebuggerstatus.cpp54
-rw-r--r--src/declarative/debugger/qmldebuggerstatus_p.h66
-rw-r--r--src/declarative/debugger/qmldebugservice.cpp393
-rw-r--r--src/declarative/debugger/qmldebugservice_p.h90
-rw-r--r--src/declarative/debugger/qpacketprotocol.cpp498
-rw-r--r--src/declarative/debugger/qpacketprotocol_p.h122
-rw-r--r--src/declarative/declarative.pro30
-rw-r--r--src/declarative/graphicsitems/graphicsitems.pri90
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanchors.cpp1060
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanchors_p.h196
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h174
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanimatedimage.cpp305
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanimatedimage_p.h106
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanimatedimage_p_p.h82
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsborderimage.cpp409
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsborderimage_p.h103
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsborderimage_p_p.h97
-rw-r--r--src/declarative/graphicsitems/qmlgraphicseffects.cpp183
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsevents.cpp195
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsevents_p_p.h137
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable.cpp1374
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable_p.h210
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h164
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflipable.cpp239
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflipable_p.h95
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp90
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsfocuspanel_p.h77
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp71
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsfocusscope_p.h68
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer.cpp271
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer_p.h90
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsgridview.cpp1761
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsgridview_p.h164
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimage.cpp369
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimage_p.h102
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimage_p_p.h79
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimagebase.cpp191
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimagebase_p.h92
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimagebase_p_p.h84
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem.cpp3099
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem.h239
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem_p.h287
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h76
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslayoutitem.cpp108
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslayoutitem_p.h94
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview.cpp2748
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview_p.h238
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsloader.cpp488
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsloader_p.h109
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsloader_p_p.h88
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp653
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsmouseregion_p.h177
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsmouseregion_p_p.h117
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspainteditem.cpp466
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspainteditem_p.h114
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h90
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsparticles.cpp1241
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsparticles_p.h247
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspath.cpp850
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspath_p.h262
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspath_p_p.h81
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspathview.cpp976
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspathview_p.h134
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspathview_p_p.h144
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspositioners.cpp851
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspositioners_p.h192
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h136
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsrectangle.cpp467
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsrectangle_p.h186
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsrectangle_p_p.h109
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsrepeater.cpp320
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsrepeater_p.h102
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsrepeater_p_p.h82
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsscalegrid.cpp213
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsscalegrid_p_p.h133
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstext.cpp927
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstext_p.h160
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstext_p_p.h127
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextedit.cpp1035
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextedit_p.h240
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextedit_p_p.h113
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextinput.cpp916
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextinput_p.h230
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextinput_p_p.h114
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp1155
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h207
-rw-r--r--src/declarative/graphicsitems/qmlgraphicswebview.cpp1351
-rw-r--r--src/declarative/graphicsitems/qmlgraphicswebview_p.h257
-rw-r--r--src/declarative/graphicsitems/qmlgraphicswebview_p_p.h151
-rw-r--r--src/declarative/qml/parser/parser.pri21
-rw-r--r--src/declarative/qml/parser/qmljs.g3075
-rw-r--r--src/declarative/qml/parser/qmljsast.cpp955
-rw-r--r--src/declarative/qml/parser/qmljsast_p.h2678
-rw-r--r--src/declarative/qml/parser/qmljsastfwd_p.h189
-rw-r--r--src/declarative/qml/parser/qmljsastvisitor.cpp58
-rw-r--r--src/declarative/qml/parser/qmljsastvisitor_p.h335
-rw-r--r--src/declarative/qml/parser/qmljsengine_p.cpp212
-rw-r--r--src/declarative/qml/parser/qmljsengine_p.h173
-rw-r--r--src/declarative/qml/parser/qmljsglobal_p.h64
-rw-r--r--src/declarative/qml/parser/qmljsgrammar.cpp939
-rw-r--r--src/declarative/qml/parser/qmljsgrammar_p.h209
-rw-r--r--src/declarative/qml/parser/qmljslexer.cpp1161
-rw-r--r--src/declarative/qml/parser/qmljslexer_p.h249
-rw-r--r--src/declarative/qml/parser/qmljsmemorypool_p.h133
-rw-r--r--src/declarative/qml/parser/qmljsnodepool_p.h139
-rw-r--r--src/declarative/qml/parser/qmljsparser.cpp1843
-rw-r--r--src/declarative/qml/parser/qmljsparser_p.h246
-rw-r--r--src/declarative/qml/qbitfield_p.h165
-rw-r--r--src/declarative/qml/qmetaobjectbuilder.cpp2575
-rw-r--r--src/declarative/qml/qmetaobjectbuilder_p.h321
-rw-r--r--src/declarative/qml/qml.h155
-rw-r--r--src/declarative/qml/qml.pri123
-rw-r--r--src/declarative/qml/qmlbinding.cpp304
-rw-r--r--src/declarative/qml/qmlbinding.h129
-rw-r--r--src/declarative/qml/qmlbinding_p.h89
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp264
-rw-r--r--src/declarative/qml/qmlboundsignal_p.h100
-rw-r--r--src/declarative/qml/qmlclassfactory.cpp50
-rw-r--r--src/declarative/qml/qmlclassfactory_p.h74
-rw-r--r--src/declarative/qml/qmlcleanup.cpp85
-rw-r--r--src/declarative/qml/qmlcleanup_p.h79
-rw-r--r--src/declarative/qml/qmlcompiledbindings.cpp2720
-rw-r--r--src/declarative/qml/qmlcompiledbindings_p.h116
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp239
-rw-r--r--src/declarative/qml/qmlcompiler.cpp2815
-rw-r--r--src/declarative/qml/qmlcompiler_p.h337
-rw-r--r--src/declarative/qml/qmlcomponent.cpp798
-rw-r--r--src/declarative/qml/qmlcomponent.h134
-rw-r--r--src/declarative/qml/qmlcomponent_p.h147
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h150
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp670
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h117
-rw-r--r--src/declarative/qml/qmlcontext.cpp544
-rw-r--r--src/declarative/qml/qmlcontext.h105
-rw-r--r--src/declarative/qml/qmlcontext_p.h192
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp270
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h101
-rw-r--r--src/declarative/qml/qmlcustomparser.cpp263
-rw-r--r--src/declarative/qml/qmlcustomparser_p.h146
-rw-r--r--src/declarative/qml/qmlcustomparser_p_p.h89
-rw-r--r--src/declarative/qml/qmldeclarativedata_p.h138
-rw-r--r--src/declarative/qml/qmldom.cpp1837
-rw-r--r--src/declarative/qml/qmldom.h349
-rw-r--r--src/declarative/qml/qmldom_p.h157
-rw-r--r--src/declarative/qml/qmlengine.cpp1659
-rw-r--r--src/declarative/qml/qmlengine.h106
-rw-r--r--src/declarative/qml/qmlengine_p.h320
-rw-r--r--src/declarative/qml/qmlenginedebug.cpp457
-rw-r--r--src/declarative/qml/qmlenginedebug_p.h121
-rw-r--r--src/declarative/qml/qmlerror.cpp257
-rw-r--r--src/declarative/qml/qmlerror.h86
-rw-r--r--src/declarative/qml/qmlexpression.cpp831
-rw-r--r--src/declarative/qml/qmlexpression.h118
-rw-r--r--src/declarative/qml/qmlexpression_p.h187
-rw-r--r--src/declarative/qml/qmlglobal_p.h91
-rw-r--r--src/declarative/qml/qmlglobalscriptclass.cpp121
-rw-r--r--src/declarative/qml/qmlglobalscriptclass_p.h83
-rw-r--r--src/declarative/qml/qmlguard_p.h156
-rw-r--r--src/declarative/qml/qmlinfo.cpp127
-rw-r--r--src/declarative/qml/qmlinfo.h92
-rw-r--r--src/declarative/qml/qmlinstruction.cpp216
-rw-r--r--src/declarative/qml/qmlinstruction_p.h321
-rw-r--r--src/declarative/qml/qmlintegercache.cpp86
-rw-r--r--src/declarative/qml/qmlintegercache_p.h111
-rw-r--r--src/declarative/qml/qmllist.h126
-rw-r--r--src/declarative/qml/qmllistscriptclass.cpp173
-rw-r--r--src/declarative/qml/qmllistscriptclass_p.h86
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp1245
-rw-r--r--src/declarative/qml/qmlmetaproperty.h148
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h124
-rw-r--r--src/declarative/qml/qmlmetatype.cpp1301
-rw-r--r--src/declarative/qml/qmlmetatype.h301
-rw-r--r--src/declarative/qml/qmlmoduleplugin.cpp111
-rw-r--r--src/declarative/qml/qmlmoduleplugin.h86
-rw-r--r--src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp79
-rw-r--r--src/declarative/qml/qmlnetworkaccessmanagerfactory.h66
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp675
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h144
-rw-r--r--src/declarative/qml/qmlparser.cpp387
-rw-r--r--src/declarative/qml/qmlparser_p.h357
-rw-r--r--src/declarative/qml/qmlparserstatus.cpp80
-rw-r--r--src/declarative/qml/qmlparserstatus.h75
-rw-r--r--src/declarative/qml/qmlprivate.cpp48
-rw-r--r--src/declarative/qml/qmlprivate.h386
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp415
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h194
-rw-r--r--src/declarative/qml/qmlpropertyvalueinterceptor.cpp79
-rw-r--r--src/declarative/qml/qmlpropertyvalueinterceptor.h68
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.cpp71
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.h67
-rw-r--r--src/declarative/qml/qmlproxymetaobject.cpp138
-rw-r--r--src/declarative/qml/qmlproxymetaobject_p.h100
-rw-r--r--src/declarative/qml/qmlrefcount.cpp70
-rw-r--r--src/declarative/qml/qmlrefcount_p.h80
-rw-r--r--src/declarative/qml/qmlrewrite.cpp215
-rw-r--r--src/declarative/qml/qmlrewrite_p.h121
-rw-r--r--src/declarative/qml/qmlscript.cpp87
-rw-r--r--src/declarative/qml/qmlscriptclass_p.h89
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp952
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h137
-rw-r--r--src/declarative/qml/qmlscriptstring.cpp154
-rw-r--r--src/declarative/qml/qmlscriptstring.h87
-rw-r--r--src/declarative/qml/qmlsqldatabase.cpp425
-rw-r--r--src/declarative/qml/qmlsqldatabase_p.h60
-rw-r--r--src/declarative/qml/qmlstringconverters.cpp276
-rw-r--r--src/declarative/qml/qmlstringconverters_p.h87
-rw-r--r--src/declarative/qml/qmltypenamecache.cpp103
-rw-r--r--src/declarative/qml/qmltypenamecache_p.h117
-rw-r--r--src/declarative/qml/qmltypenamescriptclass.cpp166
-rw-r--r--src/declarative/qml/qmltypenamescriptclass_p.h93
-rw-r--r--src/declarative/qml/qmlvaluetype.cpp636
-rw-r--r--src/declarative/qml/qmlvaluetype_p.h340
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass.cpp148
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass_p.h86
-rw-r--r--src/declarative/qml/qmlvme.cpp891
-rw-r--r--src/declarative/qml/qmlvme_p.h119
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp340
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h172
-rw-r--r--src/declarative/qml/qmlwatcher.cpp185
-rw-r--r--src/declarative/qml/qmlwatcher_p.h94
-rw-r--r--src/declarative/qml/qmlworkerscript.cpp1037
-rw-r--r--src/declarative/qml/qmlworkerscript_p.h160
-rw-r--r--src/declarative/qml/qmlxmlhttprequest.cpp1627
-rw-r--r--src/declarative/qml/qmlxmlhttprequest_p.h60
-rw-r--r--src/declarative/qml/qpodvector_p.h173
-rw-r--r--src/declarative/qml/rewriter/rewriter.cpp102
-rw-r--r--src/declarative/qml/rewriter/rewriter.pri9
-rw-r--r--src/declarative/qml/rewriter/rewriter_p.h153
-rw-r--r--src/declarative/qml/rewriter/textwriter.cpp217
-rw-r--r--src/declarative/qml/rewriter/textwriter_p.h101
-rw-r--r--src/declarative/util/qfxperf.cpp67
-rw-r--r--src/declarative/util/qfxperf_p_p.h90
-rw-r--r--src/declarative/util/qmlanimation.cpp2337
-rw-r--r--src/declarative/util/qmlanimation_p.h440
-rw-r--r--src/declarative/util/qmlanimation_p_p.h384
-rw-r--r--src/declarative/util/qmlbehavior.cpp189
-rw-r--r--src/declarative/util/qmlbehavior_p.h92
-rw-r--r--src/declarative/util/qmlbind.cpp201
-rw-r--r--src/declarative/util/qmlbind_p.h95
-rw-r--r--src/declarative/util/qmlconnection.cpp287
-rw-r--r--src/declarative/util/qmlconnection_p.h93
-rw-r--r--src/declarative/util/qmldatetimeformatter.cpp372
-rw-r--r--src/declarative/util/qmldatetimeformatter_p.h117
-rw-r--r--src/declarative/util/qmleasefollow.cpp527
-rw-r--r--src/declarative/util/qmleasefollow_p.h114
-rw-r--r--src/declarative/util/qmlfontloader.cpp229
-rw-r--r--src/declarative/util/qmlfontloader_p.h95
-rw-r--r--src/declarative/util/qmllistaccessor.cpp260
-rw-r--r--src/declarative/util/qmllistaccessor_p.h85
-rw-r--r--src/declarative/util/qmllistmodel.cpp990
-rw-r--r--src/declarative/util/qmllistmodel_p.h107
-rw-r--r--src/declarative/util/qmlnullablevalue_p_p.h81
-rw-r--r--src/declarative/util/qmlnumberformatter.cpp260
-rw-r--r--src/declarative/util/qmlnumberformatter_p.h93
-rw-r--r--src/declarative/util/qmlopenmetaobject.cpp355
-rw-r--r--src/declarative/util/qmlopenmetaobject_p.h125
-rw-r--r--src/declarative/util/qmlpackage.cpp177
-rw-r--r--src/declarative/util/qmlpackage_p.h88
-rw-r--r--src/declarative/util/qmlpixmapcache.cpp605
-rw-r--r--src/declarative/util/qmlpixmapcache_p.h107
-rw-r--r--src/declarative/util/qmlpropertychanges.cpp468
-rw-r--r--src/declarative/util/qmlpropertychanges_p.h84
-rw-r--r--src/declarative/util/qmlpropertymap.cpp278
-rw-r--r--src/declarative/util/qmlpropertymap.h90
-rw-r--r--src/declarative/util/qmlspringfollow.cpp464
-rw-r--r--src/declarative/util/qmlspringfollow_p.h112
-rw-r--r--src/declarative/util/qmlstate.cpp468
-rw-r--r--src/declarative/util/qmlstate_p.h178
-rw-r--r--src/declarative/util/qmlstate_p_p.h147
-rw-r--r--src/declarative/util/qmlstategroup.cpp423
-rw-r--r--src/declarative/util/qmlstategroup_p.h95
-rw-r--r--src/declarative/util/qmlstateoperations.cpp834
-rw-r--r--src/declarative/util/qmlstateoperations_p.h184
-rw-r--r--src/declarative/util/qmlstyledtext.cpp343
-rw-r--r--src/declarative/util/qmlstyledtext_p.h63
-rw-r--r--src/declarative/util/qmlsystempalette.cpp303
-rw-r--r--src/declarative/util/qmlsystempalette_p.h122
-rw-r--r--src/declarative/util/qmltimeline.cpp941
-rw-r--r--src/declarative/util/qmltimeline_p_p.h223
-rw-r--r--src/declarative/util/qmltimer.cpp313
-rw-r--r--src/declarative/util/qmltimer_p.h109
-rw-r--r--src/declarative/util/qmltransition.cpp261
-rw-r--r--src/declarative/util/qmltransition_p.h101
-rw-r--r--src/declarative/util/qmltransitionmanager.cpp282
-rw-r--r--src/declarative/util/qmltransitionmanager_p_p.h85
-rw-r--r--src/declarative/util/qmlview.cpp586
-rw-r--r--src/declarative/util/qmlview.h113
-rw-r--r--src/declarative/util/qmlxmllistmodel.cpp728
-rw-r--r--src/declarative/util/qmlxmllistmodel_p.h136
-rw-r--r--src/declarative/util/qnumberformat.cpp225
-rw-r--r--src/declarative/util/qnumberformat_p.h174
-rw-r--r--src/declarative/util/qperformancelog.cpp181
-rw-r--r--src/declarative/util/qperformancelog_p_p.h141
-rw-r--r--src/declarative/util/util.pri72
-rw-r--r--src/declarative/widgets/graphicslayouts.cpp319
-rw-r--r--src/declarative/widgets/graphicslayouts_p.h183
-rw-r--r--src/declarative/widgets/graphicswidgets.cpp163
-rw-r--r--src/declarative/widgets/graphicswidgets_p.h68
-rw-r--r--src/declarative/widgets/widgets.pri9
-rw-r--r--src/gui/dialogs/qdialog.cpp7
-rw-r--r--src/gui/dialogs/qfiledialog.cpp3
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp84
-rw-r--r--src/gui/dialogs/qmessagebox.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp17
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h10
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp32
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp1
-rw-r--r--src/gui/image/qicon.cpp17
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp20
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks_p.h23
-rw-r--r--src/gui/image/qimagereader.cpp28
-rw-r--r--src/gui/image/qpixmap.cpp12
-rw-r--r--src/gui/image/qpixmap_x11.cpp40
-rw-r--r--src/gui/image/qpixmap_x11_p.h2
-rw-r--r--src/gui/image/qpixmapdata.cpp11
-rw-r--r--src/gui/image/qpixmapdata_p.h8
-rw-r--r--src/gui/image/qpixmapfilter.cpp17
-rw-r--r--src/gui/image/qpnghandler.cpp137
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_p.h5
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_s60.cpp28
-rw-r--r--src/gui/itemviews/qlistview.cpp2
-rw-r--r--src/gui/kernel/qaction.cpp4
-rw-r--r--src/gui/kernel/qapplication.cpp254
-rw-r--r--src/gui/kernel/qapplication_mac.mm6
-rw-r--r--src/gui/kernel/qapplication_p.h9
-rw-r--r--src/gui/kernel/qapplication_s60.cpp31
-rw-r--r--src/gui/kernel/qapplication_win.cpp28
-rw-r--r--src/gui/kernel/qapplication_x11.cpp8
-rw-r--r--src/gui/kernel/qclipboard_mac.cpp12
-rw-r--r--src/gui/kernel/qcocoapanel_mac.mm3
-rw-r--r--src/gui/kernel/qcocoasharedwindowmethods_mac_p.h24
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm14
-rw-r--r--src/gui/kernel/qcocoawindow_mac_p.h3
-rw-r--r--src/gui/kernel/qcursor.cpp6
-rw-r--r--src/gui/kernel/qcursor_mac.mm24
-rw-r--r--src/gui/kernel/qcursor_win.cpp7
-rw-r--r--src/gui/kernel/qcursor_x11.cpp50
-rw-r--r--src/gui/kernel/qdesktopwidget_s60.cpp18
-rw-r--r--src/gui/kernel/qdnd.cpp218
-rw-r--r--src/gui/kernel/qdnd_p.h2
-rw-r--r--src/gui/kernel/qdnd_x11.cpp6
-rw-r--r--src/gui/kernel/qkeymapper_x11.cpp14
-rw-r--r--src/gui/kernel/qsoftkeymanager_s60.cpp102
-rw-r--r--src/gui/kernel/qsoftkeymanager_s60_p.h5
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm2
-rw-r--r--src/gui/kernel/qwidget.cpp53
-rw-r--r--src/gui/kernel/qwidget_mac.mm19
-rw-r--r--src/gui/kernel/qwidget_p.h5
-rw-r--r--src/gui/kernel/qwidget_s60.cpp114
-rw-r--r--src/gui/kernel/qwidget_win.cpp5
-rw-r--r--src/gui/kernel/qwidget_x11.cpp77
-rw-r--r--src/gui/painting/qdrawhelper.cpp40
-rw-r--r--src/gui/painting/qdrawhelper_mmx_p.h45
-rw-r--r--src/gui/painting/qdrawhelper_p.h3
-rw-r--r--src/gui/painting/qmath_p.h6
-rw-r--r--src/gui/painting/qpaintengine_x11.cpp3
-rw-r--r--src/gui/painting/qpainter.cpp27
-rw-r--r--src/gui/painting/qpathclipper.cpp6
-rw-r--r--src/gui/painting/qpathclipper_p.h2
-rw-r--r--src/gui/painting/qwindowsurface_raster.cpp4
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp11
-rw-r--r--src/gui/styles/qcommonstyle.cpp194
-rw-r--r--src/gui/styles/qmacstyle_mac.mm10
-rw-r--r--src/gui/styles/qs60style_simulated.cpp12
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp2
-rw-r--r--src/gui/text/qfont.cpp5
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp11
-rw-r--r--src/gui/text/qfontengine_s60.cpp2
-rw-r--r--src/gui/text/qtextcontrol.cpp12
-rw-r--r--src/gui/text/qtextdocument.cpp17
-rw-r--r--src/gui/text/qtextdocument.h7
-rw-r--r--src/gui/text/qtextdocument_p.cpp63
-rw-r--r--src/gui/text/qtextdocument_p.h3
-rw-r--r--src/gui/text/qtextlayout.cpp6
-rw-r--r--src/gui/text/qzip.cpp9
-rw-r--r--src/gui/text/qzipreader_p.h6
-rw-r--r--src/gui/text/qzipwriter_p.h2
-rw-r--r--src/gui/util/qsystemtrayicon_p.h2
-rw-r--r--src/gui/util/qsystemtrayicon_x11.cpp2
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp11
-rw-r--r--src/gui/widgets/qabstractslider.cpp73
-rw-r--r--src/gui/widgets/qabstractslider_p.h1
-rw-r--r--src/gui/widgets/qabstractspinbox.h2
-rw-r--r--src/gui/widgets/qcombobox.h2
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp2
-rw-r--r--src/gui/widgets/qdialogbuttonbox.cpp2
-rw-r--r--src/gui/widgets/qdockarealayout.cpp62
-rw-r--r--src/gui/widgets/qdockarealayout_p.h5
-rw-r--r--src/gui/widgets/qlabel.cpp4
-rw-r--r--src/gui/widgets/qlinecontrol.cpp2
-rw-r--r--src/gui/widgets/qlineedit.cpp6
-rw-r--r--src/gui/widgets/qmainwindow.cpp13
-rw-r--r--src/gui/widgets/qmainwindowlayout.cpp14
-rw-r--r--src/gui/widgets/qmenu.cpp4
-rw-r--r--src/gui/widgets/qmenu.h2
-rw-r--r--src/gui/widgets/qscrollbar.cpp18
-rw-r--r--src/gui/widgets/qtoolbar.cpp3
-rw-r--r--src/gui/widgets/qvalidator.h5
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo.cpp4
-rw-r--r--src/multimedia/audio/qaudioformat.cpp8
-rw-r--r--src/multimedia/video/qabstractvideobuffer.cpp1
-rw-r--r--src/multimedia/video/qabstractvideosurface.cpp1
-rw-r--r--src/multimedia/video/qvideoframe.cpp1
-rw-r--r--src/multimedia/video/qvideosurfaceformat.cpp1
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp27
-rw-r--r--src/network/access/qhttpnetworkreply.cpp68
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp2
-rw-r--r--src/network/access/qnetworkcookie.h2
-rw-r--r--src/network/access/qnetworkcookiejar.h2
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp37
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h1
-rw-r--r--src/opengl/qgl.cpp40
-rw-r--r--src/opengl/qgl_mac.mm2
-rw-r--r--src/opengl/qgl_p.h13
-rw-r--r--src/opengl/qglextensions.cpp6
-rw-r--r--src/opengl/qglextensions_p.h50
-rw-r--r--src/opengl/qglpixelbuffer_x11.cpp6
-rw-r--r--src/opengl/qglpixmapfilter.cpp23
-rw-r--r--src/opengl/qglshaderprogram.cpp234
-rw-r--r--src/opengl/qglshaderprogram.h35
-rw-r--r--src/openvg/qpaintengine_vg.cpp97
-rw-r--r--src/openvg/qpixmapdata_vg.cpp12
-rw-r--r--src/plugins/accessible/widgets/qaccessiblewidgets.cpp2
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp11
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp2
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp308
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.h3
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp24
-rw-r--r--src/plugins/imageformats/ico/qicohandler.h3
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp574
-rw-r--r--src/plugins/kbddrivers/linuxinput/main.cpp2
-rw-r--r--src/qt3support/dialogs/q3filedialog.cpp40
-rw-r--r--src/qt3support/itemviews/q3iconview.cpp13
-rw-r--r--src/qt3support/itemviews/q3listview.cpp3
-rw-r--r--src/s60installs/bwins/QtGuiu.def80
-rw-r--r--src/s60installs/bwins/QtOpenVGu.def29
-rw-r--r--src/s60installs/eabi/QtGuiu.def25
-rw-r--r--src/s60installs/eabi/QtOpenVGu.def23
-rw-r--r--src/s60installs/qt.iby3
-rw-r--r--src/s60main/s60main.pro3
-rw-r--r--src/script/bridge/qscriptdeclarativeclass.cpp192
-rw-r--r--src/script/bridge/qscriptdeclarativeclass_p.h37
-rw-r--r--src/script/bridge/qscriptdeclarativeobject.cpp35
-rw-r--r--src/script/bridge/qscriptdeclarativeobject_p.h6
-rw-r--r--src/sql/drivers/sqlite/qsql_sqlite.cpp47
-rw-r--r--src/sql/kernel/qsqldatabase.cpp1
-rw-r--r--src/testlib/qbenchmark.cpp2
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp5
-rw-r--r--src/xml/dom/qdom.cpp2
-rw-r--r--src/xmlpatterns/data/qatomicvalue.cpp2
-rw-r--r--src/xmlpatterns/schema/qxsdschemaparser.cpp2
-rw-r--r--tests/auto/auto.pro8
-rw-r--r--tests/auto/declarative/.gitignore4
-rw-r--r--tests/auto/declarative/declarative.pro65
-rw-r--r--tests/auto/declarative/examples/data/dummytest.qml6
-rw-r--r--tests/auto/declarative/examples/data/webbrowser/webbrowser.qml6
-rw-r--r--tests/auto/declarative/examples/examples.pro5
-rw-r--r--tests/auto/declarative/examples/tst_examples.cpp201
-rw-r--r--tests/auto/declarative/graphicswidgets/data/graphicswidgets.qml57
-rw-r--r--tests/auto/declarative/graphicswidgets/graphicswidgets.pro8
-rw-r--r--tests/auto/declarative/graphicswidgets/tst_graphicswidgets.cpp77
-rw-r--r--tests/auto/declarative/layouts/data/layouts.qml33
-rw-r--r--tests/auto/declarative/layouts/layouts.pro7
-rw-r--r--tests/auto/declarative/layouts/tst_layouts.cpp148
-rw-r--r--tests/auto/declarative/parserstress/parserstress.pro7
-rw-r--r--tests/auto/declarative/parserstress/tst_parserstress.cpp151
-rw-r--r--tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro7
-rw-r--r--tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp1258
-rw-r--r--tests/auto/declarative/qmlanimations/data/attached.qml34
-rw-r--r--tests/auto/declarative/qmlanimations/data/badproperty1.qml21
-rw-r--r--tests/auto/declarative/qmlanimations/data/badproperty2.qml21
-rw-r--r--tests/auto/declarative/qmlanimations/data/badtype1.qml12
-rw-r--r--tests/auto/declarative/qmlanimations/data/badtype2.qml12
-rw-r--r--tests/auto/declarative/qmlanimations/data/badtype3.qml12
-rw-r--r--tests/auto/declarative/qmlanimations/data/badtype4.qml27
-rw-r--r--tests/auto/declarative/qmlanimations/data/dotproperty.qml24
-rw-r--r--tests/auto/declarative/qmlanimations/data/mixedtype1.qml25
-rw-r--r--tests/auto/declarative/qmlanimations/data/mixedtype2.qml25
-rw-r--r--tests/auto/declarative/qmlanimations/data/properties.qml14
-rw-r--r--tests/auto/declarative/qmlanimations/data/properties2.qml14
-rw-r--r--tests/auto/declarative/qmlanimations/data/properties3.qml14
-rw-r--r--tests/auto/declarative/qmlanimations/data/properties4.qml14
-rw-r--r--tests/auto/declarative/qmlanimations/data/properties5.qml14
-rw-r--r--tests/auto/declarative/qmlanimations/data/propertiesTransition.qml29
-rw-r--r--tests/auto/declarative/qmlanimations/data/propertiesTransition2.qml29
-rw-r--r--tests/auto/declarative/qmlanimations/data/propertiesTransition3.qml29
-rw-r--r--tests/auto/declarative/qmlanimations/data/propertiesTransition4.qml29
-rw-r--r--tests/auto/declarative/qmlanimations/data/propertiesTransition5.qml29
-rw-r--r--tests/auto/declarative/qmlanimations/data/propertiesTransition6.qml29
-rw-r--r--tests/auto/declarative/qmlanimations/data/valuesource.qml14
-rw-r--r--tests/auto/declarative/qmlanimations/data/valuesource2.qml14
-rw-r--r--tests/auto/declarative/qmlanimations/qmlanimations.pro6
-rw-r--r--tests/auto/declarative/qmlanimations/tst_qmlanimations.cpp611
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/binding.qml26
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/color.qml24
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/cpptrigger.qml11
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/disabled.qml27
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/empty.qml23
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/groupProperty.qml23
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/groupProperty2.qml23
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/loop.qml19
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/nonSelecting.qml26
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/nonSelecting2.qml26
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/parent.qml28
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/reassignedAnimation.qml27
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/scripttrigger.qml16
-rw-r--r--tests/auto/declarative/qmlbehaviors/data/simple.qml26
-rw-r--r--tests/auto/declarative/qmlbehaviors/qmlbehaviors.pro6
-rw-r--r--tests/auto/declarative/qmlbehaviors/tst_qmlbehaviors.cpp281
-rw-r--r--tests/auto/declarative/qmlbinding/data/test-binding.qml16
-rw-r--r--tests/auto/declarative/qmlbinding/data/test-binding2.qml16
-rw-r--r--tests/auto/declarative/qmlbinding/qmlbinding.pro8
-rw-r--r--tests/auto/declarative/qmlbinding/tst_qmlbinding.cpp107
-rw-r--r--tests/auto/declarative/qmlconnection/data/test-connection.qml10
-rw-r--r--tests/auto/declarative/qmlconnection/data/test-connection2.qml3
-rw-r--r--tests/auto/declarative/qmlconnection/data/test-connection3.qml3
-rw-r--r--tests/auto/declarative/qmlconnection/data/trimming.qml10
-rw-r--r--tests/auto/declarative/qmlconnection/qmlconnection.pro8
-rw-r--r--tests/auto/declarative/qmlconnection/tst_qmlconnection.cpp139
-rw-r--r--tests/auto/declarative/qmlcontext/qmlcontext.pro6
-rw-r--r--tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp434
-rw-r--r--tests/auto/declarative/qmldatetimeformatter/qmldatetimeformatter.pro5
-rw-r--r--tests/auto/declarative/qmldatetimeformatter/tst_qmldatetimeformatter.cpp150
-rw-r--r--tests/auto/declarative/qmldebug/qmldebug.pro7
-rw-r--r--tests/auto/declarative/qmldebug/tst_qmldebug.cpp833
-rw-r--r--tests/auto/declarative/qmldebugclient/qmldebugclient.pro7
-rw-r--r--tests/auto/declarative/qmldebugclient/tst_qmldebugclient.cpp157
-rw-r--r--tests/auto/declarative/qmldebugservice/qmldebugservice.pro7
-rw-r--r--tests/auto/declarative/qmldebugservice/tst_qmldebugservice.cpp189
-rw-r--r--tests/auto/declarative/qmldom/data/MyComponent.qml4
-rw-r--r--tests/auto/declarative/qmldom/data/MyItem.qml4
-rw-r--r--tests/auto/declarative/qmldom/data/importdir/Bar.qml2
-rw-r--r--tests/auto/declarative/qmldom/data/importlib/sublib/qmldir/Foo.qml2
-rw-r--r--tests/auto/declarative/qmldom/data/top.qml6
-rw-r--r--tests/auto/declarative/qmldom/qmldom.pro7
-rw-r--r--tests/auto/declarative/qmldom/tst_qmldom.cpp1313
-rw-r--r--tests/auto/declarative/qmleasefollow/data/easefollow1.qml3
-rw-r--r--tests/auto/declarative/qmleasefollow/data/easefollow2.qml5
-rw-r--r--tests/auto/declarative/qmleasefollow/data/easefollow3.qml6
-rw-r--r--tests/auto/declarative/qmleasefollow/qmleasefollow.pro8
-rw-r--r--tests/auto/declarative/qmleasefollow/tst_qmleasefollow.cpp122
-rw-r--r--tests/auto/declarative/qmlecmascript/data/ConstantsOverrideBindings.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/CustomObject.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/MethodsObject.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/NestedTypeTransientErrors.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/ScopeObject.qml14
-rw-r--r--tests/auto/declarative/qmlecmascript/data/TypeForDynamicCreation.qml2
-rw-r--r--tests/auto/declarative/qmlecmascript/data/aliasPropertyAndBinding.qml14
-rw-r--r--tests/auto/declarative/qmlecmascript/data/assignBasicTypes.2.qml26
-rw-r--r--tests/auto/declarative/qmlecmascript/data/assignBasicTypes.qml29
-rw-r--r--tests/auto/declarative/qmlecmascript/data/attachedProperty.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/bindingLoop.qml14
-rw-r--r--tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/bug.1.qml10
-rw-r--r--tests/auto/declarative/qmlecmascript/data/compositePropertyType.qml8
-rw-r--r--tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.1.qml8
-rw-r--r--tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.2.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.3.qml7
-rw-r--r--tests/auto/declarative/qmlecmascript/data/deferredProperties.qml10
-rw-r--r--tests/auto/declarative/qmlecmascript/data/deletedObject.qml25
-rw-r--r--tests/auto/declarative/qmlecmascript/data/dynamicCreation.helper.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/dynamicCreation.qml21
-rw-r--r--tests/auto/declarative/qmlecmascript/data/dynamicDeletion.qml20
-rw-r--r--tests/auto/declarative/qmlecmascript/data/enums.1.qml20
-rw-r--r--tests/auto/declarative/qmlecmascript/data/enums.2.qml8
-rw-r--r--tests/auto/declarative/qmlecmascript/data/exceptionClearsOnReeval.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning.qml8
-rw-r--r--tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning2.qml7
-rw-r--r--tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml8
-rw-r--r--tests/auto/declarative/qmlecmascript/data/extensionObjects.qml10
-rw-r--r--tests/auto/declarative/qmlecmascript/data/externalScript.1.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/externalScript.2.js8
-rw-r--r--tests/auto/declarative/qmlecmascript/data/externalScript.2.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/externalScript.3.qml13
-rw-r--r--tests/auto/declarative/qmlecmascript/data/externalScript.4.qml15
-rw-r--r--tests/auto/declarative/qmlecmascript/data/externalScript.js6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.1.qml13
-rw-r--r--tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.qml12
-rw-r--r--tests/auto/declarative/qmlecmascript/data/jsObject.qml12
-rw-r--r--tests/auto/declarative/qmlecmascript/data/listProperties.qml44
-rw-r--r--tests/auto/declarative/qmlecmascript/data/listToVariant.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/methods.1.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/methods.2.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/methods.3.qml7
-rw-r--r--tests/auto/declarative/qmlecmascript/data/methods.4.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/methods.5.qml9
-rw-r--r--tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/nonExistantAttachedObject.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml15
-rw-r--r--tests/auto/declarative/qmlecmascript/data/outerBindingOverridesInnerBinding.qml14
-rw-r--r--tests/auto/declarative/qmlecmascript/data/qmlToString.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scope.2.qml42
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scope.qml48
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptAccess.js7
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptAccess.qml17
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptErrors.js2
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptErrors.qml17
-rw-r--r--tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml17
-rw-r--r--tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml18
-rw-r--r--tests/auto/declarative/qmlecmascript/data/shutdownErrors.qml13
-rw-r--r--tests/auto/declarative/qmlecmascript/data/signalAssignment.1.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/signalAssignment.2.qml5
-rw-r--r--tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml16
-rw-r--r--tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml20
-rw-r--r--tests/auto/declarative/qmlecmascript/data/transientErrors.qml10
-rw-r--r--tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.2.qml10
-rw-r--r--tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.qml7
-rw-r--r--tests/auto/declarative/qmlecmascript/data/valueTypeFunctions.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/qmlecmascript.pro10
-rw-r--r--tests/auto/declarative/qmlecmascript/testtypes.cpp82
-rw-r--r--tests/auto/declarative/qmlecmascript/testtypes.h595
-rw-r--r--tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp1663
-rw-r--r--tests/auto/declarative/qmlengine/qmlengine.pro8
-rw-r--r--tests/auto/declarative/qmlengine/tst_qmlengine.cpp240
-rw-r--r--tests/auto/declarative/qmlerror/qmlerror.pro6
-rw-r--r--tests/auto/declarative/qmlerror/test.txt3
-rw-r--r--tests/auto/declarative/qmlerror/tst_qmlerror.cpp242
-rw-r--r--tests/auto/declarative/qmlfontloader/data/dummy.ttf0
-rw-r--r--tests/auto/declarative/qmlfontloader/data/tarzeau_ocr_a.ttfbin0 -> 24544 bytes-rw-r--r--tests/auto/declarative/qmlfontloader/qmlfontloader.pro8
-rw-r--r--tests/auto/declarative/qmlfontloader/tst_qmlfontloader.cpp156
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/data/anchors.qml162
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/data/centerin.qml12
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/data/crash1.qml11
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/data/fill.qml14
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/data/loop1.qml8
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/data/loop2.qml20
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/data/margins.qml13
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/qmlgraphicsanchors.pro6
-rw-r--r--tests/auto/declarative/qmlgraphicsanchors/tst_qmlgraphicsanchors.cpp459
-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.gifbin0 -> 505 bytes-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.gifbin0 -> 164923 bytes-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanpause.qml7
-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanstopped.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/qmlgraphicsanimatedimage.pro7
-rw-r--r--tests/auto/declarative/qmlgraphicsanimatedimage/tst_qmlgraphicsanimatedimage.cpp191
-rw-r--r--tests/auto/declarative/qmlgraphicsborderimage/data/colors-round.sci7
-rw-r--r--tests/auto/declarative/qmlgraphicsborderimage/data/colors.pngbin0 -> 1655 bytes-rw-r--r--tests/auto/declarative/qmlgraphicsborderimage/data/invalid.sci7
-rw-r--r--tests/auto/declarative/qmlgraphicsborderimage/qmlgraphicsborderimage.pro9
-rw-r--r--tests/auto/declarative/qmlgraphicsborderimage/tst_qmlgraphicsborderimage.cpp351
-rw-r--r--tests/auto/declarative/qmlgraphicsflickable/data/flickable01.qml4
-rw-r--r--tests/auto/declarative/qmlgraphicsflickable/data/flickable02.qml14
-rw-r--r--tests/auto/declarative/qmlgraphicsflickable/data/flickable03.qml14
-rw-r--r--tests/auto/declarative/qmlgraphicsflickable/data/flickable04.qml16
-rw-r--r--tests/auto/declarative/qmlgraphicsflickable/qmlgraphicsflickable.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicsflickable/tst_qmlgraphicsflickable.cpp145
-rw-r--r--tests/auto/declarative/qmlgraphicsflipable/data/test-flipable.qml9
-rw-r--r--tests/auto/declarative/qmlgraphicsflipable/qmlgraphicsflipable.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicsflipable/tst_qmlgraphicsflipable.cpp113
-rw-r--r--tests/auto/declarative/qmlgraphicsgridview/data/gridview-initCurrent.qml51
-rw-r--r--tests/auto/declarative/qmlgraphicsgridview/data/gridview.qml50
-rw-r--r--tests/auto/declarative/qmlgraphicsgridview/data/gridview2.qml26
-rw-r--r--tests/auto/declarative/qmlgraphicsgridview/data/gridview3.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicsgridview/qmlgraphicsgridview.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicsgridview/tst_qmlgraphicsgridview.cpp989
-rw-r--r--tests/auto/declarative/qmlgraphicsimage/data/colors.pngbin0 -> 1655 bytes-rw-r--r--tests/auto/declarative/qmlgraphicsimage/qmlgraphicsimage.pro9
-rw-r--r--tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp247
-rw-r--r--tests/auto/declarative/qmlgraphicsitem/data/keynavigation.qml39
-rw-r--r--tests/auto/declarative/qmlgraphicsitem/data/keys.qml18
-rw-r--r--tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro7
-rw-r--r--tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp271
-rw-r--r--tests/auto/declarative/qmlgraphicslistview/data/itemlist.qml43
-rw-r--r--tests/auto/declarative/qmlgraphicslistview/data/listview-enforcerange.qml55
-rw-r--r--tests/auto/declarative/qmlgraphicslistview/data/listview-initCurrent.qml50
-rw-r--r--tests/auto/declarative/qmlgraphicslistview/data/listview-sections.qml59
-rw-r--r--tests/auto/declarative/qmlgraphicslistview/data/listview.qml119
-rw-r--r--tests/auto/declarative/qmlgraphicslistview/qmlgraphicslistview.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp1378
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/GraphicsWidget250x250.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/NoResize.qml7
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/NoResizeGraphicsWidget.qml8
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/Rect120x60.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/SetSourceComponent.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/SizeGraphicsWidgetToLoader.qml8
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/SizeLoaderToGraphicsWidget.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/SizeToItem.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/data/SizeToLoader.qml7
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/qmlgraphicsloader.pro11
-rw-r--r--tests/auto/declarative/qmlgraphicsloader/tst_qmlgraphicsloader.cpp456
-rw-r--r--tests/auto/declarative/qmlgraphicsparticles/data/particle.pngbin0 -> 262 bytes-rw-r--r--tests/auto/declarative/qmlgraphicsparticles/data/particles.qml15
-rw-r--r--tests/auto/declarative/qmlgraphicsparticles/qmlgraphicsparticles.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicsparticles/tst_qmlgraphicsparticles.cpp125
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/data/datamodel.qml36
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/data/path.qml14
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/data/pathview.qml66
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/data/pathview1.qml4
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/data/pathview2.qml57
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/data/pathview3.qml57
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/qmlgraphicspathview.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp494
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/grid-animated.qml60
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/grid-spacing.qml40
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/grid.qml39
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/horizontal-animated.qml40
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/horizontal-spacing.qml27
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/horizontal.qml26
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/repeater.qml20
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/vertical-animated.qml40
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/vertical-spacing.qml27
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/data/vertical.qml26
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/qmlgraphicspositioners.pro7
-rw-r--r--tests/auto/declarative/qmlgraphicspositioners/tst_qmlgraphicspositioners.cpp427
-rw-r--r--tests/auto/declarative/qmlgraphicsrepeater/data/intmodel.qml29
-rw-r--r--tests/auto/declarative/qmlgraphicsrepeater/data/itemlist.qml49
-rw-r--r--tests/auto/declarative/qmlgraphicsrepeater/data/objlist.qml21
-rw-r--r--tests/auto/declarative/qmlgraphicsrepeater/data/repeater.qml28
-rw-r--r--tests/auto/declarative/qmlgraphicsrepeater/data/repeater2.qml35
-rw-r--r--tests/auto/declarative/qmlgraphicsrepeater/qmlgraphicsrepeater.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicsrepeater/tst_qmlgraphicsrepeater.cpp354
-rw-r--r--tests/auto/declarative/qmlgraphicstext/qmlgraphicstext.pro5
-rw-r--r--tests/auto/declarative/qmlgraphicstext/tst_qmlgraphicstext.cpp844
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/cursorTest.qml8
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/http/ErrItem.qml7
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/http/NormItem.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTest.qml22
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail1.qml18
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail2.qml18
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestPass.qml18
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/httpfail/FailItem.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/httpslow/WaitItem.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/inputmethodhints.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/navigation.qml23
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/data/readOnly.qml12
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/qmlgraphicstextedit.pro9
-rw-r--r--tests/auto/declarative/qmlgraphicstextedit/tst_qmlgraphicstextedit.cpp807
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/data/cursorTest.qml8
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/data/inputmethodhints.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/data/masks.qml7
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/data/maxLength.qml7
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/data/navigation.qml23
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/data/readOnly.qml12
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/data/validators.qml23
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/qmlgraphicstextinput.pro8
-rw-r--r--tests/auto/declarative/qmlgraphicstextinput/tst_qmlgraphicstextinput.cpp655
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/basic.html17
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/basic.icobin0 -> 318 bytes-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/basic.pngbin0 -> 3961 bytes-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/basic.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/elements.html14
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/elements.qml7
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/forward.html12
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/javaScript.html11
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/javaScript.qml11
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/loadError.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/newwindows.html16
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/newwindows.qml32
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/pixelCache.html10
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/pixelCache.qml6
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/data/sethtml.qml5
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/qmlgraphicswebview.pro10
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/testtypes.cpp49
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/testtypes.h64
-rw-r--r--tests/auto/declarative/qmlgraphicswebview/tst_qmlgraphicswebview.cpp393
-rw-r--r--tests/auto/declarative/qmlinfo/data/NestedObject.qml8
-rw-r--r--tests/auto/declarative/qmlinfo/data/nestedQmlObject.qml8
-rw-r--r--tests/auto/declarative/qmlinfo/data/qmlObject.qml8
-rw-r--r--tests/auto/declarative/qmlinfo/qmlinfo.pro7
-rw-r--r--tests/auto/declarative/qmlinfo/tst_qmlinfo.cpp139
-rw-r--r--tests/auto/declarative/qmlinstruction/qmlinstruction.pro6
-rw-r--r--tests/auto/declarative/qmlinstruction/tst_qmlinstruction.cpp603
-rw-r--r--tests/auto/declarative/qmllanguage/data/Alias.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/Alias2.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/Alias3.qml12
-rw-r--r--tests/auto/declarative/qmllanguage/data/Alias4.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/ComponentComposite.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/CompositeType.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/CompositeType2.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/CompositeType3.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/CompositeType4.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/DynamicPropertiesNestedType.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/HelperAlias.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/I18n.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/I18nType30.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/MyComponent.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/MyCompositeValueSource.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/MyContainerComponent.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/NestedAlias.qml14
-rw-r--r--tests/auto/declarative/qmllanguage/data/NestedErrorsType.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/OnCompletedType.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.1.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.2.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.3.qml10
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.4.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.5.qml13
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.6.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.7.qml14
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.8.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.9.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignBasicTypes.qml29
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml18
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignLiteralSignalProperty.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignObjectToSignal.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignObjectToVariant.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignQmlComponent.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignSignal.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignTypeExtremes.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/attachedProperties.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/autoComponentCreation.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.1.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.2.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.3.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.4.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.5.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/component.6.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/componentCompositeType.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/cppnamespace.2.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/cppnamespace.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/crash2.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/customParserTypes.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/customVariantTypes.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/declaredPropertyValues.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/defaultGrouped.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/defaultGrouped.qml10
-rw-r--r--tests/auto/declarative/qmllanguage/data/defaultPropertyListOrder.qml29
-rw-r--r--tests/auto/declarative/qmllanguage/data/doubleSignal.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/doubleSignal.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/duplicateIDs.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/duplicateIDs.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/dynamicObject.1.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml13
-rw-r--r--tests/auto/declarative/qmllanguage/data/dynamicProperties.qml14
-rw-r--r--tests/auto/declarative/qmllanguage/data/dynamicPropertiesNested.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/dynamicSignalsAndSlots.qml10
-rw-r--r--tests/auto/declarative/qmllanguage/data/empty.errors.txt2
-rw-r--r--tests/auto/declarative/qmllanguage/data/empty.qml0
-rw-r--r--tests/auto/declarative/qmllanguage/data/emptySignal.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/emptySignal.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/failingComponent.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/failingComponentTest.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/fakeDotProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/fakeDotProperty.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/finalOverride.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/finalOverride.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml3
-rw-r--r--tests/auto/declarative/qmllanguage/data/i18nNameSpace.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/i18nScript.qml12
-rw-r--r--tests/auto/declarative/qmllanguage/data/i18nStrings.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/i18nType.qml1
-rw-r--r--tests/auto/declarative/qmllanguage/data/idProperty.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/importNamespaceConflict.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/importNamespaceConflict.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.qml3
-rw-r--r--tests/auto/declarative/qmllanguage/data/inlineQmlComponents.qml10
-rw-r--r--tests/auto/declarative/qmllanguage/data/interfaceProperty.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/interfaceQList.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/interfaceQmlList.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.2.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.3.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.4.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.5.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.6.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidID.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidImportID.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidImportID.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidRoot.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/invalidRoot.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest2.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/PrivateType.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/qmldir4
-rw-r--r--tests/auto/declarative/qmllanguage/data/listAssignment.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/listAssignment.1.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/listAssignment.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmllanguage/data/listAssignment.2.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/listAssignment.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/listAssignment.3.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/listItemDeleteSelf.qml38
-rw-r--r--tests/auto/declarative/qmllanguage/data/listProperties.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/missingObject.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/missingObject.qml1
-rw-r--r--tests/auto/declarative/qmllanguage/data/missingSignal.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/missingSignal.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/nestedErrors.errors.txt2
-rw-r--r--tests/auto/declarative/qmllanguage/data/nestedErrors.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/nullDotProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/nullDotProperty.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/onCompleted.qml17
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.1.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.2.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.3.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.4.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/property.5.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/propertyValueSource.2.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/propertyValueSource.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/readOnly.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/readOnly.1.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/readOnly.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/readOnly.2.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/readOnly.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/readOnly.3.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/rootAsQmlComponent.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.1.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.10.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.10.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.11.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.11.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.12.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.12.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.2.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.3.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.4.qml8
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.5.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.6.qml11
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.7.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.7.qml11
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.8.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.8.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.9.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/script.9.qml7
-rw-r--r--tests/auto/declarative/qmllanguage/data/scriptString.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/signal.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/signal.1.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/signal.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/signal.2.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/signal.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/signal.3.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/data/simpleBindings.qml18
-rw-r--r--tests/auto/declarative/qmllanguage/data/simpleContainer.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/simpleObject.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/subdir/Test.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/subdir/subsubdir/SubTest.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/test.js0
-rw-r--r--tests/auto/declarative/qmllanguage/data/test2.js0
-rw-r--r--tests/auto/declarative/qmllanguage/data/unregisteredObject.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/unregisteredObject.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/unsupportedProperty.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/valueTypes.qml13
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.1.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.1.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.10.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.10.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.11.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.11.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.12.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.12.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.13.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.13.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.14.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.14.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.15.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.15.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.2.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.2.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.3.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.3.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.4.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.4.qml4
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.5.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.5.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.6.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.6.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.7.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.7.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.8.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.8.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.9.errors.txt1
-rw-r--r--tests/auto/declarative/qmllanguage/data/wrongType.9.qml5
-rw-r--r--tests/auto/declarative/qmllanguage/qmllanguage.pro14
-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/LocalInternal.qml3
-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/Test.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestLocal.qml1
-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestSubDir.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/pics/blue.pngbin0 -> 84 bytes-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/qmldir3
-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/SubTest.qml3
-rw-r--r--tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/qmldir1
-rw-r--r--tests/auto/declarative/qmllanguage/testtypes.cpp59
-rw-r--r--tests/auto/declarative/qmllanguage/testtypes.h548
-rw-r--r--tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp1396
-rw-r--r--tests/auto/declarative/qmllist/qmllist.pro5
-rw-r--r--tests/auto/declarative/qmllist/tst_qmllist.cpp78
-rw-r--r--tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro5
-rw-r--r--tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp452
-rw-r--r--tests/auto/declarative/qmllistmodel/qmllistmodel.pro6
-rw-r--r--tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp283
-rw-r--r--tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro5
-rw-r--r--tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp1123
-rw-r--r--tests/auto/declarative/qmlmetatype/qmlmetatype.pro6
-rw-r--r--tests/auto/declarative/qmlmetatype/tst_qmlmetatype.cpp445
-rw-r--r--tests/auto/declarative/qmlmoduleplugin/plugin.qml3
-rw-r--r--tests/auto/declarative/qmlmoduleplugin/plugin/plugin.cpp84
-rw-r--r--tests/auto/declarative/qmlmoduleplugin/plugin/plugin.pro5
-rw-r--r--tests/auto/declarative/qmlmoduleplugin/qmlmoduleplugin.pro7
-rw-r--r--tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.cpp117
-rw-r--r--tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.pro4
-rw-r--r--tests/auto/declarative/qmlnumberformatter/qmlnumberformatter.pro5
-rw-r--r--tests/auto/declarative/qmlnumberformatter/tst_qmlnumberformatter.cpp222
-rw-r--r--tests/auto/declarative/qmlpixmapcache/data/exists.pngbin0 -> 2738 bytes-rw-r--r--tests/auto/declarative/qmlpixmapcache/data/exists1.pngbin0 -> 2738 bytes-rw-r--r--tests/auto/declarative/qmlpixmapcache/data/exists2.pngbin0 -> 2738 bytes-rw-r--r--tests/auto/declarative/qmlpixmapcache/qmlpixmapcache.pro9
-rw-r--r--tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp282
-rw-r--r--tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro5
-rw-r--r--tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp171
-rw-r--r--tests/auto/declarative/qmlqt/data/closestangle.qml12
-rw-r--r--tests/auto/declarative/qmlqt/data/consoleLog.qml8
-rw-r--r--tests/auto/declarative/qmlqt/data/createComponent.qml23
-rw-r--r--tests/auto/declarative/qmlqt/data/createComponentData.qml5
-rw-r--r--tests/auto/declarative/qmlqt/data/createQmlObject.qml31
-rw-r--r--tests/auto/declarative/qmlqt/data/darker.qml11
-rw-r--r--tests/auto/declarative/qmlqt/data/enums.qml9
-rw-r--r--tests/auto/declarative/qmlqt/data/hsla.qml11
-rw-r--r--tests/auto/declarative/qmlqt/data/lighter.qml10
-rw-r--r--tests/auto/declarative/qmlqt/data/md5.qml6
-rw-r--r--tests/auto/declarative/qmlqt/data/point.qml9
-rw-r--r--tests/auto/declarative/qmlqt/data/rect.qml9
-rw-r--r--tests/auto/declarative/qmlqt/data/rgba.qml10
-rw-r--r--tests/auto/declarative/qmlqt/data/size.qml11
-rw-r--r--tests/auto/declarative/qmlqt/data/tint.qml9
-rw-r--r--tests/auto/declarative/qmlqt/data/vector.qml8
-rw-r--r--tests/auto/declarative/qmlqt/qmlqt.pro9
-rw-r--r--tests/auto/declarative/qmlqt/tst_qmlqt.cpp369
-rw-r--r--tests/auto/declarative/qmlspringfollow/data/springfollow1.qml4
-rw-r--r--tests/auto/declarative/qmlspringfollow/data/springfollow2.qml8
-rw-r--r--tests/auto/declarative/qmlspringfollow/data/springfollow3.qml8
-rw-r--r--tests/auto/declarative/qmlspringfollow/qmlspringfollow.pro8
-rw-r--r--tests/auto/declarative/qmlspringfollow/tst_qmlspringfollow.cpp137
-rw-r--r--tests/auto/declarative/qmlstates/data/ExtendedRectangle.qml19
-rw-r--r--tests/auto/declarative/qmlstates/data/anchorChanges.qml23
-rw-r--r--tests/auto/declarative/qmlstates/data/anchorChanges2.qml21
-rw-r--r--tests/auto/declarative/qmlstates/data/anchorChanges3.qml29
-rw-r--r--tests/auto/declarative/qmlstates/data/anchorChanges4.qml22
-rw-r--r--tests/auto/declarative/qmlstates/data/anchorChanges5.qml22
-rw-r--r--tests/auto/declarative/qmlstates/data/autoStateAtStartupRestoreBug.qml18
-rw-r--r--tests/auto/declarative/qmlstates/data/basicBinding.qml12
-rw-r--r--tests/auto/declarative/qmlstates/data/basicBinding2.qml12
-rw-r--r--tests/auto/declarative/qmlstates/data/basicBinding3.qml13
-rw-r--r--tests/auto/declarative/qmlstates/data/basicBinding4.qml17
-rw-r--r--tests/auto/declarative/qmlstates/data/basicChanges.qml10
-rw-r--r--tests/auto/declarative/qmlstates/data/basicChanges2.qml15
-rw-r--r--tests/auto/declarative/qmlstates/data/basicChanges3.qml15
-rw-r--r--tests/auto/declarative/qmlstates/data/basicExtension.qml16
-rw-r--r--tests/auto/declarative/qmlstates/data/deleting.qml11
-rw-r--r--tests/auto/declarative/qmlstates/data/deletingState.qml13
-rw-r--r--tests/auto/declarative/qmlstates/data/explicit.qml15
-rw-r--r--tests/auto/declarative/qmlstates/data/fakeExtension.qml16
-rw-r--r--tests/auto/declarative/qmlstates/data/illegalTempState.qml21
-rw-r--r--tests/auto/declarative/qmlstates/data/legalTempState.qml23
-rw-r--r--tests/auto/declarative/qmlstates/data/nonExistantProp.qml11
-rw-r--r--tests/auto/declarative/qmlstates/data/parentChange.qml37
-rw-r--r--tests/auto/declarative/qmlstates/data/parentChange2.qml31
-rw-r--r--tests/auto/declarative/qmlstates/data/parentChange3.qml42
-rw-r--r--tests/auto/declarative/qmlstates/data/parentChange4.qml30
-rw-r--r--tests/auto/declarative/qmlstates/data/parentChange5.qml30
-rw-r--r--tests/auto/declarative/qmlstates/data/propertyErrors.qml10
-rw-r--r--tests/auto/declarative/qmlstates/data/restoreEntryValues.qml14
-rw-r--r--tests/auto/declarative/qmlstates/data/script.qml10
-rw-r--r--tests/auto/declarative/qmlstates/data/signalOverride.qml18
-rw-r--r--tests/auto/declarative/qmlstates/data/signalOverride2.qml9
-rw-r--r--tests/auto/declarative/qmlstates/data/signalOverrideCrash.qml15
-rw-r--r--tests/auto/declarative/qmlstates/qmlstates.pro8
-rw-r--r--tests/auto/declarative/qmlstates/tst_qmlstates.cpp887
-rw-r--r--tests/auto/declarative/qmlsystempalette/qmlsystempalette.pro5
-rw-r--r--tests/auto/declarative/qmlsystempalette/tst_qmlsystempalette.cpp187
-rw-r--r--tests/auto/declarative/qmltimer/qmltimer.pro7
-rw-r--r--tests/auto/declarative/qmltimer/tst_qmltimer.cpp285
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.2.qml9
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.3.qml10
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.qml9
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/bindingAssignment.qml7
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/bindingConflict.qml8
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/bindingRead.qml5
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/bindingVariantCopy.qml13
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/deletedObject.js13
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/deletedObject.qml12
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/font_read.qml18
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/font_write.2.qml6
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/font_write.3.qml7
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/font_write.qml16
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/point_read.qml7
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/point_write.qml6
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/pointf_read.qml8
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/pointf_write.qml6
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/rect_read.qml10
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/rect_write.qml9
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/rectf_read.qml10
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/rectf_write.qml9
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/scriptAccess.qml9
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/scriptVariantCopy.qml14
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/size_read.qml8
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/size_write.qml7
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/sizef_read.qml9
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/sizef_write.qml6
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/staticAssignment.qml5
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/valueInterceptors.qml8
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/valueSources.qml5
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/vector3d_read.qml9
-rw-r--r--tests/auto/declarative/qmlvaluetypes/data/vector3d_write.qml8
-rw-r--r--tests/auto/declarative/qmlvaluetypes/qmlvaluetypes.pro10
-rw-r--r--tests/auto/declarative/qmlvaluetypes/testtypes.cpp45
-rw-r--r--tests/auto/declarative/qmlvaluetypes/testtypes.h152
-rw-r--r--tests/auto/declarative/qmlvaluetypes/tst_qmlvaluetypes.cpp588
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/abort.expect10
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/abort.qml42
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/abort.reply2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/abort_opened.qml58
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/abort_unsent.qml54
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/attr.qml80
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/attr.xml1
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/callbackException.qml25
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/cdata.qml135
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/cdata.xml2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/constructor.qml14
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/defaultState.qml30
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/document.qml58
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/document.xml3
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/domExceptionCodes.qml60
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/element.qml147
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/element.xml1
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders.qml65
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_args.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_sent.qml20
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_unsent.qml16
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.expect7
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.qml75
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.reply7
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_args.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_sent.qml20
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_unsent.qml16
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/instanceStateValues.qml33
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/invalidMethodUsage.qml160
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open.qml53
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.1.qml18
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.2.qml18
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_invalid_method.qml16
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_network.expect7
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_network.reply2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_network.wait0
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_sync.qml17
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_user.qml53
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/open_username.qml54
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/redirectError.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/redirectRecur.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/redirects.qml22
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/redirecttarget.html1
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/responseText.qml52
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/responseXML_invalid.qml24
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/seconddocument.html1
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_alreadySent.qml27
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.expect10
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.qml21
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.2.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.3.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.expect10
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.5.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.expect10
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.qml21
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.7.qml23
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_data.reply2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.qml26
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.reply2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_GET.expect7
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_PUT.expect7
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/send_unsent.qml16
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.expect9
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.qml28
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.reply2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_args.qml18
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_illegalName.qml57
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_sent.qml31
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_unsent.qml17
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/staticStateValues.qml24
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/status.200.reply2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/status.404.reply2
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/status.expect7
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/status.qml77
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/statusText.qml77
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/testdocument.html1
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/text.qml131
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/data/text.xml1
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/qmlxmlhttprequest.pro13
-rw-r--r--tests/auto/declarative/qmlxmlhttprequest/tst_qmlxmlhttprequest.cpp1315
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/data/model.qml10
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/data/model.xml54
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/data/model2.qml11
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/data/recipes.qml10
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/data/recipes.xml90
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/data/roleErrors.qml10
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/data/unique.qml8
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/qmlxmllistmodel.pro11
-rw-r--r--tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp203
-rw-r--r--tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro7
-rw-r--r--tests/auto/declarative/qpacketprotocol/tst_qpacketprotocol.cpp271
-rwxr-xr-xtests/auto/declarative/runall.sh30
-rw-r--r--tests/auto/declarative/shared/debugutil.cpp176
-rw-r--r--tests/auto/declarative/shared/debugutil_p.h145
-rw-r--r--tests/auto/declarative/shared/testhttpserver.cpp323
-rw-r--r--tests/auto/declarative/shared/testhttpserver.h93
-rw-r--r--tests/auto/declarative/sql/data/README3
-rw-r--r--tests/auto/declarative/sql/data/changeversion.js53
-rw-r--r--tests/auto/declarative/sql/data/creation-a.js18
-rw-r--r--tests/auto/declarative/sql/data/creation.js14
-rw-r--r--tests/auto/declarative/sql/data/error-a.js20
-rw-r--r--tests/auto/declarative/sql/data/error-b.js13
-rw-r--r--tests/auto/declarative/sql/data/error-creation.js12
-rw-r--r--tests/auto/declarative/sql/data/error-notransaction.js15
-rw-r--r--tests/auto/declarative/sql/data/error-outsidetransaction.js17
-rw-r--r--tests/auto/declarative/sql/data/iteration-forwardonly.js29
-rw-r--r--tests/auto/declarative/sql/data/iteration.js28
-rw-r--r--tests/auto/declarative/sql/data/readonly-error.js27
-rw-r--r--tests/auto/declarative/sql/data/readonly.js24
-rw-r--r--tests/auto/declarative/sql/data/reopen1.js14
-rw-r--r--tests/auto/declarative/sql/data/reopen2.js16
-rw-r--r--tests/auto/declarative/sql/data/selection-bindnames.js26
-rw-r--r--tests/auto/declarative/sql/data/selection.js26
-rw-r--r--tests/auto/declarative/sql/sql.pro9
-rw-r--r--tests/auto/declarative/sql/tst_sql.cpp237
-rw-r--r--tests/auto/declarative/visual/ListView/basic1.qml27
-rw-r--r--tests/auto/declarative/visual/ListView/basic2.qml31
-rw-r--r--tests/auto/declarative/visual/ListView/basic3.qml29
-rw-r--r--tests/auto/declarative/visual/ListView/basic4.qml33
-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/basic1.qml159
-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/basic2.qml187
-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/basic3.qml147
-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/basic4.qml171
-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.0.pngbin0 -> 961 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.1.pngbin0 -> 972 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.2.pngbin0 -> 962 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.3.pngbin0 -> 962 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.4.pngbin0 -> 962 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.5.pngbin0 -> 970 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.6.pngbin0 -> 961 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/itemlist.qml2203
-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.0.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.1.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.10.pngbin0 -> 1588 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.11.pngbin0 -> 1575 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.12.pngbin0 -> 1502 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.13.pngbin0 -> 1583 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.14.pngbin0 -> 1681 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.15.pngbin0 -> 1524 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.16.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.17.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.18.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.19.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.2.pngbin0 -> 1627 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.3.pngbin0 -> 1524 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.4.pngbin0 -> 1678 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.5.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.6.pngbin0 -> 1573 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.7.pngbin0 -> 1670 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.8.pngbin0 -> 1658 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.9.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data-MAC/listview.qml3079
-rw-r--r--tests/auto/declarative/visual/ListView/data-X11/basic1.qml159
-rw-r--r--tests/auto/declarative/visual/ListView/data-X11/basic2.qml187
-rw-r--r--tests/auto/declarative/visual/ListView/data-X11/basic3.qml147
-rw-r--r--tests/auto/declarative/visual/ListView/data-X11/basic4.qml171
-rw-r--r--tests/auto/declarative/visual/ListView/data/basic1.qml159
-rw-r--r--tests/auto/declarative/visual/ListView/data/basic2.qml187
-rw-r--r--tests/auto/declarative/visual/ListView/data/basic3.qml147
-rw-r--r--tests/auto/declarative/visual/ListView/data/basic4.qml171
-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.0.pngbin0 -> 961 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.1.pngbin0 -> 972 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.2.pngbin0 -> 962 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.3.pngbin0 -> 962 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.4.pngbin0 -> 962 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.5.pngbin0 -> 970 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.6.pngbin0 -> 961 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/itemlist.qml2203
-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.0.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.1.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.10.pngbin0 -> 1588 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.11.pngbin0 -> 1575 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.12.pngbin0 -> 1502 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.13.pngbin0 -> 1583 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.14.pngbin0 -> 1681 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.15.pngbin0 -> 1524 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.16.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.17.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.18.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.19.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.2.pngbin0 -> 1656 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.3.pngbin0 -> 1524 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.4.pngbin0 -> 1678 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.5.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.6.pngbin0 -> 1573 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.7.pngbin0 -> 1669 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.8.pngbin0 -> 1658 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.9.pngbin0 -> 1510 bytes-rw-r--r--tests/auto/declarative/visual/ListView/data/listview.qml3079
-rw-r--r--tests/auto/declarative/visual/ListView/itemlist.qml40
-rw-r--r--tests/auto/declarative/visual/ListView/listview.qml81
-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.0.pngbin0 -> 714 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.1.pngbin0 -> 798 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.10.pngbin0 -> 773 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.11.pngbin0 -> 773 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.12.pngbin0 -> 754 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.13.pngbin0 -> 742 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.14.pngbin0 -> 733 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.15.pngbin0 -> 712 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.16.pngbin0 -> 730 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.17.pngbin0 -> 730 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.18.pngbin0 -> 730 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.19.pngbin0 -> 744 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.2.pngbin0 -> 757 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.20.pngbin0 -> 754 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.21.pngbin0 -> 721 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.22.pngbin0 -> 732 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.3.pngbin0 -> 813 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.4.pngbin0 -> 756 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.5.pngbin0 -> 752 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.6.pngbin0 -> 752 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.7.pngbin0 -> 774 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.8.pngbin0 -> 774 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.9.pngbin0 -> 754 bytes-rw-r--r--tests/auto/declarative/visual/Package_Views/data/packageviews.qml3751
-rw-r--r--tests/auto/declarative/visual/Package_Views/packageviews.qml89
-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/bindinganimation.qml40
-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.0.pngbin0 -> 817 bytes-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.1.pngbin0 -> 815 bytes-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.2.pngbin0 -> 817 bytes-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.3.pngbin0 -> 815 bytes-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.4.pngbin0 -> 813 bytes-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.5.pngbin0 -> 815 bytes-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.6.pngbin0 -> 817 bytes-rw-r--r--tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.qml1655
-rw-r--r--tests/auto/declarative/visual/animation/colorAnimation/colorAnimation.qml41
-rw-r--r--tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.0.pngbin0 -> 610 bytes-rw-r--r--tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.1.pngbin0 -> 610 bytes-rw-r--r--tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.2.pngbin0 -> 610 bytes-rw-r--r--tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.qml951
-rw-r--r--tests/auto/declarative/visual/animation/easing/data/easing.0.pngbin0 -> 3393 bytes-rw-r--r--tests/auto/declarative/visual/animation/easing/data/easing.1.pngbin0 -> 3381 bytes-rw-r--r--tests/auto/declarative/visual/animation/easing/data/easing.2.pngbin0 -> 3101 bytes-rw-r--r--tests/auto/declarative/visual/animation/easing/data/easing.3.pngbin0 -> 16542 bytes-rw-r--r--tests/auto/declarative/visual/animation/easing/data/easing.qml779
-rw-r--r--tests/auto/declarative/visual/animation/easing/easing.qml193
-rw-r--r--tests/auto/declarative/visual/animation/easing/pics/qtlogo.pngbin0 -> 2738 bytes-rw-r--r--tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.0.pngbin0 -> 774 bytes-rw-r--r--tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.1.pngbin0 -> 762 bytes-rw-r--r--tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.2.pngbin0 -> 773 bytes-rw-r--r--tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.qml463
-rw-r--r--tests/auto/declarative/visual/animation/parallelAnimation/parallelAnimation.qml43
-rw-r--r--tests/auto/declarative/visual/animation/parentAction/data/parentAction.0.pngbin0 -> 1652 bytes-rw-r--r--tests/auto/declarative/visual/animation/parentAction/data/parentAction.1.pngbin0 -> 1492 bytes-rw-r--r--tests/auto/declarative/visual/animation/parentAction/data/parentAction.2.pngbin0 -> 1424 bytes-rw-r--r--tests/auto/declarative/visual/animation/parentAction/data/parentAction.3.pngbin0 -> 1583 bytes-rw-r--r--tests/auto/declarative/visual/animation/parentAction/data/parentAction.4.pngbin0 -> 1640 bytes-rw-r--r--tests/auto/declarative/visual/animation/parentAction/data/parentAction.5.pngbin0 -> 1640 bytes-rw-r--r--tests/auto/declarative/visual/animation/parentAction/data/parentAction.qml1207
-rw-r--r--tests/auto/declarative/visual/animation/parentAction/parentAction.qml55
-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.0.pngbin0 -> 3211 bytes-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.1.pngbin0 -> 3214 bytes-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.2.pngbin0 -> 3209 bytes-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.3.pngbin0 -> 3211 bytes-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.4.pngbin0 -> 3214 bytes-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.5.pngbin0 -> 3214 bytes-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.qml1619
-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/pauseAnimation.qml29
-rw-r--r--tests/auto/declarative/visual/animation/pauseAnimation/pics/qtlogo.pngbin0 -> 2738 bytes-rw-r--r--tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.0.pngbin0 -> 1418 bytes-rw-r--r--tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.1.pngbin0 -> 1430 bytes-rw-r--r--tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.2.pngbin0 -> 1431 bytes-rw-r--r--tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.qml939
-rw-r--r--tests/auto/declarative/visual/animation/propertyAction/propertyAction.qml34
-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.0.pngbin0 -> 622 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.1.pngbin0 -> 626 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.2.pngbin0 -> 622 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.3.pngbin0 -> 622 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.4.pngbin0 -> 632 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.5.pngbin0 -> 622 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.6.pngbin0 -> 622 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.7.pngbin0 -> 622 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.8.pngbin0 -> 634 bytes-rw-r--r--tests/auto/declarative/visual/animation/reanchor/data/reanchor.qml2471
-rw-r--r--tests/auto/declarative/visual/animation/reanchor/reanchor.qml68
-rw-r--r--tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.0.pngbin0 -> 1418 bytes-rw-r--r--tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.1.pngbin0 -> 1431 bytes-rw-r--r--tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.qml535
-rw-r--r--tests/auto/declarative/visual/animation/scriptAction/scriptAction.qml35
-rw-r--r--tests/auto/declarative/visual/fillmode/data/fillmode.0.pngbin0 -> 26099 bytes-rw-r--r--tests/auto/declarative/visual/fillmode/data/fillmode.qml279
-rw-r--r--tests/auto/declarative/visual/fillmode/face.pngbin0 -> 905 bytes-rw-r--r--tests/auto/declarative/visual/fillmode/fillmode.qml16
-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test.0.pngbin0 -> 14875 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test.1.pngbin0 -> 14875 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test.2.pngbin0 -> 14863 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test.3.pngbin0 -> 14877 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test.4.pngbin0 -> 14877 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test.5.pngbin0 -> 14877 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test.qml1599
-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test2.0.pngbin0 -> 5375 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test2.1.pngbin0 -> 5375 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test2.qml607
-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.0.pngbin0 -> 12749 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.1.pngbin0 -> 12667 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.2.pngbin0 -> 12373 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.3.pngbin0 -> 12150 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.4.pngbin0 -> 11944 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.5.pngbin0 -> 12150 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.6.pngbin0 -> 12373 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.7.pngbin0 -> 12667 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.8.pngbin0 -> 12749 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.9.pngbin0 -> 12710 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-MAC/test3.qml2879
-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test.0.pngbin0 -> 11501 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test.1.pngbin0 -> 11501 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test.2.pngbin0 -> 11486 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test.3.pngbin0 -> 11500 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test.4.pngbin0 -> 11500 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test.5.pngbin0 -> 11500 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test.qml1599
-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test2.0.pngbin0 -> 4656 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test2.1.pngbin0 -> 4656 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test2.qml607
-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.0.pngbin0 -> 10093 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.1.pngbin0 -> 10051 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.2.pngbin0 -> 9812 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.3.pngbin0 -> 9625 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.4.pngbin0 -> 9458 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.5.pngbin0 -> 9645 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.6.pngbin0 -> 9812 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.7.pngbin0 -> 10051 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.8.pngbin0 -> 10087 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.9.pngbin0 -> 10072 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data-X11/test3.qml2879
-rw-r--r--tests/auto/declarative/visual/focusscope/data/test.0.pngbin0 -> 14836 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test.1.pngbin0 -> 14836 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test.2.pngbin0 -> 14821 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test.3.pngbin0 -> 14833 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test.4.pngbin0 -> 14833 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test.5.pngbin0 -> 14833 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test.qml1599
-rw-r--r--tests/auto/declarative/visual/focusscope/data/test2.0.pngbin0 -> 5359 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test2.1.pngbin0 -> 5359 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test2.qml607
-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.0.pngbin0 -> 12616 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.1.pngbin0 -> 12538 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.2.pngbin0 -> 12257 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.3.pngbin0 -> 12035 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.4.pngbin0 -> 11877 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.5.pngbin0 -> 12046 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.6.pngbin0 -> 12257 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.7.pngbin0 -> 12538 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.8.pngbin0 -> 12616 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.9.pngbin0 -> 12581 bytes-rw-r--r--tests/auto/declarative/visual/focusscope/data/test3.qml2879
-rw-r--r--tests/auto/declarative/visual/focusscope/test.qml76
-rw-r--r--tests/auto/declarative/visual/focusscope/test2.qml40
-rw-r--r--tests/auto/declarative/visual/focusscope/test3.qml52
-rw-r--r--tests/auto/declarative/visual/qfxwebview/autosize/autosize.qml60
-rw-r--r--tests/auto/declarative/visual/qfxwebview/autosize/data-X11/autosize.0.pngbin0 -> 6886 bytes-rw-r--r--tests/auto/declarative/visual/qfxwebview/autosize/data-X11/autosize.qml83
-rw-r--r--tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.0.pngbin0 -> 6886 bytes-rw-r--r--tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.qml83
-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.0.pngbin0 -> 1305 bytes-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.1.pngbin0 -> 1306 bytes-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.2.pngbin0 -> 1305 bytes-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.3.pngbin0 -> 1303 bytes-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.4.pngbin0 -> 1303 bytes-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.5.pngbin0 -> 1305 bytes-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.6.pngbin0 -> 1306 bytes-rw-r--r--tests/auto/declarative/visual/qmleasefollow/data/easefollow.qml1807
-rw-r--r--tests/auto/declarative/visual/qmleasefollow/easefollow.qml40
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/animated-smooth.qml55
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/animated.qml55
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/borders.qml18
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/content/MyBorderImage.qml38
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/content/bw.pngbin0 -> 1357 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/content/colors-round.sci7
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/content/colors-stretch.sci5
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/content/colors.pngbin0 -> 1655 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.0.pngbin0 -> 61731 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.1.pngbin0 -> 98912 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.2.pngbin0 -> 48780 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.3.pngbin0 -> 32431 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.4.pngbin0 -> 35835 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.5.pngbin0 -> 79428 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.6.pngbin0 -> 45928 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated-smooth.qml1823
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.0.pngbin0 -> 23684 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.1.pngbin0 -> 29115 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.2.pngbin0 -> 27580 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.3.pngbin0 -> 14822 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.4.pngbin0 -> 21356 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.5.pngbin0 -> 31143 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.6.pngbin0 -> 26468 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.7.pngbin0 -> 16225 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/animated.qml2091
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/borders.0.pngbin0 -> 23029 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/borders.1.pngbin0 -> 23029 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/borders.2.pngbin0 -> 23029 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/borders.3.pngbin0 -> 23029 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/borders.4.pngbin0 -> 23029 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsborderimage/data/borders.qml1359
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-horizontal.0.pngbin0 -> 1427 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-horizontal.1.pngbin0 -> 1357 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-horizontal.2.pngbin0 -> 1405 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-horizontal.3.pngbin0 -> 1427 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-horizontal.qml1199
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.0.pngbin0 -> 1951 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.1.pngbin0 -> 1951 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.10.pngbin0 -> 1952 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.11.pngbin0 -> 1930 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.12.pngbin0 -> 1974 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.13.pngbin0 -> 1961 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.14.pngbin0 -> 1959 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.15.pngbin0 -> 1937 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.16.pngbin0 -> 1618 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.17.pngbin0 -> 1952 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.18.pngbin0 -> 1952 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.19.pngbin0 -> 1930 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.2.pngbin0 -> 1976 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.20.pngbin0 -> 1930 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.21.pngbin0 -> 1947 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.22.pngbin0 -> 1941 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.23.pngbin0 -> 1951 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.24.png0
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.3.pngbin0 -> 1987 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.4.pngbin0 -> 1947 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.5.pngbin0 -> 1975 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.6.pngbin0 -> 1928 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.7.pngbin0 -> 1928 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.8.pngbin0 -> 1928 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.9.pngbin0 -> 1928 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/data/flickable-vertical.qml7037
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/flickable-horizontal.qml37
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflickable/flickable-vertical.qml91
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/data/test-flipable.0.pngbin0 -> 1090 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/data/test-flipable.1.pngbin0 -> 1134 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/data/test-flipable.2.pngbin0 -> 961 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/data/test-flipable.3.pngbin0 -> 1076 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/data/test-flipable.4.pngbin0 -> 1134 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/data/test-flipable.5.pngbin0 -> 969 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/data/test-flipable.qml1623
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsflipable/test-flipable.qml79
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.0.pngbin0 -> 1303 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.1.pngbin0 -> 1317 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.2.pngbin0 -> 1318 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.3.pngbin0 -> 1306 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.4.pngbin0 -> 1308 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.5.pngbin0 -> 1303 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.6.pngbin0 -> 1323 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.7.pngbin0 -> 1325 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.8.pngbin0 -> 1346 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.9.pngbin0 -> 1303 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview.qml2859
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.0.pngbin0 -> 1310 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.1.pngbin0 -> 1322 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.10.pngbin0 -> 1313 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.2.pngbin0 -> 1341 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.3.pngbin0 -> 1368 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.4.pngbin0 -> 1319 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.5.pngbin0 -> 1352 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.6.pngbin0 -> 1309 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.7.pngbin0 -> 1347 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.8.pngbin0 -> 1310 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.9.pngbin0 -> 1354 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/data/gridview2.qml2479
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/gridview.qml51
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsgridview/gridview2.qml58
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsparticles/data/particles.0.pngbin0 -> 10219 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsparticles/data/particles.1.pngbin0 -> 13469 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsparticles/data/particles.2.pngbin0 -> 14051 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicsparticles/data/particles.qml775
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsparticles/particles.qml54
-rw-r--r--tests/auto/declarative/visual/qmlgraphicsparticles/star.pngbin0 -> 262 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.0.pngbin0 -> 2263 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.1.pngbin0 -> 2329 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.2.pngbin0 -> 2279 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.3.pngbin0 -> 2263 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.4.pngbin0 -> 2263 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.5.pngbin0 -> 2308 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.6.pngbin0 -> 2280 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview-2.qml2303
-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview.0.pngbin0 -> 2321 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview.1.pngbin0 -> 2380 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview.2.pngbin0 -> 2315 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview.3.pngbin0 -> 2372 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview.4.pngbin0 -> 2327 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/data/test-pathview.qml1495
-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/test-pathview-2.qml62
-rw-r--r--tests/auto/declarative/visual/qmlgraphicspathview/test-pathview.qml62
-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/dynamic.0.pngbin0 -> 1429 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/dynamic.1.pngbin0 -> 1433 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/dynamic.2.pngbin0 -> 1431 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/dynamic.3.pngbin0 -> 1428 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/dynamic.4.pngbin0 -> 1432 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/dynamic.5.pngbin0 -> 1434 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/dynamic.qml1603
-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/repeater.0.pngbin0 -> 2790 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/data/repeater.qml339
-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/dynamic.qml65
-rw-r--r--tests/auto/declarative/visual/qmlgraphicspositioners/repeater.qml15
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/baseline/data-X11/parentanchor.qml131
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/baseline/data/parentanchor.qml131
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/baseline/parentanchor.qml14
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/elide.0.pngbin0 -> 2276 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/elide.qml279
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/elide2.0.pngbin0 -> 4818 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/elide2.1.pngbin0 -> 4089 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/elide2.2.pngbin0 -> 3128 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/elide2.3.pngbin0 -> 1963 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/elide2.qml991
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/multilength.0.pngbin0 -> 736 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-MAC/multilength.qml303
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-X11/elide.0.pngbin0 -> 1002 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-X11/elide.qml279
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-X11/multilength.0.pngbin0 -> 596 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data-X11/multilength.qml303
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data/elide.0.pngbin0 -> 1604 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data/elide.qml279
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data/elide2.0.pngbin0 -> 4818 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data/elide2.1.pngbin0 -> 4089 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data/elide2.2.pngbin0 -> 3128 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data/elide2.3.pngbin0 -> 1963 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/data/elide2.qml991
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/elide.qml31
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/elide2.qml12
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/elide/multilength.qml19
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data-MAC/plaintext.0.pngbin0 -> 103018 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data-MAC/plaintext.qml351
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data-MAC/richtext.0.pngbin0 -> 136492 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data-MAC/richtext.qml359
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data/plaintext.0.pngbin0 -> 94120 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data/plaintext.qml351
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data/richtext.0.pngbin0 -> 121122 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/data/richtext.qml359
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/plaintext.qml85
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstext/font/richtext.qml85
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/cursorDelegate.qml35
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.0.pngbin0 -> 793 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.1.pngbin0 -> 795 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.2.pngbin0 -> 803 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.3.pngbin0 -> 805 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.4.pngbin0 -> 805 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.5.pngbin0 -> 805 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.6.pngbin0 -> 799 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.7.pngbin0 -> 799 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.8.pngbin0 -> 803 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/cursorDelegate.qml3555
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/qt-669.0.pngbin0 -> 365 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/qt-669.1.pngbin0 -> 365 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/qt-669.2.pngbin0 -> 366 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/qt-669.3.pngbin0 -> 362 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-MAC/qt-669.qml1371
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.0.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.1.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.2.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.3.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.4.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.5.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.6.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data-X11/wrap.qml2467
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.0.pngbin0 -> 3322 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.1.pngbin0 -> 3323 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.2.pngbin0 -> 3325 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.3.pngbin0 -> 3332 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.4.pngbin0 -> 3329 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.5.pngbin0 -> 3818 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.6.pngbin0 -> 3333 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.7.pngbin0 -> 3332 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.8.pngbin0 -> 3347 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/cursorDelegate.qml3555
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/qt-669.0.pngbin0 -> 4802 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/qt-669.1.pngbin0 -> 4804 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/qt-669.2.pngbin0 -> 4801 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/qt-669.3.pngbin0 -> 4791 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/qt-669.qml1371
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.0.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.1.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.2.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.3.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.4.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.5.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.6.pngbin0 -> 1110 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/data/wrap.qml2467
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/qt-669.qml19
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextedit/wrap.qml21
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/cursorDelegate.qml35
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.0.pngbin0 -> 793 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.1.pngbin0 -> 796 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.2.pngbin0 -> 804 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.3.pngbin0 -> 805 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.4.pngbin0 -> 805 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.5.pngbin0 -> 805 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.6.pngbin0 -> 801 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.7.pngbin0 -> 802 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.8.pngbin0 -> 802 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-MAC/cursorDelegate.qml3379
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/echoMode.0.pngbin0 -> 999 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/echoMode.1.pngbin0 -> 1880 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/echoMode.2.pngbin0 -> 2962 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/echoMode.3.pngbin0 -> 2827 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/echoMode.4.pngbin0 -> 2827 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/echoMode.qml1043
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/hAlign.0.pngbin0 -> 1245 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data-X11/hAlign.qml107
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.0.pngbin0 -> 3314 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.1.pngbin0 -> 3377 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.2.pngbin0 -> 3323 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.3.pngbin0 -> 3325 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.4.pngbin0 -> 3322 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.5.pngbin0 -> 3322 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.6.pngbin0 -> 3326 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.7.pngbin0 -> 3814 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.8.pngbin0 -> 3324 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/cursorDelegate.qml3379
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/echoMode.0.pngbin0 -> 999 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/echoMode.1.pngbin0 -> 1880 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/echoMode.2.pngbin0 -> 2962 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/echoMode.3.pngbin0 -> 2827 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/echoMode.4.pngbin0 -> 2827 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/echoMode.qml1043
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/hAlign.0.pngbin0 -> 1245 bytes-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/data/hAlign.qml107
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/echoMode.qml10
-rw-r--r--tests/auto/declarative/visual/qmlgraphicstextinput/hAlign.qml39
-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.0.pngbin0 -> 1563 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.1.pngbin0 -> 1570 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.2.pngbin0 -> 1553 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.3.pngbin0 -> 1563 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.4.pngbin0 -> 1569 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.5.pngbin0 -> 1569 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.6.pngbin0 -> 1566 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.7.pngbin0 -> 1566 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.8.pngbin0 -> 1567 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/drag.qml5207
-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.0.pngbin0 -> 471 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.1.pngbin0 -> 474 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.10.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.11.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.12.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.13.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.14.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.15.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.16.pngbin0 -> 1454 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.17.pngbin0 -> 1454 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.18.pngbin0 -> 1454 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.19.pngbin0 -> 1454 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.2.pngbin0 -> 474 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.20.pngbin0 -> 1454 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.21.pngbin0 -> 1454 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.22.pngbin0 -> 1454 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.3.pngbin0 -> 474 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.4.pngbin0 -> 481 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.5.pngbin0 -> 481 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.6.pngbin0 -> 481 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.7.pngbin0 -> 481 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.8.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.9.pngbin0 -> 479 bytes-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/data/mouseregion.qml5867
-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/drag.qml21
-rw-r--r--tests/auto/declarative/visual/qmlmouseregion/mouseregion.qml124
-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/clock.qml64
-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/content/background.pngbin0 -> 46895 bytes-rwxr-xr-xtests/auto/declarative/visual/qmlspringfollow/content/center.pngbin0 -> 765 bytes-rwxr-xr-xtests/auto/declarative/visual/qmlspringfollow/content/clock.pngbin0 -> 20653 bytes-rwxr-xr-xtests/auto/declarative/visual/qmlspringfollow/content/hour.pngbin0 -> 625 bytes-rwxr-xr-xtests/auto/declarative/visual/qmlspringfollow/content/minute.pngbin0 -> 625 bytes-rwxr-xr-xtests/auto/declarative/visual/qmlspringfollow/content/second.pngbin0 -> 303 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/clock.0.pngbin0 -> 17294 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/clock.1.pngbin0 -> 17394 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/clock.2.pngbin0 -> 17524 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/clock.3.pngbin0 -> 17572 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/clock.qml1135
-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.0.pngbin0 -> 959 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.1.pngbin0 -> 1244 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.10.pngbin0 -> 1299 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.2.pngbin0 -> 1224 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.3.pngbin0 -> 1243 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.4.pngbin0 -> 1230 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.5.pngbin0 -> 1231 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.6.pngbin0 -> 1239 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.7.pngbin0 -> 1241 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.8.pngbin0 -> 1237 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.9.pngbin0 -> 1229 bytes-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/data/follow.qml1763
-rw-r--r--tests/auto/declarative/visual/qmlspringfollow/follow.qml71
-rw-r--r--tests/auto/declarative/visual/rect/GradientRect.qml25
-rw-r--r--tests/auto/declarative/visual/rect/MyRect.qml21
-rw-r--r--tests/auto/declarative/visual/rect/data/rect-painting.0.pngbin0 -> 29725 bytes-rw-r--r--tests/auto/declarative/visual/rect/data/rect-painting.qml287
-rw-r--r--tests/auto/declarative/visual/rect/rect-painting.qml55
-rw-r--r--tests/auto/declarative/visual/repeater/basic1.qml27
-rw-r--r--tests/auto/declarative/visual/repeater/basic2.qml31
-rw-r--r--tests/auto/declarative/visual/repeater/basic3.qml29
-rw-r--r--tests/auto/declarative/visual/repeater/basic4.qml33
-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic1.0.pngbin0 -> 1550 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic1.qml323
-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic2.0.pngbin0 -> 1550 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic2.qml331
-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic3.0.pngbin0 -> 1550 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic3.qml347
-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic4.0.pngbin0 -> 1550 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-MAC/basic4.qml419
-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic1.0.pngbin0 -> 1354 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic1.qml323
-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic2.0.pngbin0 -> 1354 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic2.qml331
-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic3.0.pngbin0 -> 1354 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic3.qml347
-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic4.0.pngbin0 -> 1354 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data-X11/basic4.qml419
-rw-r--r--tests/auto/declarative/visual/repeater/data/basic1.0.pngbin0 -> 1513 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data/basic1.qml323
-rw-r--r--tests/auto/declarative/visual/repeater/data/basic2.0.pngbin0 -> 1513 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data/basic2.qml331
-rw-r--r--tests/auto/declarative/visual/repeater/data/basic3.0.pngbin0 -> 1513 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data/basic3.qml347
-rw-r--r--tests/auto/declarative/visual/repeater/data/basic4.0.pngbin0 -> 1513 bytes-rw-r--r--tests/auto/declarative/visual/repeater/data/basic4.qml419
-rw-r--r--tests/auto/declarative/visual/selftest_noimages/data/selftest_noimages.qml470
-rw-r--r--tests/auto/declarative/visual/selftest_noimages/selftest_noimages.qml9
-rw-r--r--tests/auto/declarative/visual/tst_visual.cpp370
-rw-r--r--tests/auto/declarative/visual/visual.pro7
-rw-r--r--tests/auto/declarative/visual/webview/embedding/data/nesting.0.pngbin0 -> 5659 bytes-rw-r--r--tests/auto/declarative/visual/webview/embedding/data/nesting.qml363
-rw-r--r--tests/auto/declarative/visual/webview/embedding/egg.qml26
-rw-r--r--tests/auto/declarative/visual/webview/embedding/nesting.html9
-rw-r--r--tests/auto/declarative/visual/webview/embedding/nesting.qml8
-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.0.pngbin0 -> 7999 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.1.pngbin0 -> 8020 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.2.pngbin0 -> 8143 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.3.pngbin0 -> 8158 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.4.pngbin0 -> 8284 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.5.pngbin0 -> 8284 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.6.pngbin0 -> 8284 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.7.pngbin0 -> 8284 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.8.pngbin0 -> 8284 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/evaluateJavaScript.qml3759
-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/windowObjects.0.pngbin0 -> 7991 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/windowObjects.1.pngbin0 -> 7991 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/windowObjects.2.pngbin0 -> 7643 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/windowObjects.3.pngbin0 -> 7733 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/windowObjects.4.pngbin0 -> 8116 bytes-rw-r--r--tests/auto/declarative/visual/webview/javascript/data/windowObjects.qml2643
-rw-r--r--tests/auto/declarative/visual/webview/javascript/evaluateJavaScript.qml31
-rw-r--r--tests/auto/declarative/visual/webview/javascript/test-objects.html12
-rw-r--r--tests/auto/declarative/visual/webview/javascript/windowObjects.qml26
-rw-r--r--tests/auto/declarative/visual/webview/settings/data/fontFamily.0.pngbin0 -> 3774 bytes-rw-r--r--tests/auto/declarative/visual/webview/settings/data/fontFamily.qml395
-rw-r--r--tests/auto/declarative/visual/webview/settings/data/fontSize.0.pngbin0 -> 32180 bytes-rw-r--r--tests/auto/declarative/visual/webview/settings/data/fontSize.qml339
-rw-r--r--tests/auto/declarative/visual/webview/settings/data/noAutoLoadImages.0.pngbin0 -> 6609 bytes-rw-r--r--tests/auto/declarative/visual/webview/settings/data/noAutoLoadImages.1.pngbin0 -> 6609 bytes-rw-r--r--tests/auto/declarative/visual/webview/settings/data/noAutoLoadImages.qml595
-rw-r--r--tests/auto/declarative/visual/webview/settings/data/setFontFamily.0.pngbin0 -> 12132 bytes-rw-r--r--tests/auto/declarative/visual/webview/settings/data/setFontFamily.qml351
-rw-r--r--tests/auto/declarative/visual/webview/settings/fontFamily.qml16
-rw-r--r--tests/auto/declarative/visual/webview/settings/fontSize.qml70
-rw-r--r--tests/auto/declarative/visual/webview/settings/noAutoLoadImages.qml20
-rw-r--r--tests/auto/declarative/visual/webview/settings/qtlogo.pngbin0 -> 2738 bytes-rw-r--r--tests/auto/declarative/visual/webview/settings/setFontFamily.qml10
-rw-r--r--tests/auto/declarative/visual/webview/settings/tarzeau_ocr_a.ttfbin0 -> 24544 bytes-rw-r--r--tests/auto/declarative/visual/webview/settings/test-img.html6
-rw-r--r--tests/auto/declarative/visual/webview/settings/test.html9
-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/pageWidth.qml227
-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/renderControl.0.pngbin0 -> 7589 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/renderControl.qml415
-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/resolution.0.pngbin0 -> 6275 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/resolution.1.pngbin0 -> 3553 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/resolution.2.pngbin0 -> 5838 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/resolution.3.pngbin0 -> 8005 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/resolution.4.pngbin0 -> 6087 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/resolution.qml1319
-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zoomTextOnly.0.pngbin0 -> 5589 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zoomTextOnly.1.pngbin0 -> 6848 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zoomTextOnly.qml655
-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zooming.0.pngbin0 -> 735 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zooming.1.pngbin0 -> 735 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zooming.2.pngbin0 -> 735 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zooming.3.pngbin0 -> 735 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/data/zooming.qml2115
-rw-r--r--tests/auto/declarative/visual/webview/zooming/pageWidth.qml9
-rw-r--r--tests/auto/declarative/visual/webview/zooming/qtlogo.pngbin0 -> 2738 bytes-rw-r--r--tests/auto/declarative/visual/webview/zooming/renderControl.html7
-rw-r--r--tests/auto/declarative/visual/webview/zooming/renderControl.qml20
-rw-r--r--tests/auto/declarative/visual/webview/zooming/resolution.html6
-rw-r--r--tests/auto/declarative/visual/webview/zooming/resolution.qml16
-rw-r--r--tests/auto/declarative/visual/webview/zooming/zoomTextOnly.html7
-rw-r--r--tests/auto/declarative/visual/webview/zooming/zoomTextOnly.qml14
-rw-r--r--tests/auto/declarative/visual/webview/zooming/zooming.html6
-rw-r--r--tests/auto/declarative/visual/webview/zooming/zooming.qml17
-rw-r--r--tests/auto/qabstractitemview/tst_qabstractitemview.cpp11
-rw-r--r--tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp97
-rw-r--r--tests/auto/qabstractslider/tst_qabstractslider.cpp8
-rw-r--r--tests/auto/qapplication/tst_qapplication.cpp30
-rw-r--r--tests/auto/qdatetime/tst_qdatetime.cpp7
-rw-r--r--tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp2
-rw-r--r--tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp10
-rw-r--r--tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp20
-rw-r--r--tests/auto/qgl/qgl.pro4
-rw-r--r--tests/auto/qgl/qgl.qrc5
-rw-r--r--tests/auto/qgl/tst_qgl.cpp240
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp151
-rw-r--r--tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp8
-rw-r--r--tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp43
-rw-r--r--tests/auto/qimagereader/images/qt-gif-anim.gifbin0 -> 1661 bytes-rw-r--r--tests/auto/qimagereader/images/qt-gif-noanim.gifbin0 -> 1642 bytes-rw-r--r--tests/auto/qimagereader/qimagereader.qrc4
-rw-r--r--tests/auto/qimagereader/tst_qimagereader.cpp63
-rw-r--r--tests/auto/qlabel/tst_qlabel.cpp24
-rw-r--r--tests/auto/qlineedit/tst_qlineedit.cpp51
-rw-r--r--tests/auto/qlistview/tst_qlistview.cpp86
-rw-r--r--tests/auto/qmainwindow/tst_qmainwindow.cpp40
-rw-r--r--tests/auto/qmenu/tst_qmenu.cpp17
-rw-r--r--tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp1
-rw-r--r--tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp64
-rw-r--r--tests/auto/qscriptv8testsuite/tst_qscriptv8testsuite.cpp14
-rw-r--r--tests/auto/qscriptvalue/testgen/data.txt4
-rwxr-xr-xtests/auto/qscriptvalue/testgen/gen.py2
-rw-r--r--tests/auto/qscriptvalue/tst_qscriptvalue_generated.cpp127
-rw-r--r--tests/auto/qsqldatabase/tst_qsqldatabase.cpp20
-rw-r--r--tests/auto/qtextcodec/tst_qtextcodec.cpp46
-rw-r--r--tests/auto/qtextedit/tst_qtextedit.cpp22
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp249
-rw-r--r--tests/auto/uiloader/baseline/css_qtbug7737_borderimageradius.ui44
-rw-r--r--tests/benchmarks/benchmarks.pro52
-rw-r--r--tests/benchmarks/corelib/corelib.pro6
-rw-r--r--tests/benchmarks/corelib/io/io.pro9
-rw-r--r--tests/benchmarks/corelib/io/qdir/qdir.pro (renamed from tests/benchmarks/qdir/qdir.pro)0
-rw-r--r--tests/benchmarks/corelib/io/qdir/tst_qdir.cpp (renamed from tests/benchmarks/qdir/tst_qdir.cpp)0
-rw-r--r--tests/benchmarks/corelib/io/qdiriterator/main.cpp (renamed from tests/benchmarks/qdiriterator/main.cpp)0
-rwxr-xr-xtests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro (renamed from tests/benchmarks/qdiriterator/qdiriterator.pro)0
-rw-r--r--tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp (renamed from tests/benchmarks/qdiriterator/qfilesystemiterator.cpp)0
-rw-r--r--tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h (renamed from tests/benchmarks/qdiriterator/qfilesystemiterator.h)0
-rw-r--r--tests/benchmarks/corelib/io/qfile/main.cpp (renamed from tests/benchmarks/qfile/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/io/qfile/qfile.pro (renamed from tests/benchmarks/qfile/qfile.pro)0
-rw-r--r--tests/benchmarks/corelib/io/qfileinfo/main.cpp (renamed from tests/benchmarks/qfileinfo/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro (renamed from tests/benchmarks/qfileinfo/qfileinfo.pro)0
-rw-r--r--tests/benchmarks/corelib/io/qiodevice/main.cpp (renamed from tests/benchmarks/qiodevice/main.cpp)0
-rwxr-xr-xtests/benchmarks/corelib/io/qiodevice/qiodevice.pro (renamed from tests/benchmarks/qiodevice/qiodevice.pro)0
-rw-r--r--tests/benchmarks/corelib/io/qtemporaryfile/main.cpp (renamed from tests/benchmarks/qtemporaryfile/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro (renamed from tests/benchmarks/qtemporaryfile/qtemporaryfile.pro)0
-rw-r--r--tests/benchmarks/corelib/kernel/events/events.pro (renamed from tests/benchmarks/events/events.pro)0
-rw-r--r--tests/benchmarks/corelib/kernel/events/main.cpp (renamed from tests/benchmarks/events/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/kernel/kernel.pro6
-rw-r--r--tests/benchmarks/corelib/kernel/qmetaobject/main.cpp (renamed from tests/benchmarks/qmetaobject/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/kernel/qmetaobject/qmetaobject.pro (renamed from tests/benchmarks/qmetaobject/qmetaobject.pro)0
-rw-r--r--tests/benchmarks/corelib/kernel/qobject/main.cpp (renamed from tests/benchmarks/qobject/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/kernel/qobject/object.cpp (renamed from tests/benchmarks/qobject/object.cpp)0
-rw-r--r--tests/benchmarks/corelib/kernel/qobject/object.h (renamed from tests/benchmarks/qobject/object.h)0
-rw-r--r--tests/benchmarks/corelib/kernel/qobject/qobject.pro (renamed from tests/benchmarks/qobject/qobject.pro)0
-rw-r--r--tests/benchmarks/corelib/kernel/qvariant/qvariant.pro (renamed from tests/benchmarks/qvariant/qvariant.pro)0
-rw-r--r--tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp (renamed from tests/benchmarks/qvariant/tst_qvariant.cpp)0
-rw-r--r--tests/benchmarks/corelib/thread/qthreadstorage/qthreadstorage.pro (renamed from tests/benchmarks/qthreadstorage/qthreadstorage.pro)0
-rw-r--r--tests/benchmarks/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp (renamed from tests/benchmarks/qthreadstorage/tst_qthreadstorage.cpp)0
-rw-r--r--tests/benchmarks/corelib/thread/thread.pro3
-rw-r--r--tests/benchmarks/corelib/tools/containers-associative/containers-associative.pro (renamed from tests/benchmarks/containers-associative/containers-associative.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/containers-associative/main.cpp (renamed from tests/benchmarks/containers-associative/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/tools/containers-sequential/containers-sequential.pro (renamed from tests/benchmarks/containers-sequential/containers-sequential.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/containers-sequential/main.cpp (renamed from tests/benchmarks/containers-sequential/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/tools/qbytearray/main.cpp (renamed from tests/benchmarks/qbytearray/main.cpp)0
-rwxr-xr-xtests/benchmarks/corelib/tools/qbytearray/qbytearray.pro (renamed from tests/benchmarks/qbytearray/qbytearray.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/qrect/main.cpp (renamed from tests/benchmarks/qrect/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/tools/qrect/qrect.pro (renamed from tests/benchmarks/qrect/qrect.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/qregexp/main.cpp (renamed from tests/benchmarks/qregexp/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/tools/qregexp/qregexp.pro (renamed from tests/benchmarks/qregexp/qregexp.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/qstring/main.cpp (renamed from tests/benchmarks/qstring/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/tools/qstring/qstring.pro (renamed from tests/benchmarks/qstring/qstring.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/qstring/utf-8.txt (renamed from tests/benchmarks/qstring/utf-8.txt)0
-rw-r--r--tests/benchmarks/corelib/tools/qstringbuilder/main.cpp (renamed from tests/benchmarks/qstringbuilder/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/tools/qstringbuilder/qstringbuilder.pro (renamed from tests/benchmarks/qstringbuilder/qstringbuilder.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/qstringlist/.gitignore (renamed from tests/benchmarks/qstringlist/.gitignore)0
-rw-r--r--tests/benchmarks/corelib/tools/qstringlist/main.cpp (renamed from tests/benchmarks/qstringlist/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/tools/qstringlist/qstringlist.pro (renamed from tests/benchmarks/qstringlist/qstringlist.pro)0
-rw-r--r--tests/benchmarks/corelib/tools/tools.pro10
-rw-r--r--tests/benchmarks/declarative/binding/binding.pro9
-rw-r--r--tests/benchmarks/declarative/binding/data/idproperty.txt9
-rw-r--r--tests/benchmarks/declarative/binding/data/localproperty.txt5
-rw-r--r--tests/benchmarks/declarative/binding/data/objectproperty.txt7
-rw-r--r--tests/benchmarks/declarative/binding/testtypes.cpp43
-rw-r--r--tests/benchmarks/declarative/binding/testtypes.h81
-rw-r--r--tests/benchmarks/declarative/binding/tst_binding.cpp160
-rw-r--r--tests/benchmarks/declarative/creation/creation.pro10
-rw-r--r--tests/benchmarks/declarative/creation/data/item.qml34
-rw-r--r--tests/benchmarks/declarative/creation/data/qobject.qml4
-rw-r--r--tests/benchmarks/declarative/creation/tst_creation.cpp375
-rw-r--r--tests/benchmarks/declarative/declarative.pro10
-rw-r--r--tests/benchmarks/declarative/painting/paintbenchmark.cpp309
-rw-r--r--tests/benchmarks/declarative/painting/paintbenchmark.pro13
-rw-r--r--tests/benchmarks/declarative/pointers/pointers.pro8
-rw-r--r--tests/benchmarks/declarative/pointers/tst_pointers.cpp77
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/myqmlobject.qml3
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/myqmlobject_binding.qml6
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/object.qml3
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/object_id.qml6
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/BoomBlock.qml55
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/pics/blueStar.pngbin0 -> 278 bytes-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/pics/blueStone.pngbin0 -> 2691 bytes-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/pics/greenStar.pngbin0 -> 273 bytes-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/pics/greenStone.pngbin0 -> 2662 bytes-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/pics/redStar.pngbin0 -> 274 bytes-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/pics/redStone.pngbin0 -> 2604 bytes-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/samegame/pics/yellowStone.pngbin0 -> 2667 bytes-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/synthesized_properties.2.qml15
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/data/synthesized_properties.qml5
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/qmlcomponent.pro9
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/testtypes.cpp43
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/testtypes.h81
-rw-r--r--tests/benchmarks/declarative/qmlcomponent/tst_qmlcomponent.cpp118
-rw-r--r--tests/benchmarks/declarative/qmlgraphicsimage/image.pngbin0 -> 611 bytes-rw-r--r--tests/benchmarks/declarative/qmlgraphicsimage/qmlgraphicsimage.pro11
-rw-r--r--tests/benchmarks/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp102
-rw-r--r--tests/benchmarks/declarative/qmlmetaproperty/data/object.qml3
-rw-r--r--tests/benchmarks/declarative/qmlmetaproperty/data/synthesized_object.qml6
-rw-r--r--tests/benchmarks/declarative/qmlmetaproperty/qmlmetaproperty.pro8
-rw-r--r--tests/benchmarks/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp113
-rw-r--r--tests/benchmarks/declarative/qmltime/example.qml14
-rw-r--r--tests/benchmarks/declarative/qmltime/qmltime.cpp219
-rw-r--r--tests/benchmarks/declarative/qmltime/qmltime.pro8
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/anchors/empty.qml34
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/anchors/fill.qml41
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/anchors/null.qml27
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/item_creation/children.qml34
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/item_creation/data.qml34
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/item_creation/no_creation.qml12
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/item_creation/resources.qml34
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/positioner_creation/no_positioner.qml37
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/positioner_creation/null_positioner.qml34
-rw-r--r--tests/benchmarks/declarative/qmltime/tests/positioner_creation/positioner.qml37
-rw-r--r--tests/benchmarks/declarative/script/data/CustomObject.qml7
-rw-r--r--tests/benchmarks/declarative/script/data/block.qml34
-rw-r--r--tests/benchmarks/declarative/script/data/signal_args.qml6
-rw-r--r--tests/benchmarks/declarative/script/data/signal_qml.qml6
-rw-r--r--tests/benchmarks/declarative/script/data/signal_unconnected.qml4
-rw-r--r--tests/benchmarks/declarative/script/data/signal_unusedArgs.qml6
-rw-r--r--tests/benchmarks/declarative/script/data/slot_complex.qml16
-rw-r--r--tests/benchmarks/declarative/script/data/slot_complex_js.qml18
-rw-r--r--tests/benchmarks/declarative/script/data/slot_simple.qml9
-rw-r--r--tests/benchmarks/declarative/script/data/slot_simple_js.qml13
-rw-r--r--tests/benchmarks/declarative/script/script.pro11
-rw-r--r--tests/benchmarks/declarative/script/tst_script.cpp618
-rw-r--r--tests/benchmarks/gui/animation/animation.pro2
-rw-r--r--tests/benchmarks/gui/animation/qanimation/dummyanimation.cpp (renamed from tests/benchmarks/qanimation/dummyanimation.cpp)0
-rw-r--r--tests/benchmarks/gui/animation/qanimation/dummyanimation.h (renamed from tests/benchmarks/qanimation/dummyanimation.h)0
-rw-r--r--tests/benchmarks/gui/animation/qanimation/dummyobject.cpp (renamed from tests/benchmarks/qanimation/dummyobject.cpp)0
-rw-r--r--tests/benchmarks/gui/animation/qanimation/dummyobject.h (renamed from tests/benchmarks/qanimation/dummyobject.h)0
-rw-r--r--tests/benchmarks/gui/animation/qanimation/main.cpp (renamed from tests/benchmarks/qanimation/main.cpp)0
-rw-r--r--tests/benchmarks/gui/animation/qanimation/qanimation.pro (renamed from tests/benchmarks/qanimation/qanimation.pro)0
-rw-r--r--tests/benchmarks/gui/animation/qanimation/rectanimation.cpp (renamed from tests/benchmarks/qanimation/rectanimation.cpp)0
-rw-r--r--tests/benchmarks/gui/animation/qanimation/rectanimation.h (renamed from tests/benchmarks/qanimation/rectanimation.h)0
-rw-r--r--tests/benchmarks/gui/graphicsview/graphicsview.pro7
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro (renamed from tests/benchmarks/qgraphicsanchorlayout/qgraphicsanchorlayout.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp (renamed from tests/benchmarks/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsitem/qgraphicsitem.pro (renamed from tests/benchmarks/qgraphicsitem/qgraphicsitem.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp (renamed from tests/benchmarks/qgraphicsitem/tst_qgraphicsitem.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsscene/qgraphicsscene.pro (renamed from tests/benchmarks/qgraphicsscene/qgraphicsscene.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp (renamed from tests/benchmarks/qgraphicsscene/tst_qgraphicsscene.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/chip.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.debug (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/chip.debug)bin863805 -> 863805 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.h (renamed from tests/benchmarks/qgraphicsview/chiptester/chip.h)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.pro (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/chip.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/fileprint.png (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/fileprint.png)bin1456 -> 1456 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/images.qrc (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/images.qrc)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/main.cpp (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/main.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.cpp (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/mainwindow.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.h (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/mainwindow.h)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/qt4logo.png (renamed from tests/benchmarks/qgraphicsview/chiptester/qt4logo.png)bin48333 -> 48333 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateleft.png (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/rotateleft.png)bin1754 -> 1754 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateright.png (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/rotateright.png)bin1732 -> 1732 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/view.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.h (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/view.h)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomin.png (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/zoomin.png)bin1622 -> 1622 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomout.png (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/zoomout.png)bin1601 -> 1601 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp (renamed from tests/benchmarks/qgraphicsview/benchapps/moveItems/main.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/moveItems.pro (renamed from tests/benchmarks/qgraphicsview/benchapps/moveItems/moveItems.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp (renamed from tests/benchmarks/qgraphicsview/benchapps/scrolltest/main.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/scrolltest.pro (renamed from tests/benchmarks/qgraphicsview/benchapps/scrolltest/scrolltest.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.cpp (renamed from tests/benchmarks/qgraphicsview/chiptester/chip.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.h (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/chip.h)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.cpp (renamed from tests/benchmarks/qgraphicsview/chiptester/chiptester.cpp)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.h (renamed from tests/benchmarks/qgraphicsview/chiptester/chiptester.h)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.pri (renamed from tests/benchmarks/qgraphicsview/chiptester/chiptester.pri)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/images.qrc (renamed from tests/benchmarks/qgraphicsview/chiptester/images.qrc)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/qt4logo.png (renamed from tests/benchmarks/qgraphicsview/benchapps/chipTest/qt4logo.png)bin48333 -> 48333 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/images/designer.png (renamed from tests/benchmarks/qgraphicsview/images/designer.png)bin4205 -> 4205 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine-big.jpeg (renamed from tests/benchmarks/qgraphicsview/images/wine-big.jpeg)bin12249 -> 12249 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine.jpeg (renamed from tests/benchmarks/qgraphicsview/images/wine.jpeg)bin2265 -> 2265 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.pro (renamed from tests/benchmarks/qgraphicsview/qgraphicsview.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.qrc (renamed from tests/benchmarks/qgraphicsview/qgraphicsview.qrc)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/random.data (renamed from tests/benchmarks/qgraphicsview/random.data)bin800 -> 800 bytes-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsview/tst_qgraphicsview.cpp936
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicswidget/qgraphicswidget.pro (renamed from tests/benchmarks/qgraphicswidget/qgraphicswidget.pro)0
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp (renamed from tests/benchmarks/qgraphicswidget/tst_qgraphicswidget.cpp)0
-rw-r--r--tests/benchmarks/gui/gui.pro11
-rw-r--r--tests/benchmarks/gui/image/blendbench/blendbench.pro (renamed from tests/benchmarks/blendbench/blendbench.pro)0
-rw-r--r--tests/benchmarks/gui/image/blendbench/main.cpp (renamed from tests/benchmarks/blendbench/main.cpp)0
-rw-r--r--tests/benchmarks/gui/image/image.pro6
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/16bpp.bmp (renamed from tests/benchmarks/qimagereader/images/16bpp.bmp)bin153654 -> 153654 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/4bpp-rle.bmp (renamed from tests/benchmarks/qimagereader/images/4bpp-rle.bmp)bin23662 -> 23662 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/YCbCr_cmyk.jpg (renamed from tests/benchmarks/qimagereader/images/YCbCr_cmyk.jpg)bin3699 -> 3699 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/YCbCr_cmyk.png (renamed from tests/benchmarks/qimagereader/images/YCbCr_cmyk.png)bin230 -> 230 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/YCbCr_rgb.jpg (renamed from tests/benchmarks/qimagereader/images/YCbCr_rgb.jpg)bin2045 -> 2045 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/away.png (renamed from tests/benchmarks/qimagereader/images/away.png)bin753 -> 753 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/ball.mng (renamed from tests/benchmarks/qimagereader/images/ball.mng)bin34394 -> 34394 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/bat1.gif (renamed from tests/benchmarks/qimagereader/images/bat1.gif)bin953 -> 953 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/bat2.gif (renamed from tests/benchmarks/qimagereader/images/bat2.gif)bin980 -> 980 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/beavis.jpg (renamed from tests/benchmarks/qimagereader/images/beavis.jpg)bin20688 -> 20688 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/black.png (renamed from tests/benchmarks/qimagereader/images/black.png)bin697 -> 697 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/black.xpm (renamed from tests/benchmarks/qimagereader/images/black.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/colorful.bmp (renamed from tests/benchmarks/qimagereader/images/colorful.bmp)bin65002 -> 65002 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt-colors.xpm (renamed from tests/benchmarks/qimagereader/images/corrupt-colors.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt-data.tif (renamed from tests/benchmarks/qimagereader/images/corrupt-data.tif)bin8590 -> 8590 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt-pixels.xpm (renamed from tests/benchmarks/qimagereader/images/corrupt-pixels.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt.bmp (renamed from tests/benchmarks/qimagereader/images/corrupt.bmp)bin116 -> 116 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt.gif (renamed from tests/benchmarks/qimagereader/images/corrupt.gif)bin2608 -> 2608 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt.jpg (renamed from tests/benchmarks/qimagereader/images/corrupt.jpg)bin18 -> 18 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt.mng (renamed from tests/benchmarks/qimagereader/images/corrupt.mng)bin183 -> 183 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt.png (renamed from tests/benchmarks/qimagereader/images/corrupt.png)bin95 -> 95 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/corrupt.xbm (renamed from tests/benchmarks/qimagereader/images/corrupt.xbm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/crash-signed-char.bmp (renamed from tests/benchmarks/qimagereader/images/crash-signed-char.bmp)bin45748 -> 45748 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/earth.gif (renamed from tests/benchmarks/qimagereader/images/earth.gif)bin51712 -> 51712 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/fire.mng (renamed from tests/benchmarks/qimagereader/images/fire.mng)bin44430 -> 44430 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/font.bmp (renamed from tests/benchmarks/qimagereader/images/font.bmp)bin1026 -> 1026 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/gnus.xbm (renamed from tests/benchmarks/qimagereader/images/gnus.xbm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/image.pbm (renamed from tests/benchmarks/qimagereader/images/image.pbm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/image.pgm (renamed from tests/benchmarks/qimagereader/images/image.pgm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/image.png (renamed from tests/benchmarks/qimagereader/images/image.png)bin549 -> 549 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/image.ppm (renamed from tests/benchmarks/qimagereader/images/image.ppm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/kollada-noext (renamed from tests/benchmarks/qimagereader/images/kollada-noext)bin13907 -> 13907 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/kollada.png (renamed from tests/benchmarks/qimagereader/images/kollada.png)bin13907 -> 13907 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/marble.xpm (renamed from tests/benchmarks/qimagereader/images/marble.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/namedcolors.xpm (renamed from tests/benchmarks/qimagereader/images/namedcolors.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/negativeheight.bmp (renamed from tests/benchmarks/qimagereader/images/negativeheight.bmp)bin24630 -> 24630 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/noclearcode.bmp (renamed from tests/benchmarks/qimagereader/images/noclearcode.bmp)bin326 -> 326 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/noclearcode.gif (renamed from tests/benchmarks/qimagereader/images/noclearcode.gif)bin130 -> 130 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/nontransparent.xpm (renamed from tests/benchmarks/qimagereader/images/nontransparent.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/pngwithcompressedtext.png (renamed from tests/benchmarks/qimagereader/images/pngwithcompressedtext.png)bin757 -> 757 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/pngwithtext.png (renamed from tests/benchmarks/qimagereader/images/pngwithtext.png)bin796 -> 796 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/rgba_adobedeflate_littleendian.tif (renamed from tests/benchmarks/qimagereader/images/rgba_adobedeflate_littleendian.tif)bin4784 -> 4784 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/rgba_lzw_littleendian.tif (renamed from tests/benchmarks/qimagereader/images/rgba_lzw_littleendian.tif)bin26690 -> 26690 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/rgba_nocompression_bigendian.tif (renamed from tests/benchmarks/qimagereader/images/rgba_nocompression_bigendian.tif)bin160384 -> 160384 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/rgba_nocompression_littleendian.tif (renamed from tests/benchmarks/qimagereader/images/rgba_nocompression_littleendian.tif)bin160388 -> 160388 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/rgba_packbits_littleendian.tif (renamed from tests/benchmarks/qimagereader/images/rgba_packbits_littleendian.tif)bin161370 -> 161370 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/rgba_zipdeflate_littleendian.tif (renamed from tests/benchmarks/qimagereader/images/rgba_zipdeflate_littleendian.tif)bin14728 -> 14728 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/runners.ppm (renamed from tests/benchmarks/qimagereader/images/runners.ppm)bin960016 -> 960016 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/task210380.jpg (renamed from tests/benchmarks/qimagereader/images/task210380.jpg)bin975535 -> 975535 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/teapot.ppm (renamed from tests/benchmarks/qimagereader/images/teapot.ppm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/test.ppm (renamed from tests/benchmarks/qimagereader/images/test.ppm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/test.xpm (renamed from tests/benchmarks/qimagereader/images/test.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/transparent.xpm (renamed from tests/benchmarks/qimagereader/images/transparent.xpm)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/trolltech.gif (renamed from tests/benchmarks/qimagereader/images/trolltech.gif)bin42629 -> 42629 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/tst7.bmp (renamed from tests/benchmarks/qimagereader/images/tst7.bmp)bin582 -> 582 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/images/tst7.png (renamed from tests/benchmarks/qimagereader/images/tst7.png)bin167 -> 167 bytes-rw-r--r--tests/benchmarks/gui/image/qimagereader/qimagereader.pro (renamed from tests/benchmarks/qimagereader/qimagereader.pro)0
-rw-r--r--tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp (renamed from tests/benchmarks/qimagereader/tst_qimagereader.cpp)0
-rw-r--r--tests/benchmarks/gui/image/qpixmap/qpixmap.pro (renamed from tests/benchmarks/qpixmap/qpixmap.pro)0
-rw-r--r--tests/benchmarks/gui/image/qpixmap/tst_qpixmap.cpp (renamed from tests/benchmarks/qpixmap/tst_qpixmap.cpp)0
-rw-r--r--tests/benchmarks/gui/image/qpixmapcache/qpixmapcache.pro (renamed from tests/benchmarks/qpixmapcache/qpixmapcache.pro)0
-rw-r--r--tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp (renamed from tests/benchmarks/qpixmapcache/tst_qpixmapcache.cpp)0
-rw-r--r--tests/benchmarks/gui/itemviews/itemviews.pro3
-rw-r--r--tests/benchmarks/gui/itemviews/qtableview/qtableview.pro (renamed from tests/benchmarks/qtableview/qtableview.pro)0
-rw-r--r--tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp (renamed from tests/benchmarks/qtableview/tst_qtableview.cpp)0
-rw-r--r--tests/benchmarks/gui/kernel/kernel.pro4
-rw-r--r--tests/benchmarks/gui/kernel/qapplication/main.cpp (renamed from tests/benchmarks/qapplication/main.cpp)0
-rw-r--r--tests/benchmarks/gui/kernel/qapplication/qapplication.pro (renamed from tests/benchmarks/qapplication/qapplication.pro)0
-rw-r--r--tests/benchmarks/gui/kernel/qwidget/qwidget.pro (renamed from tests/benchmarks/qwidget/qwidget.pro)0
-rw-r--r--tests/benchmarks/gui/kernel/qwidget/tst_qwidget.cpp (renamed from tests/benchmarks/qwidget/tst_qwidget.cpp)0
-rw-r--r--tests/benchmarks/gui/math3d/math3d.pro4
-rw-r--r--tests/benchmarks/gui/math3d/qmatrix4x4/qmatrix4x4.pro (renamed from tests/benchmarks/qmatrix4x4/qmatrix4x4.pro)0
-rw-r--r--tests/benchmarks/gui/math3d/qmatrix4x4/tst_qmatrix4x4.cpp (renamed from tests/benchmarks/qmatrix4x4/tst_qmatrix4x4.cpp)0
-rw-r--r--tests/benchmarks/gui/math3d/qquaternion/qquaternion.pro (renamed from tests/benchmarks/qquaternion/qquaternion.pro)0
-rw-r--r--tests/benchmarks/gui/math3d/qquaternion/tst_qquaternion.cpp (renamed from tests/benchmarks/qquaternion/tst_qquaternion.cpp)0
-rw-r--r--tests/benchmarks/gui/painting/painting.pro5
-rw-r--r--tests/benchmarks/gui/painting/qpainter/qpainter.pro (renamed from tests/benchmarks/qpainter/qpainter.pro)0
-rw-r--r--tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp (renamed from tests/benchmarks/qpainter/tst_qpainter.cpp)0
-rw-r--r--tests/benchmarks/gui/painting/qregion/main.cpp (renamed from tests/benchmarks/qregion/main.cpp)0
-rw-r--r--tests/benchmarks/gui/painting/qregion/qregion.pro (renamed from tests/benchmarks/qregion/qregion.pro)0
-rw-r--r--tests/benchmarks/gui/painting/qtransform/qtransform.pro (renamed from tests/benchmarks/qtransform/qtransform.pro)0
-rw-r--r--tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp (renamed from tests/benchmarks/qtransform/tst_qtransform.cpp)0
-rw-r--r--tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp (renamed from tests/benchmarks/qstylesheetstyle/main.cpp)0
-rw-r--r--tests/benchmarks/gui/styles/qstylesheetstyle/qstylesheetstyle.pro (renamed from tests/benchmarks/qstylesheetstyle/qstylesheetstyle.pro)0
-rw-r--r--tests/benchmarks/gui/styles/styles.pro3
-rw-r--r--tests/benchmarks/gui/text/qfontmetrics/main.cpp (renamed from tests/benchmarks/qfontmetrics/main.cpp)0
-rw-r--r--tests/benchmarks/gui/text/qfontmetrics/qfontmetrics.pro (renamed from tests/benchmarks/qfontmetrics/qfontmetrics.pro)0
-rw-r--r--tests/benchmarks/gui/text/qtext/bidi.txt (renamed from tests/benchmarks/qtext/bidi.txt)0
-rw-r--r--tests/benchmarks/gui/text/qtext/main.cpp (renamed from tests/benchmarks/qtext/main.cpp)0
-rw-r--r--tests/benchmarks/gui/text/qtext/qtext.pro (renamed from tests/benchmarks/qtext/qtext.pro)0
-rw-r--r--tests/benchmarks/gui/text/text.pro4
-rw-r--r--tests/benchmarks/network/access/access.pro4
-rw-r--r--tests/benchmarks/network/access/qfile_vs_qnetworkaccessmanager/main.cpp193
-rw-r--r--tests/benchmarks/network/access/qfile_vs_qnetworkaccessmanager/qfile_vs_qnetworkaccessmanager.pro (renamed from tests/benchmarks/qfile_vs_qnetworkaccessmanager/qfile_vs_qnetworkaccessmanager.pro)0
-rw-r--r--tests/benchmarks/network/access/qnetworkreply/qnetworkreply.pro (renamed from tests/benchmarks/qnetworkreply/qnetworkreply.pro)0
-rw-r--r--tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp656
-rw-r--r--tests/benchmarks/network/kernel/kernel.pro3
-rw-r--r--tests/benchmarks/network/kernel/qhostinfo/main.cpp (renamed from tests/benchmarks/qhostinfo/main.cpp)0
-rwxr-xr-xtests/benchmarks/network/kernel/qhostinfo/qhostinfo.pro (renamed from tests/benchmarks/qhostinfo/qhostinfo.pro)0
-rw-r--r--tests/benchmarks/network/network.pro5
-rw-r--r--tests/benchmarks/network/socket/qtcpserver/qtcpserver.pro (renamed from tests/benchmarks/qtcpserver/qtcpserver.pro)0
-rw-r--r--tests/benchmarks/network/socket/qtcpserver/tst_qtcpserver.cpp277
-rw-r--r--tests/benchmarks/network/socket/socket.pro3
-rw-r--r--tests/benchmarks/qfile_vs_qnetworkaccessmanager/main.cpp193
-rw-r--r--tests/benchmarks/qgraphicsview/tst_qgraphicsview.cpp908
-rw-r--r--tests/benchmarks/qnetworkreply/tst_qnetworkreply.cpp656
-rw-r--r--tests/benchmarks/qscriptclass/tst_qscriptclass.cpp511
-rw-r--r--tests/benchmarks/qtcpserver/tst_qtcpserver.cpp277
-rw-r--r--tests/benchmarks/qtestlib-simple/main.cpp117
-rw-r--r--tests/benchmarks/qtestlib-simple/qtestlib-simple.pro8
-rw-r--r--tests/benchmarks/qtwidgets/advanced.ui319
-rw-r--r--tests/benchmarks/qtwidgets/icons/big.pngbin1323 -> 0 bytes-rw-r--r--tests/benchmarks/qtwidgets/icons/folder.pngbin4069 -> 0 bytes-rw-r--r--tests/benchmarks/qtwidgets/icons/icon.bmpbin246 -> 0 bytes-rw-r--r--tests/benchmarks/qtwidgets/icons/icon.pngbin344 -> 0 bytes-rw-r--r--tests/benchmarks/qtwidgets/mainwindow.cpp313
-rw-r--r--tests/benchmarks/qtwidgets/mainwindow.h80
-rw-r--r--tests/benchmarks/qtwidgets/qtstyles.qrc8
-rw-r--r--tests/benchmarks/qtwidgets/qtwidgets.pro9
-rw-r--r--tests/benchmarks/qtwidgets/standard.ui1207
-rw-r--r--tests/benchmarks/qtwidgets/system.ui658
-rw-r--r--tests/benchmarks/qtwidgets/tst_qtwidgets.cpp67
-rw-r--r--tests/benchmarks/script/qscriptclass/qscriptclass.pro (renamed from tests/benchmarks/qscriptclass/qscriptclass.pro)0
-rw-r--r--tests/benchmarks/script/qscriptclass/tst_qscriptclass.cpp285
-rw-r--r--tests/benchmarks/script/qscriptengine/qscriptengine.pro (renamed from tests/benchmarks/qscriptengine/qscriptengine.pro)0
-rw-r--r--tests/benchmarks/script/qscriptengine/tst_qscriptengine.cpp (renamed from tests/benchmarks/qscriptengine/tst_qscriptengine.cpp)0
-rw-r--r--tests/benchmarks/script/qscriptvalue/qscriptvalue.pro (renamed from tests/benchmarks/qscriptvalue/qscriptvalue.pro)0
-rw-r--r--tests/benchmarks/script/qscriptvalue/tst_qscriptvalue.cpp (renamed from tests/benchmarks/qscriptvalue/tst_qscriptvalue.cpp)0
-rw-r--r--tests/benchmarks/script/script.pro5
-rw-r--r--tests/benchmarks/svg/qsvgrenderer/data/tiger.svg (renamed from tests/benchmarks/qsvgrenderer/data/tiger.svg)0
-rw-r--r--tests/benchmarks/svg/qsvgrenderer/qsvgrenderer.pro (renamed from tests/benchmarks/qsvgrenderer/qsvgrenderer.pro)0
-rw-r--r--tests/benchmarks/svg/qsvgrenderer/qsvgrenderer.qrc (renamed from tests/benchmarks/qsvgrenderer/qsvgrenderer.qrc)0
-rw-r--r--tests/benchmarks/svg/qsvgrenderer/tst_qsvgrenderer.cpp (renamed from tests/benchmarks/qsvgrenderer/tst_qsvgrenderer.cpp)0
-rw-r--r--tests/benchmarks/svg/svg.pro3
-rw-r--r--tests/tests.pro3
-rw-r--r--tools/assistant/lib/qhelp_global.cpp3
-rw-r--r--tools/assistant/lib/qhelpenginecore.cpp2
-rw-r--r--tools/assistant/lib/qhelpprojectdata.cpp47
-rw-r--r--tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp230
-rw-r--r--tools/assistant/lib/qhelpsearchresultwidget.cpp2
-rw-r--r--tools/assistant/tools/assistant/aboutdialog.cpp31
-rw-r--r--tools/assistant/tools/assistant/assistant.pro89
-rw-r--r--tools/assistant/tools/assistant/bookmarkdialog.cpp226
-rw-r--r--tools/assistant/tools/assistant/bookmarkdialog.h88
-rw-r--r--tools/assistant/tools/assistant/bookmarkdialog.ui82
-rw-r--r--tools/assistant/tools/assistant/bookmarkfiltermodel.cpp322
-rw-r--r--tools/assistant/tools/assistant/bookmarkfiltermodel.h118
-rw-r--r--tools/assistant/tools/assistant/bookmarkitem.cpp174
-rw-r--r--tools/assistant/tools/assistant/bookmarkitem.h83
-rw-r--r--tools/assistant/tools/assistant/bookmarkmanager.cpp1029
-rw-r--r--tools/assistant/tools/assistant/bookmarkmanager.h201
-rw-r--r--tools/assistant/tools/assistant/bookmarkmodel.cpp425
-rw-r--r--tools/assistant/tools/assistant/bookmarkmodel.h115
-rw-r--r--tools/assistant/tools/assistant/bookmarkwidget.ui82
-rw-r--r--tools/assistant/tools/assistant/centralwidget.cpp356
-rw-r--r--tools/assistant/tools/assistant/centralwidget.h81
-rw-r--r--tools/assistant/tools/assistant/cmdlineparser.cpp7
-rw-r--r--tools/assistant/tools/assistant/contentwindow.cpp4
-rw-r--r--tools/assistant/tools/assistant/findwidget.cpp233
-rw-r--r--tools/assistant/tools/assistant/findwidget.h101
-rw-r--r--tools/assistant/tools/assistant/helpenginewrapper.cpp61
-rw-r--r--tools/assistant/tools/assistant/helpenginewrapper.h9
-rw-r--r--tools/assistant/tools/assistant/helpviewer.cpp600
-rw-r--r--tools/assistant/tools/assistant/helpviewer.h137
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qtb.cpp331
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qtb.h116
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qwv.cpp413
-rw-r--r--tools/assistant/tools/assistant/helpviewer_qwv.h122
-rw-r--r--tools/assistant/tools/assistant/indexwindow.cpp2
-rw-r--r--tools/assistant/tools/assistant/main.cpp43
-rw-r--r--tools/assistant/tools/assistant/mainwindow.cpp184
-rw-r--r--tools/assistant/tools/assistant/mainwindow.h29
-rw-r--r--tools/assistant/tools/assistant/preferencesdialog.cpp30
-rw-r--r--tools/assistant/tools/assistant/topicchooser.cpp10
-rw-r--r--tools/assistant/tools/assistant/xbelsupport.cpp152
-rw-r--r--tools/assistant/tools/assistant/xbelsupport.h22
-rw-r--r--tools/assistant/tools/qcollectiongenerator/main.cpp21
-rw-r--r--tools/assistant/tools/qhelpgenerator/main.cpp11
-rw-r--r--tools/configure/configureapp.cpp4
-rw-r--r--tools/designer/src/components/formeditor/formwindow.cpp1
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor.cpp4
-rw-r--r--tools/designer/src/lib/shared/actionrepository.cpp21
-rw-r--r--tools/designer/src/lib/shared/actionrepository_p.h9
-rw-r--r--tools/designer/src/lib/shared/iconloader.cpp3
-rw-r--r--tools/designer/src/lib/shared/qdesigner_menu.cpp11
-rw-r--r--tools/designer/src/lib/shared/qdesigner_menu_p.h2
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp16
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h8
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertysheet.cpp10
-rw-r--r--tools/installer/README12
-rwxr-xr-xtools/installer/batch/build.bat157
-rwxr-xr-xtools/installer/batch/copy.bat121
-rwxr-xr-xtools/installer/batch/delete.bat73
-rwxr-xr-xtools/installer/batch/env.bat141
-rwxr-xr-xtools/installer/batch/extract.bat83
-rwxr-xr-xtools/installer/batch/installer.bat247
-rwxr-xr-xtools/installer/batch/log.bat58
-rwxr-xr-xtools/installer/batch/toupper.bat69
-rw-r--r--tools/installer/config/config.default.sample64
-rw-r--r--tools/installer/config/mingw-opensource.conf136
-rwxr-xr-xtools/installer/iwmake.bat124
-rw-r--r--tools/installer/nsis/confirmpage.ini59
-rw-r--r--tools/installer/nsis/gwdownload.ini118
-rw-r--r--tools/installer/nsis/gwmirror.ini67
-rw-r--r--tools/installer/nsis/images/install.icobin22486 -> 0 bytes-rw-r--r--tools/installer/nsis/images/qt-header.bmpbin25818 -> 0 bytes-rw-r--r--tools/installer/nsis/images/qt-wizard.bmpbin154542 -> 0 bytes-rw-r--r--tools/installer/nsis/includes/global.nsh143
-rw-r--r--tools/installer/nsis/includes/instdir.nsh254
-rw-r--r--tools/installer/nsis/includes/list.nsh136
-rw-r--r--tools/installer/nsis/includes/qtcommon.nsh549
-rw-r--r--tools/installer/nsis/includes/qtenv.nsh303
-rw-r--r--tools/installer/nsis/includes/system.nsh269
-rw-r--r--tools/installer/nsis/installer.nsi524
-rw-r--r--tools/installer/nsis/modules/environment.nsh216
-rw-r--r--tools/installer/nsis/modules/mingw.nsh670
-rw-r--r--tools/installer/nsis/modules/opensource.nsh94
-rw-r--r--tools/installer/nsis/modules/registeruiext.nsh207
-rw-r--r--tools/installer/nsis/opensource.ini78
-rw-r--r--tools/linguist/linguist/images/transbox.pngbin782 -> 0 bytes-rw-r--r--tools/linguist/linguist/linguist.qrc3
-rw-r--r--tools/linguist/linguist/mainwindow.cpp29
-rw-r--r--tools/linguist/linguist/messageeditor.cpp16
-rw-r--r--tools/linguist/linguist/messageeditorwidgets.cpp6
-rw-r--r--tools/linguist/linguist/messagemodel.cpp48
-rw-r--r--tools/linguist/linguist/messagemodel.h2
-rw-r--r--tools/linguist/lupdate/lupdate.h1
-rw-r--r--tools/linguist/lupdate/lupdate.pro4
-rw-r--r--tools/linguist/lupdate/main.cpp5
-rw-r--r--tools/linguist/lupdate/qml.cpp240
-rw-r--r--tools/qdoc3/cppcodemarker.cpp4
-rw-r--r--tools/qdoc3/test/qml.qdocconf80
-rw-r--r--tools/qdoc3/test/qt-build-docs.qdocconf5
-rw-r--r--tools/qdoc3/test/qt.qdocconf5
-rw-r--r--tools/qmldebugger/qmldebugger.pro5
-rw-r--r--tools/qmldebugger/standalone/canvasframerate.cpp581
-rw-r--r--tools/qmldebugger/standalone/canvasframerate.h91
-rw-r--r--tools/qmldebugger/standalone/engine.cpp219
-rw-r--r--tools/qmldebugger/standalone/engine.h101
-rw-r--r--tools/qmldebugger/standalone/engine.pngbin0 -> 6394 bytes-rw-r--r--tools/qmldebugger/standalone/engines.qml46
-rw-r--r--tools/qmldebugger/standalone/expressionquerywidget.cpp276
-rw-r--r--tools/qmldebugger/standalone/expressionquerywidget.h105
-rw-r--r--tools/qmldebugger/standalone/main.cpp77
-rw-r--r--tools/qmldebugger/standalone/objectpropertiesview.cpp274
-rw-r--r--tools/qmldebugger/standalone/objectpropertiesview.h93
-rw-r--r--tools/qmldebugger/standalone/objecttree.cpp231
-rw-r--r--tools/qmldebugger/standalone/objecttree.h96
-rw-r--r--tools/qmldebugger/standalone/qmldebugger.cpp181
-rw-r--r--tools/qmldebugger/standalone/qmldebugger.h90
-rw-r--r--tools/qmldebugger/standalone/qmldebugger.pri18
-rw-r--r--tools/qmldebugger/standalone/qmldebugger.qrc7
-rw-r--r--tools/qmldebugger/standalone/refresh.pngbin0 -> 6169 bytes-rw-r--r--tools/qmldebugger/standalone/standalone.pro19
-rw-r--r--tools/qmldebugger/standalone/watchtable.cpp366
-rw-r--r--tools/qmldebugger/standalone/watchtable.h154
-rw-r--r--tools/qmlviewer/content/Browser.qml243
-rw-r--r--tools/qmlviewer/content/images/folder.pngbin0 -> 1841 bytes-rw-r--r--tools/qmlviewer/content/images/titlebar.pngbin0 -> 1436 bytes-rw-r--r--tools/qmlviewer/content/images/titlebar.sci5
-rw-r--r--tools/qmlviewer/content/images/up.pngbin0 -> 662 bytes-rw-r--r--tools/qmlviewer/deviceorientation.cpp73
-rw-r--r--tools/qmlviewer/deviceorientation.h69
-rw-r--r--tools/qmlviewer/deviceorientation_maemo.cpp139
-rw-r--r--tools/qmlviewer/main.cpp344
-rw-r--r--tools/qmlviewer/proxysettings.cpp106
-rw-r--r--tools/qmlviewer/proxysettings.h68
-rw-r--r--tools/qmlviewer/proxysettings.ui115
-rw-r--r--tools/qmlviewer/qfxtester.cpp378
-rw-r--r--tools/qmlviewer/qfxtester.h262
-rw-r--r--tools/qmlviewer/qmlfolderlistmodel.cpp416
-rw-r--r--tools/qmlviewer/qmlfolderlistmodel.h119
-rw-r--r--tools/qmlviewer/qmlviewer.cpp1455
-rw-r--r--tools/qmlviewer/qmlviewer.h194
-rw-r--r--tools/qmlviewer/qmlviewer.pro54
-rw-r--r--tools/qmlviewer/qmlviewer.qrc9
-rw-r--r--tools/qmlviewer/recopts.ui513
-rw-r--r--tools/runonphone/main.cpp4
-rw-r--r--tools/runonphone/runonphone.pro4
-rw-r--r--tools/runonphone/symbianutils/bluetoothlistener.cpp224
-rw-r--r--tools/runonphone/symbianutils/bluetoothlistener.h103
-rw-r--r--tools/runonphone/symbianutils/bluetoothlistener_gui.cpp111
-rw-r--r--tools/runonphone/symbianutils/bluetoothlistener_gui.h89
-rw-r--r--tools/runonphone/symbianutils/callback.h160
-rw-r--r--tools/runonphone/symbianutils/communicationstarter.cpp251
-rw-r--r--tools/runonphone/symbianutils/communicationstarter.h160
-rw-r--r--tools/runonphone/symbianutils/launcher.cpp740
-rw-r--r--tools/runonphone/symbianutils/launcher.h179
-rw-r--r--tools/runonphone/symbianutils/symbiandevicemanager.cpp331
-rw-r--r--tools/runonphone/symbianutils/symbiandevicemanager.h145
-rw-r--r--tools/runonphone/symbianutils/symbianutils.pri27
-rw-r--r--tools/runonphone/symbianutils/symbianutils_global.h55
-rw-r--r--tools/runonphone/symbianutils/trkdevice.cpp1122
-rw-r--r--tools/runonphone/symbianutils/trkdevice.h138
-rw-r--r--tools/runonphone/symbianutils/trkutils.cpp480
-rw-r--r--tools/runonphone/symbianutils/trkutils.h185
-rw-r--r--tools/runonphone/symbianutils/trkutils_p.h62
-rw-r--r--tools/runonphone/trk/bluetoothlistener.cpp224
-rw-r--r--tools/runonphone/trk/bluetoothlistener.h101
-rw-r--r--tools/runonphone/trk/bluetoothlistener_gui.cpp111
-rw-r--r--tools/runonphone/trk/bluetoothlistener_gui.h87
-rw-r--r--tools/runonphone/trk/callback.h160
-rw-r--r--tools/runonphone/trk/communicationstarter.cpp260
-rw-r--r--tools/runonphone/trk/communicationstarter.h160
-rw-r--r--tools/runonphone/trk/launcher.cpp740
-rw-r--r--tools/runonphone/trk/launcher.h179
-rw-r--r--tools/runonphone/trk/trk.pri23
-rw-r--r--tools/runonphone/trk/trkdevice.cpp1099
-rw-r--r--tools/runonphone/trk/trkdevice.h133
-rw-r--r--tools/runonphone/trk/trkutils.cpp486
-rw-r--r--tools/runonphone/trk/trkutils.h194
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowserutils.cpp16
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowserutils_p.h1
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertymanager.cpp82
-rw-r--r--translations/designer_de.ts45
-rw-r--r--translations/qt_de.ts541
-rw-r--r--util/qlalr/cppgenerator.cpp2
3249 files changed, 335535 insertions, 21512 deletions
diff --git a/.gitignore b/.gitignore
index c8153fc..548e69e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,15 +5,20 @@ examples/*/*/*
!examples/*/*/*[.]*
!examples/*/*/README
examples/*/*/*[.]app
+!examples/declarative/*
demos/*/*
!demos/*/*[.]*
demos/*/*[.]app
+!demos/declarative/*
config.tests/*/*/*
!config.tests/*/*/*[.]*
config.tests/*/*/*[.]app
+callgrind.out.*
+pcviewer.cfg
*~
*.a
+*.la
*.core
*.moc
*.o
@@ -42,10 +47,12 @@ Makefile*
*.prl
*.app
*.pro.user
+*.gcov
bin/Qt*.dll
bin/assistant*
bin/designer*
bin/dumpcpp*
+bin/duiviewer*
bin/idc*
bin/linguist*
bin/lrelease*
@@ -72,6 +79,12 @@ bin/cetest*
bin/collectiongenerator
bin/helpconverter
bin/helpgenerator
+bin/kmap2qmap*
+bin/qlalr*
+bin/qmlconv*
+bin/qmldebugger*
+bin/qmlviewer*
+bin/qttracereplay*
configure.cache
config.status
mkspecs/default
@@ -94,6 +107,7 @@ tests/auto/qprocess/fileWriterProcess.txt
.com.apple.timemachine.supported
tests/auto/qlibrary/libmylib.so*
tests/auto/qresourceengine/runtime_resource.rcc
+tools/qtestlib/chart/chart*
tools/qtestlib/updater/updater*
tools/activeqt/testcon/testcon.tlb
translations/*.qm
diff --git a/bin/createpackage.pl b/bin/createpackage.pl
index ff89b64..1d6ab6b 100755
--- a/bin/createpackage.pl
+++ b/bin/createpackage.pl
@@ -54,6 +54,8 @@ use Getopt::Long;
use File::Basename;
# Use File::Spec services mainly rel2abs
use File::Spec;
+# Use File::Path - to make stub sis target directory
+use File::Path;
# use CWD abs_bath, which is exported only on request
use Cwd 'abs_path';
@@ -64,7 +66,7 @@ sub Usage() {
==============================================================================================
Convenience script for creating signed packages you can install on your phone.
-Usage: createpackage.pl [options] templatepkg target-platform [certificate key [passphrase]]
+Usage: createpackage.pl [options] templatepkg [target]-[platform] [certificate key [passphrase]]
Where supported optiobns are as follows:
[-i|install] = Install the package right away using PC suite
@@ -72,9 +74,10 @@ Where supported optiobns are as follows:
[-c|certfile=<file>] = The file containing certificate information for signing.
The file can have several certificates, each specified in
separate line. The certificate, key and passphrase in line
- must be ';' separated. Lines starting with '#' are treated
- as a comments. Also empty lines are ignored. The paths in
+ must be ';' separated. Lines starting with '#' are treated
+ as a comments. Also empty lines are ignored. The paths in
<file> can be absolute or relative to <file>.
+ [-u|unsigned] = Preserves the unsigned package
Where parameters are as follows:
templatepkg = Name of .pkg file template
target = Either debug or release
@@ -86,18 +89,18 @@ Where parameters are as follows:
Example:
createpackage.pl fluidlauncher_template.pkg release-armv5
-
+
Example with certfile:
createpackage.pl -c=mycerts.txt fluidlauncher_template.pkg release-armv5
-
+
Content of 'mycerts.txt' must be something like this:
# This is comment line, also the empty lines are ignored
rd.cer;rd-key.pem
.\\cert\\mycert.cer;.\\cert\\mykey.key;yourpassword
- X:\\QtS60\\selfsigned.cer;X:\\QtS60\\selfsigned.key
+ X:\\QtS60\\s60installs\\selfsigned.cer;X:\\QtS60\\s60installs\\selfsigned.key
If no certificate and key files are provided, either a RnD certificate or
-a self-signed certificate from Qt installation root directory is used.
+a self-signed certificate from QtDir\\src\\s60installs directory is used.
==============================================================================================
ENDUSAGESTRING
@@ -109,8 +112,14 @@ ENDUSAGESTRING
my $install = "";
my $preprocessonly = "";
my $certfile = "";
-
-unless (GetOptions('i|install' => \$install, 'p|preprocess' => \$preprocessonly, 'c|certfile=s' => \$certfile)){
+my $preserveUnsigned = "";
+my $stub = "";
+
+unless (GetOptions('i|install' => \$install,
+ 'p|preprocess' => \$preprocessonly,
+ 'c|certfile=s' => \$certfile,
+ 'u|unsigned' => \$preserveUnsigned,
+ 's|stub' => \$stub,)){
Usage();
}
@@ -134,13 +143,21 @@ my $passphrase = $ARGV[4];
# Generate output pkg basename (i.e. file name without extension)
my $pkgoutputbasename = $templatepkg;
-$pkgoutputbasename =~ s/_template\.pkg/_$targetplatform/g;
+my $preservePkgOutput = "";
+$pkgoutputbasename =~ s/_template/_$targetplatform/g;
+if ($pkgoutputbasename eq $templatepkg) {
+ $preservePkgOutput = "1";
+}
+$pkgoutputbasename =~ s/\.pkg//g;
$pkgoutputbasename = lc($pkgoutputbasename);
# Store output file names to variables
my $pkgoutput = lc($pkgoutputbasename.".pkg");
-my $unsigned_sis_name = $pkgoutputbasename."_unsigned.sis";
-my $signed_sis_name = $pkgoutputbasename.".sis";
+my $sisoutputbasename = lc($pkgoutputbasename);
+$sisoutputbasename =~ s/_$targetplatform//g;
+my $unsigned_sis_name = $sisoutputbasename."_unsigned.sis";
+my $signed_sis_name = $sisoutputbasename.".sis";
+my $stub_sis_name = $sisoutputbasename."_stub.sis";
# Store some utility variables
my $scriptpath = dirname(__FILE__);
@@ -148,12 +165,20 @@ my $certtext = $certificate;
# certificates are one step up in hierarchy
my $certpath = File::Spec->catdir($scriptpath, File::Spec->updir(), "src/s60installs/");
-# Check some pre-conditions and print error messages if needed
-unless (length($templatepkg) && length($platform) && length($target)) {
- print "\nError: Template PKG filename, platform or target is not defined!\n";
+# Check some pre-conditions and print error messages if needed.
+unless (length($templatepkg)) {
+ print "\nError: Template PKG filename is not defined!\n";
Usage();
}
+# If the pkg file is not actually a template, there is no need for plaform or target.
+if ($templatepkg =~ m/_template\.pkg/i) {
+ unless (length($platform) && length($target)) {
+ print "\nError: Platform or target is not defined!\n";
+ Usage();
+ }
+}
+
# Check template exist
stat($templatepkg);
unless( -e _ ) {
@@ -190,18 +215,18 @@ if (length($certfile)) {
next if /^(\s)*$/; # skip blank lines
chomp; # remove trailing newline characters
my @certinfo = split(';', $_); # split row to certinfo
-
+
# Trim spaces
for(@certinfo) {
s/^\s+//;
s/\s+$//;
- }
-
+ }
+
# Do some validation
- unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) {
+ unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) {
print "\nError: $certfile line '$_' does not contain valid information!\n";
- Usage();
- }
+ Usage();
+ }
push @certificates, [@certinfo]; # push data to two dimensional array
}
@@ -210,7 +235,9 @@ if (length($certfile)) {
# Remove any existing .sis packages
unlink $unsigned_sis_name;
unlink $signed_sis_name;
-unlink $pkgoutput;
+if (!$preservePkgOutput) {
+ unlink $pkgoutput;
+}
# Preprocess PKG
local $/;
@@ -232,40 +259,57 @@ if ($preprocessonly) {
exit;
}
-# Create SIS.
-system ("makesis $pkgoutput $unsigned_sis_name");
-
-# Sign SIS with certificate info given as an argument.
-system ("signsis $unsigned_sis_name $signed_sis_name $certificate $key $passphrase");
-
-# Check if creating signed SIS Succeeded
-stat($signed_sis_name);
-if( -e _ ) {
- print ("\nSuccessfully created $signed_sis_name using certificate: $certtext!\n");
-
- # Sign with additional certificates & keys
- for my $row ( @certificates ) {
- # Get certificate absolute file names, relative paths are relative to certfilepath
- my $abscert = File::Spec->rel2abs( $row->[0], $certfilepath);
- my $abskey = File::Spec->rel2abs( $row->[1], $certfilepath);
-
- system ("signsis $signed_sis_name $signed_sis_name $abscert $abskey $row->[2]");
- print ("\tAdditionally signed the SIS with certificate: $row->[0]!\n");
- }
-
- # remove temporary pkg and unsigned sis
- unlink $pkgoutput;
- unlink $unsigned_sis_name;
-
- # Install the sis if requested
- if ($install) {
- print ("\nInstalling $signed_sis_name...\n");
- system ("$signed_sis_name");
- }
+if($stub) {
+ if(!($ENV{EPOCROOT})) { die("EPOCROOT must be set to create stub sis files"); }
+ my $systeminstall = "$ENV{EPOCROOT}epoc32/data/z/system/install";
+ mkpath($systeminstall);
+ my $stub_sis_name = $systeminstall."/".$stub_sis_name;
+ # Create stub SIS.
+ system ("makesis -s $pkgoutput $stub_sis_name");
} else {
- # Lets leave the generated PKG for problem solving purposes
- print ("\nSIS creation failed!\n");
+ # Create SIS.
+ system ("makesis $pkgoutput $unsigned_sis_name");
+ print("\n");
+
+ # Sign SIS with certificate info given as an argument.
+ system ("signsis $unsigned_sis_name $signed_sis_name $certificate $key $passphrase");
+
+ # Check if creating signed SIS Succeeded
+ stat($signed_sis_name);
+ if( -e _ ) {
+ my $targetInsert = "";
+ if ($targetplatform ne "-") {
+ $targetInsert = "for $targetplatform ";
+ }
+ print ("Successfully created $signed_sis_name ${targetInsert}using certificate: $certtext!\n");
+
+ # Sign with additional certificates & keys
+ for my $row ( @certificates ) {
+ # Get certificate absolute file names, relative paths are relative to certfilepath
+ my $abscert = File::Spec->rel2abs( $row->[0], $certfilepath);
+ my $abskey = File::Spec->rel2abs( $row->[1], $certfilepath);
+
+ system ("signsis $signed_sis_name $signed_sis_name $abscert $abskey $row->[2]");
+ print ("\tAdditionally signed the SIS with certificate: $row->[0]!\n");
+ }
+
+ # remove temporary pkg and unsigned sis
+ if (!$preservePkgOutput) {
+ unlink $pkgoutput;
+ }
+ if (!$preserveUnsigned) {
+ unlink $unsigned_sis_name;
+ }
+
+ # Install the sis if requested
+ if ($install) {
+ print ("\nInstalling $signed_sis_name...\n");
+ system ("$signed_sis_name");
+ }
+ } else {
+ # Lets leave the generated PKG for problem solving purposes
+ print ("\nSIS creation failed!\n");
+ }
}
-
#end of file
diff --git a/bin/patch_capabilities.pl b/bin/patch_capabilities.pl
index 8afe776..f82c48f 100755
--- a/bin/patch_capabilities.pl
+++ b/bin/patch_capabilities.pl
@@ -131,9 +131,13 @@ if (@ARGV)
}
}
- # Remove all dependencies to other packages to reduce unnecessary error messages
- # from depended packages that are also patched and therefore have different UID.
- if ($line =~ m/^\(0x[0-9|a-f|A-F]*\).*\{.*\}$/)
+ # Remove dependencies to known problem packages (i.e. packages that are likely to be patched, also)
+ # to reduce unnecessary error messages.
+ if ($line =~ m/^\(0x2002af5f\).*\{.*\}$/)
+ {
+ $newLine = "\n"
+ }
+ if ($line =~ m/^\(0x2001E61C\).*\{.*\}$/)
{
$newLine = "\n"
}
diff --git a/bin/syncqt b/bin/syncqt
index 803bae2..6fb21dd 100755
--- a/bin/syncqt
+++ b/bin/syncqt
@@ -62,6 +62,7 @@ my %moduleheaders = ( # restrict the module headers to those found in relative p
# global variables (modified by options)
my $module = 0;
my $showonly = 0;
+my $quiet = 0;
my $remove_stale = 1;
my $force_win = 0;
my $force_relative = 0;
@@ -92,6 +93,7 @@ sub showUsage
print " -windows Force platform to Windows (default: " . ($force_win ? "yes" : "no") . ")\n";
print " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n";
print " -outdir <PATH> Specify output directory for sync (default: $out_basedir)\n";
+ print " -quiet Only report problems, not activity (default: " . ($quiet ? "yes" : "no") . ")\n";
print " -separate-module <NAME>:<PROFILEDIR>:<HEADERDIR> Create headers for <NAME> with original headers in <HEADERDIR> relative to <PROFILEDIR> \n";
print " -help This help\n";
exit 0;
@@ -193,6 +195,8 @@ sub classNames {
push @ret, "QtConcurrentFilter"
} elsif(basename($iheader) eq "qtconcurrentrun.h") {
push @ret, "QtConcurrentRun"
+ } elsif(basename($iheader) eq "qaudio.h") {
+ push @ret, "QAudio"
}
my $parsable = "";
@@ -322,7 +326,7 @@ sub syncHeader {
unless(-e "$header") {
my $header_dir = dirname($header);
- mkpath $header_dir, 0777;
+ mkpath $header_dir, !$quiet;
#write it
my $iheader_out = fixPaths($iheader, $header_dir);
@@ -462,7 +466,7 @@ sub copyFile
if ( $knowdiff || ($filecontents ne $ifilecontents) ) {
if ( $copy > 0 ) {
my $file_dir = dirname($file);
- mkpath $file_dir, 0777 unless(-e "$file_dir");
+ mkpath $file_dir, !$quiet unless(-e "$file_dir");
open(O, "> " . $file) || die "Could not open $file for writing (no write permission?)";
local $/;
binmode O;
@@ -471,7 +475,7 @@ sub copyFile
return 1;
} elsif ( $copy < 0 ) {
my $ifile_dir = dirname($ifile);
- mkpath $ifile_dir, 0777 unless(-e "$ifile_dir");
+ mkpath $ifile_dir, !$quiet unless(-e "$ifile_dir");
open(O, "> " . $ifile) || die "Could not open $ifile for writing (no write permission?)";
local $/;
binmode O;
@@ -497,7 +501,7 @@ sub symlinkFile
my ($file,$ifile) = @_;
if ($isunix) {
- print "symlink created for $file ";
+ print "symlink created for $file " unless $quiet;
if ( $force_relative && ($ifile =~ /^$basedir/)) {
my $t = getcwd();
my $c = -1;
@@ -505,9 +509,9 @@ sub symlinkFile
$t =~ s-^$basedir/--;
$p .= "../" while( ($c = index( $t, "/", $c + 1)) != -1 );
$file =~ s-^$basedir/-$p-;
- print " ($file)\n";
+ print " ($file)\n" unless $quiet;
}
- print "\n";
+ print "\n" unless $quiet;
return symlink($file, $ifile);
}
return copyFile($file, $ifile);
@@ -591,6 +595,9 @@ while ( @ARGV ) {
} elsif("$arg" eq "-show") {
$var = "showonly";
$val = "yes";
+ } elsif("$arg" eq "-quiet") {
+ $var = "quiet";
+ $val = "yes";
} elsif("$arg" eq "-base-dir") {
# skip, it's been dealt with at the top of the file
shift @ARGV;
@@ -613,6 +620,12 @@ while ( @ARGV ) {
} elsif($showonly) {
$showonly--;
}
+ } elsif ("$var" eq "quiet") {
+ if("$val" eq "yes") {
+ $quiet++;
+ } elsif($quiet) {
+ $quiet--;
+ }
} elsif ("$var" eq "check-includes") {
if("$val" eq "yes") {
$check_includes++;
@@ -638,7 +651,7 @@ while ( @ARGV ) {
$force_relative--;
}
} elsif ("$var" eq "module") {
- print "module :$val:\n";
+ print "module :$val:\n" unless $quiet;
die "No such module: $val" unless(defined $modules{$val});
push @modules_to_sync, $val;
} elsif ("$var" eq "separate-module") {
@@ -666,7 +679,7 @@ while ( @ARGV ) {
$isunix = checkUnix; #cache checkUnix
# create path
-mkpath "$out_basedir/include", 0777;
+mkpath "$out_basedir/include", !$quiet;
my @ignore_headers = ();
my $class_lib_map_contents = "";
@@ -869,7 +882,7 @@ foreach (@modules_to_sync) {
$pri_install_pfiles.= "$pri_install_iheader ";;
}
}
- print "header created for $iheader ($header_copies)\n" if($header_copies > 0);
+ print "header created for $iheader ($header_copies)\n" if($header_copies > 0 && !$quiet);
}
}
}
@@ -896,8 +909,8 @@ foreach (@modules_to_sync) {
}
if($master_include && $master_contents) {
my $master_dir = dirname($master_include);
- mkpath $master_dir, 0777;
- print "header (master) created for $lib\n";
+ mkpath $master_dir, !$quiet;
+ print "header (master) created for $lib\n" unless $quiet;
open MASTERINCLUDE, ">$master_include";
print MASTERINCLUDE "$master_contents";
close MASTERINCLUDE;
@@ -921,8 +934,8 @@ foreach (@modules_to_sync) {
}
if($headers_pri_file && $master_contents) {
my $headers_pri_dir = dirname($headers_pri_file);
- mkpath $headers_pri_dir, 0777;
- print "headers.pri file created for $lib\n";
+ mkpath $headers_pri_dir, !$quiet;
+ print "headers.pri file created for $lib\n" unless $quiet;
open HEADERS_PRI_FILE, ">$headers_pri_file";
print HEADERS_PRI_FILE "$headers_pri_contents";
close HEADERS_PRI_FILE;
@@ -942,7 +955,7 @@ unless($showonly || !$create_uic_class_map) {
}
if($class_lib_map) {
my $class_lib_map_dir = dirname($class_lib_map);
- mkpath $class_lib_map_dir, 0777;
+ mkpath $class_lib_map_dir, !$quiet;
open CLASS_LIB_MAP, ">$class_lib_map";
print CLASS_LIB_MAP "$class_lib_map_contents";
close CLASS_LIB_MAP;
diff --git a/configure b/configure
index ae6d724..cd29e95 100755
--- a/configure
+++ b/configure
@@ -3373,10 +3373,10 @@ Configure options:
-debug-and-release . Compile and link two versions of Qt, with and without
debugging turned on (Mac only).
- -developer-build.... Compile and link Qt with Qt developer options (including auto-tests exporting)
+ -developer-build ... Compile and link Qt with Qt developer options (including auto-tests exporting)
- -opensource......... Compile and link the Open-Source Edition of Qt.
- -commercial......... Compile and link the Commercial Edition of Qt.
+ -opensource ........ Compile and link the Open-Source Edition of Qt.
+ -commercial ........ Compile and link the Commercial Edition of Qt.
* -shared ............ Create and use shared Qt libraries.
@@ -3769,7 +3769,7 @@ Qt/X11 only:
Requires fontconfig/fontconfig.h, libfontconfig,
freetype.h and libfreetype.
- $XIN -no-xinput.......... Do not compile Xinput support.
+ $XIN -no-xinput ......... Do not compile Xinput support.
$XIY -xinput ............ Compile Xinput support. This also enabled tablet support
which requires IRIX with wacom.h and libXi or
XFree86 with X11/extensions/XInput.h and libXi.
diff --git a/configure.exe b/configure.exe
index 21fdcfa..8913de1 100644
--- a/configure.exe
+++ b/configure.exe
Binary files differ
diff --git a/demos/browser/browser.pro b/demos/browser/browser.pro
index a42aa60..f038c61 100644
--- a/demos/browser/browser.pro
+++ b/demos/browser/browser.pro
@@ -6,8 +6,6 @@ CONFIG += qt warn_on
contains(QT_BUILD_PARTS, tools):!embedded: CONFIG += uitools
else: DEFINES += QT_NO_UITOOLS
-release:DEFINES+=QT_NO_DEBUG_OUTPUT QT_NO_WARNING_OUTPUT
-
FORMS += \
addbookmarkdialog.ui \
bookmarks.ui \
diff --git a/demos/browser/networkaccessmanager.cpp b/demos/browser/networkaccessmanager.cpp
index b0b00a2..70a9305 100644
--- a/demos/browser/networkaccessmanager.cpp
+++ b/demos/browser/networkaccessmanager.cpp
@@ -112,8 +112,9 @@ void NetworkAccessManager::requestFinished(QNetworkReply *reply)
double pctCached = (double(requestFinishedFromCacheCount) * 100.0/ double(requestFinishedCount));
double pctPipelined = (double(requestFinishedPipelinedCount) * 100.0/ double(requestFinishedCount));
double pctSecure = (double(requestFinishedSecureCount) * 100.0/ double(requestFinishedCount));
+#ifdef QT_DEBUG
qDebug("STATS [%lli requests total] [%3.2f%% from cache] [%3.2f%% pipelined] [%3.2f%% SSL/TLS]", requestFinishedCount, pctCached, pctPipelined, pctSecure);
-
+#endif
}
void NetworkAccessManager::loadSettings()
diff --git a/demos/browser/webview.cpp b/demos/browser/webview.cpp
index 1a7e38a..2f9b3e6 100644
--- a/demos/browser/webview.cpp
+++ b/demos/browser/webview.cpp
@@ -143,11 +143,19 @@ QObject *WebPage::createPlugin(const QString &classId, const QUrl &url, const QS
void WebPage::handleUnsupportedContent(QNetworkReply *reply)
{
- if (reply->error() == QNetworkReply::NoError) {
- BrowserApplication::downloadManager()->handleUnsupportedContent(reply);
+ QString errorString = reply->errorString();
+
+ if (m_loadingUrl != reply->url()) {
+ // sub resource of this page
+ qWarning() << "Resource" << reply->url().toEncoded() << "has unknown Content-Type, will be ignored.";
+ reply->deleteLater();
return;
}
+ if (reply->error() == QNetworkReply::NoError && !reply->header(QNetworkRequest::ContentTypeHeader).isValid()) {
+ errorString = "Unknown Content-Type";
+ }
+
QFile file(QLatin1String(":/notfound.html"));
bool isOpened = file.open(QIODevice::ReadOnly);
Q_ASSERT(isOpened);
@@ -156,7 +164,7 @@ void WebPage::handleUnsupportedContent(QNetworkReply *reply)
QString title = tr("Error loading page: %1").arg(reply->url().toString());
QString html = QString(QLatin1String(file.readAll()))
.arg(title)
- .arg(reply->errorString())
+ .arg(errorString)
.arg(reply->url().toString());
QBuffer imageBuffer;
diff --git a/demos/declarative/calculator/CalcButton.qml b/demos/declarative/calculator/CalcButton.qml
new file mode 100644
index 0000000..08851d0
--- /dev/null
+++ b/demos/declarative/calculator/CalcButton.qml
@@ -0,0 +1,41 @@
+import Qt 4.6
+
+Rectangle {
+ property alias operation: label.text
+ property bool toggable: false
+ property bool toggled: false
+ signal clicked
+
+ id: button; width: 50; height: 30
+ border.color: palette.mid; radius: 6
+ gradient: Gradient {
+ GradientStop { id: gradientStop1; position: 0.0; color: Qt.lighter(palette.button) }
+ GradientStop { id: gradientStop2; position: 1.0; color: palette.button }
+ }
+
+ Text { id: label; anchors.centerIn: parent; color: palette.buttonText }
+
+ MouseRegion {
+ id: clickRegion
+ anchors.fill: parent
+ onClicked: {
+ doOp(operation);
+ button.clicked();
+ if (!button.toggable) return;
+ button.toggled ? button.toggled = false : button.toggled = true
+ }
+ }
+
+ states: [
+ State {
+ name: "Pressed"; when: clickRegion.pressed == true
+ PropertyChanges { target: gradientStop1; color: palette.dark }
+ PropertyChanges { target: gradientStop2; color: palette.button }
+ },
+ State {
+ name: "Toggled"; when: button.toggled == true
+ PropertyChanges { target: gradientStop1; color: palette.dark }
+ PropertyChanges { target: gradientStop2; color: palette.button }
+ }
+ ]
+}
diff --git a/demos/declarative/calculator/calculator.js b/demos/declarative/calculator/calculator.js
new file mode 100644
index 0000000..cd6490a
--- /dev/null
+++ b/demos/declarative/calculator/calculator.js
@@ -0,0 +1,87 @@
+
+var curVal = 0;
+var memory = 0;
+var lastOp = "";
+var timer = 0;
+
+function disabled(op) {
+ if (op == "." && curNum.text.toString().search(/\./) != -1) {
+ return true;
+ } else if (op == "Sqrt" && curNum.text.toString().search(/-/) != -1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function doOp(op) {
+ if (disabled(op)) {
+ return;
+ }
+
+ if (op.toString().length==1 && ((op >= "0" && op <= "9") || op==".") ) {
+ if (curNum.text.toString().length >= 14)
+ return; // No arbitrary length numbers
+ if (lastOp.toString().length == 1 && ((lastOp >= "0" && lastOp <= "9") || lastOp==".") ) {
+ curNum.text = curNum.text + op.toString();
+ } else {
+ curNum.text = op;
+ }
+ lastOp = op;
+ return;
+ }
+ lastOp = op;
+
+ // Pending operations
+ if (currentOperation.text == "+") {
+ curNum.text = Number(curNum.text.valueOf()) + Number(curVal.valueOf());
+ } else if (currentOperation.text == "-") {
+ curNum.text = Number(curVal) - Number(curNum.text.valueOf());
+ } else if (currentOperation.text == "x") {
+ curNum.text = Number(curVal) * Number(curNum.text.valueOf());
+ } else if (currentOperation.text == "/") {
+ curNum.text = Number(Number(curVal) / Number(curNum.text.valueOf())).toString();
+ } else if (currentOperation.text == "=") {
+ }
+
+ if (op == "+" || op == "-" || op == "x" || op == "/") {
+ currentOperation.text = op;
+ curVal = curNum.text.valueOf();
+ return;
+ }
+ curVal = 0;
+ currentOperation.text = "";
+
+ // Immediate operations
+ if (op == "1/x") { // reciprocal
+ curNum.text = (1 / curNum.text.valueOf()).toString();
+ } else if (op == "^2") { // squared
+ curNum.text = (curNum.text.valueOf() * curNum.text.valueOf()).toString();
+ } else if (op == "Abs") {
+ curNum.text = (Math.abs(curNum.text.valueOf())).toString();
+ } else if (op == "Int") {
+ curNum.text = (Math.floor(curNum.text.valueOf())).toString();
+ } else if (op == "+/-") { // plus/minus
+ curNum.text = (curNum.text.valueOf() * -1).toString();
+ } else if (op == "Sqrt") { // square root
+ curNum.text = (Math.sqrt(curNum.text.valueOf())).toString();
+ } else if (op == "MC") { // memory clear
+ memory = 0;
+ } else if (op == "M+") { // memory increment
+ memory += curNum.text.valueOf();
+ } else if (op == "MR") { // memory recall
+ curNum.text = memory.toString();
+ } else if (op == "MS") { // memory set
+ memory = curNum.text.valueOf();
+ } else if (op == "Bksp") {
+ curNum.text = curNum.text.toString().slice(0, -1);
+ } else if (op == "C") {
+ curNum.text = "0";
+ } else if (op == "AC") {
+ curVal = 0;
+ memory = 0;
+ lastOp = "";
+ curNum.text ="0";
+ }
+}
+
diff --git a/demos/declarative/calculator/calculator.qml b/demos/declarative/calculator/calculator.qml
new file mode 100644
index 0000000..d9b73ed
--- /dev/null
+++ b/demos/declarative/calculator/calculator.qml
@@ -0,0 +1,124 @@
+import Qt 4.6
+
+Rectangle {
+ width: 320; height: 270; color: palette.window
+
+ SystemPalette { id: palette }
+ Script { source: "calculator.js" }
+
+ Column {
+ x: 2; spacing: 10;
+
+ Rectangle {
+ id: container
+ width: 316; height: 50
+ border.color: palette.dark; color: palette.base
+
+ Text {
+ id: curNum
+ font.bold: true; font.pointSize: 16
+ color: palette.text
+ anchors.right: container.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: container.verticalCenter
+ }
+
+ Text {
+ id: currentOperation
+ color: palette.text
+ font.bold: true; font.pointSize: 16
+ anchors.left: container.left
+ anchors.leftMargin: 5
+ anchors.verticalCenter: container.verticalCenter
+ }
+ }
+
+ Item {
+ width: 320; height: 30
+
+ CalcButton {
+ id: advancedCheckBox
+ x: 55; width: 206
+ operation: "Advanced Mode"
+ toggable: true
+ }
+ }
+
+ Item {
+ width: 320; height: 160
+
+ Item {
+ id: basicButtons
+ x: 55; width: 160; height: 160
+
+ CalcButton { operation: "Bksp"; id: bksp; width: 67; opacity: 0 }
+ CalcButton { operation: "C"; id: c; width: 76 }
+ CalcButton { operation: "AC"; id: ac; x: 78; width: 76 }
+
+ Grid {
+ id: numKeypad; y: 32; spacing: 2; columns: 3
+
+ CalcButton { operation: "7" }
+ CalcButton { operation: "8" }
+ CalcButton { operation: "9" }
+ CalcButton { operation: "4" }
+ CalcButton { operation: "5" }
+ CalcButton { operation: "6" }
+ CalcButton { operation: "1" }
+ CalcButton { operation: "2" }
+ CalcButton { operation: "3" }
+ }
+
+ Row {
+ y: 128; spacing: 2
+
+ CalcButton { operation: "0"; width: 50 }
+ CalcButton { operation: "."; x: 77; width: 50 }
+ CalcButton { operation: "="; id: equals; x: 77; width: 102 }
+ }
+
+ Column {
+ id: simpleOperations
+ x: 156; y: 0; spacing: 2
+
+ CalcButton { operation: "x" }
+ CalcButton { operation: "/" }
+ CalcButton { operation: "-" }
+ CalcButton { operation: "+" }
+ }
+ }
+
+ Grid {
+ id: advancedButtons
+ x: 350; spacing: 2; columns: 2; opacity: 0
+
+ CalcButton { operation: "Abs" }
+ CalcButton { operation: "Int" }
+ CalcButton { operation: "MC" }
+ CalcButton { operation: "Sqrt" }
+ CalcButton { operation: "MR" }
+ CalcButton { operation: "^2" }
+ CalcButton { operation: "MS" }
+ CalcButton { operation: "1/x" }
+ CalcButton { operation: "M+" }
+ CalcButton { operation: "+/-" }
+ }
+ }
+ }
+
+ states: State {
+ name: "Advanced"; when: advancedCheckBox.toggled == true
+ PropertyChanges { target: basicButtons; x: 0 }
+ PropertyChanges { target: simpleOperations; y: 32 }
+ PropertyChanges { target: bksp; opacity: 1 }
+ PropertyChanges { target: c; x: 69; width: 67 }
+ PropertyChanges { target: ac; x: 138; width: 67 }
+ PropertyChanges { target: equals; width: 50 }
+ PropertyChanges { target: advancedButtons; x: 210; opacity: 1 }
+ }
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "x,y,width"; easing: "easeOutBounce"; duration: 500 }
+ NumberAnimation { matchProperties: "opacity"; easing: "easeInOutQuad"; duration: 500 }
+ }
+}
diff --git a/demos/declarative/flickr/common/ImageDetails.qml b/demos/declarative/flickr/common/ImageDetails.qml
new file mode 100644
index 0000000..95c32e8
--- /dev/null
+++ b/demos/declarative/flickr/common/ImageDetails.qml
@@ -0,0 +1,161 @@
+import Qt 4.6
+
+Flipable {
+ id: container
+
+ property var frontContainer: containerFront
+ property string photoTitle: ""
+ property string photoDescription: ""
+ property string photoTags: ""
+ property int photoWidth
+ property int photoHeight
+ property string photoType
+ property string photoAuthor
+ property string photoDate
+ property string photoUrl
+ property int rating: 2
+ property var prevScale: 1.0
+
+ signal closed
+
+ transform: Rotation {
+ id: detailsRotation
+ origin.y: container.height / 2;
+ origin.x: container.width / 2;
+ axis.y: 1; axis.z: 0
+ }
+
+ front: Item {
+ id: containerFront; anchors.fill: container
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"; opacity: 0.4
+ border.color: "white"; border.width: 2
+ }
+
+ MediaButton {
+ id: backButton; x: 630; y: 370; text: "Back"
+ onClicked: { container.closed() }
+ }
+
+ MediaButton {
+ id: moreButton; x: 530; y: 370; text: "View..."
+ onClicked: { container.state='Back' }
+ }
+
+ Text { id: titleText; style: Text.Raised; styleColor: "black"; color: "white"; elide: Text.ElideRight
+ x: 220; y: 30; width: parent.width - 240; text: container.photoTitle; font.pointSize: 22 }
+
+ LikeOMeter { x: 40; y: 250; rating: container.rating }
+
+ Flickable { id: flickable; x: 220; width: 480; height: 210; y: 130; clip: true
+ viewportWidth: 480; viewportHeight: descriptionText.height
+
+ WebView { id: descriptionText; width: parent.width
+ html: "<style TYPE=\"text/css\">body {color: white;} a:link {color: cyan; text-decoration: underline; }</style>" + container.photoDescription }
+ }
+
+ Text { id: size; color: "white"; width: 300; x: 40; y: 300
+ text: "<b>Size:</b> " + container.photoWidth + 'x' + container.photoHeight }
+ Text { id: type; color: "white"; width: 300; x: 40; anchors.top: size.bottom
+ text: "<b>Type:</b> " + container.photoType }
+
+ Text { id: author; color: "white"; width: 300; x: 220; y: 80
+ text: "<b>Author:</b> " + container.photoAuthor }
+ Text { id: date; color: "white"; width: 300; x: 220; anchors.top: author.bottom
+ text: "<b>Published:</b> " + container.photoDate }
+ Text { id: tagsLabel; color: "white"; x: 220; anchors.top: date.bottom;
+ text: container.photoTags == "" ? "" : "<b>Tags:</b> " }
+ Text { id: tags; color: "white"; width: parent.width-x-20;
+ anchors.left: tagsLabel.right; anchors.top: date.bottom;
+ elide: Text.ElideRight; text: container.photoTags }
+
+ ScrollBar { id: scrollBar; x: 720; y: flickable.y; width: 7; height: flickable.height; opacity: 0;
+ flickableArea: flickable; clip: true }
+ }
+
+ back: Item {
+ anchors.fill: container
+
+ Rectangle { anchors.fill: parent; color: "black"; opacity: 0.4; border.color: "white"; border.width: 2 }
+
+ Progress { anchors.centerIn: parent; width: 200; height: 18; progress: bigImage.progress; visible: bigImage.status!=1 }
+ Flickable {
+ id: flick; width: container.width - 10; height: container.height - 10
+ x: 5; y: 5; clip: true;
+ viewportWidth: imageContainer.width; viewportHeight: imageContainer.height
+
+ Item {
+ id: imageContainer
+ width: Math.max(bigImage.width * bigImage.scale, flick.width);
+ height: Math.max(bigImage.height * bigImage.scale, flick.height);
+
+ Image {
+ id: bigImage; source: container.photoUrl; scale: slider.value
+ // Center image if it is smaller than the flickable area.
+ x: imageContainer.width > width*scale ? (imageContainer.width - width*scale) / 2 : 0
+ y: imageContainer.height > height*scale ? (imageContainer.height - height*scale) / 2 : 0
+ smooth: !flick.moving
+ onStatusChanged : {
+ // Default scale shows the entire image.
+ if (status == 1 && width != 0) {
+ slider.minimum = Math.min(flick.width / width, flick.height / height);
+ prevScale = Math.min(slider.minimum, 1);
+ slider.value = prevScale;
+ }
+ }
+ }
+ }
+ }
+
+ MediaButton {
+ id: backButton2; x: 630; y: 370; text: "Back"; onClicked: { container.state = '' }
+ }
+ Text {
+ text: "Image Unavailable"
+ visible: bigImage.status == 'Error'
+ anchors.centerIn: parent; color: "white"; font.bold: true
+ }
+
+ Slider {
+ id: slider; x: 25; y: 374; visible: { bigImage.status == 1 && maximum > minimum }
+ onValueChanged: {
+ if (bigImage.width * value > flick.width) {
+ var xoff = (flick.width/2 + flick.viewportX) * value / prevScale;
+ flick.viewportX = xoff - flick.width/2;
+ }
+ if (bigImage.height * value > flick.height) {
+ var yoff = (flick.height/2 + flick.viewportY) * value / prevScale;
+ flick.viewportY = yoff - flick.height/2;
+ }
+ prevScale = value;
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "Back"
+ PropertyChanges { target: detailsRotation; angle: 180 }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ SequentialAnimation {
+ PropertyAction {
+ target: bigImage
+ property: "smooth"
+ value: false
+ }
+ NumberAnimation { easing: "easeInOutQuad"; matchProperties: "angle"; duration: 500 }
+ PropertyAction {
+ target: bigImage
+ property: "smooth"
+ value: !flick.moving
+ }
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/common/LikeOMeter.qml b/demos/declarative/flickr/common/LikeOMeter.qml
new file mode 100644
index 0000000..5ee048b
--- /dev/null
+++ b/demos/declarative/flickr/common/LikeOMeter.qml
@@ -0,0 +1,35 @@
+import Qt 4.6
+
+Item {
+ id: container
+
+ property int rating: 2
+
+ Row {
+ Star {
+ rating: 0
+ onClicked: { container.rating = rating }
+ on: container.rating >= 0
+ }
+ Star {
+ rating: 1
+ onClicked: { container.rating = rating }
+ on: container.rating >= 1
+ }
+ Star {
+ rating: 2
+ onClicked: { container.rating = rating }
+ on: container.rating >= 2
+ }
+ Star {
+ rating: 3
+ onClicked: { container.rating = rating }
+ on: container.rating >= 3
+ }
+ Star {
+ rating: 4
+ onClicked: { container.rating = rating }
+ on: container.rating >= 4
+ }
+ }
+}
diff --git a/demos/declarative/flickr/common/Loading.qml b/demos/declarative/flickr/common/Loading.qml
new file mode 100644
index 0000000..64a04c4
--- /dev/null
+++ b/demos/declarative/flickr/common/Loading.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Image {
+ id: loading; source: "pics/loading.png"; transformOrigin: "Center"
+ rotation: NumberAnimation {
+ id: "RotationAnimation"; from: 0; to: 360; running: loading.visible == true; repeat: true; duration: 900
+ }
+}
diff --git a/demos/declarative/flickr/common/MediaButton.qml b/demos/declarative/flickr/common/MediaButton.qml
new file mode 100644
index 0000000..c12b642
--- /dev/null
+++ b/demos/declarative/flickr/common/MediaButton.qml
@@ -0,0 +1,41 @@
+import Qt 4.6
+
+Item {
+ id: container
+
+ signal clicked
+
+ property string text
+
+ Image {
+ id: buttonImage
+ source: "pics/button.png"
+ }
+ Image {
+ id: pressed
+ source: "pics/button-pressed.png"
+ opacity: 0
+ }
+ MouseRegion {
+ id: mouseRegion
+ anchors.fill: buttonImage
+ onClicked: { container.clicked(); }
+ }
+ Text {
+ font.bold: true
+ color: "white"
+ anchors.centerIn: buttonImage
+ text: container.text
+ }
+ width: buttonImage.width
+ states: [
+ State {
+ name: "Pressed"
+ when: mouseRegion.pressed == true
+ PropertyChanges {
+ target: pressed
+ opacity: 1
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/common/MediaLineEdit.qml b/demos/declarative/flickr/common/MediaLineEdit.qml
new file mode 100644
index 0000000..abc8034
--- /dev/null
+++ b/demos/declarative/flickr/common/MediaLineEdit.qml
@@ -0,0 +1,104 @@
+import Qt 4.6
+
+Item {
+ id: container
+
+ property string label
+ property string text
+
+ width: Math.max(94,labeltext.width + editor.width + 20)
+ height: buttonImage.height
+
+ states: [
+ State {
+ name: "Edit"
+ PropertyChanges {
+ target: labeltext
+ text: container.label + ": "
+ }
+ PropertyChanges {
+ target: labeltext
+ x: 10
+ }
+ PropertyChanges {
+ target: editor
+ cursorVisible: true
+ width: 100
+ }
+ PropertyChanges {
+ target: container
+ focus: true
+ }
+ StateChangeScript {
+ script:editor.selectAll()
+ }
+ },
+ State {
+ // When returning to default state, typed text is propagated
+ StateChangeScript {
+ script: container.text = editor.text
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation { matchProperties: "x,width"; duration: 500; easing: "easeInOutQuad" }
+ }
+ ]
+
+
+ BorderImage {
+ id: buttonImage
+ source: "pics/button.sci"
+ anchors.left: container.left
+ anchors.right: container.right
+ }
+
+ BorderImage {
+ id: pressed
+ source: "pics/button-pressed.sci"
+ opacity: 0
+ anchors.left: container.left
+ anchors.right: container.right
+ }
+
+ MouseRegion {
+ id: mouseRegion
+ anchors.fill: buttonImage
+ onClicked: { container.state = container.state=="Edit" ? "" : "Edit" }
+ states: [
+ State {
+ when: mouseRegion.pressed == true
+ PropertyChanges {
+ target: pressed
+ opacity: 1
+ }
+ }
+ ]
+ }
+
+ Text {
+ id: labeltext
+ font.bold: true
+ color: "white"
+ anchors.verticalCenter: container.verticalCenter
+ x: (container.width - width)/2
+ text: container.label + "..."
+ }
+
+ TextInput {
+ id: editor
+ font.bold: true
+ color: "white"
+ selectionColor: "green"
+ width: 0
+ clip: true
+ anchors.left: labeltext.right
+ anchors.verticalCenter: container.verticalCenter
+ }
+ Keys.forwardTo: [(returnKey), (editor)]
+ Item {
+ id: returnKey
+ Keys.onReturnPressed: "container.state = ''"
+ }
+}
diff --git a/demos/declarative/flickr/common/Progress.qml b/demos/declarative/flickr/common/Progress.qml
new file mode 100644
index 0000000..fd9be10
--- /dev/null
+++ b/demos/declarative/flickr/common/Progress.qml
@@ -0,0 +1,32 @@
+import Qt 4.6
+
+Item {
+ property var progress: 0
+
+ Rectangle {
+ anchors.fill: parent; smooth: true
+ border.color: "white"; border.width: 0; radius: height/2 - 2
+ gradient: Gradient {
+ GradientStop { position: 0; color: "#66343434" }
+ GradientStop { position: 1.0; color: "#66000000" }
+ }
+ }
+
+ Rectangle {
+ y: 2; height: parent.height-4;
+ x: 2; width: Math.max(parent.width * progress - 4, 0);
+ opacity: width < 1 ? 0 : 1; smooth: true
+ gradient: Gradient {
+ GradientStop { position: 0; color: "lightsteelblue" }
+ GradientStop { position: 1.0; color: "steelblue" }
+ }
+ radius: height/2 - 2
+ }
+
+ Text {
+ text: Math.round(progress * 100) + "%"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ color: "white"; font.bold: true
+ }
+}
diff --git a/demos/declarative/flickr/common/RssModel.qml b/demos/declarative/flickr/common/RssModel.qml
new file mode 100644
index 0000000..ed9fd5c
--- /dev/null
+++ b/demos/declarative/flickr/common/RssModel.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+XmlListModel {
+ property string tags : ""
+
+ source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+ query: "/rss/channel/item"
+ namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" }
+ XmlRole { name: "url"; query: "media:content/@url/string()" }
+ XmlRole { name: "description"; query: "description/string()" }
+ XmlRole { name: "tags"; query: "media:category/string()" }
+ XmlRole { name: "photoWidth"; query: "media:content/@width/string()" }
+ XmlRole { name: "photoHeight"; query: "media:content/@height/string()" }
+ XmlRole { name: "photoType"; query: "media:content/@type/string()" }
+ XmlRole { name: "photoAuthor"; query: "author/string()" }
+ XmlRole { name: "photoDate"; query: "pubDate/string()" }
+}
diff --git a/demos/declarative/flickr/common/ScrollBar.qml b/demos/declarative/flickr/common/ScrollBar.qml
new file mode 100644
index 0000000..2c1ec8a
--- /dev/null
+++ b/demos/declarative/flickr/common/ScrollBar.qml
@@ -0,0 +1,40 @@
+import Qt 4.6
+
+Item {
+ id: container
+
+ property var flickableArea
+
+ Rectangle {
+ radius: 5
+ color: "black"
+ opacity: 0.3
+ border.color: "white"
+ border.width: 2
+ x: 0
+ y: flickableArea.visibleArea.yPosition * container.height
+ width: parent.width
+ height: flickableArea.visibleArea.heightRatio * container.height
+ }
+ states: [
+ State {
+ name: "show"
+ when: flickableArea.moving
+ PropertyChanges {
+ target: container
+ opacity: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"
+ to: "*"
+ NumberAnimation {
+ target: container
+ matchProperties: "opacity"
+ duration: 400
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/common/Slider.qml b/demos/declarative/flickr/common/Slider.qml
new file mode 100644
index 0000000..fa1645c
--- /dev/null
+++ b/demos/declarative/flickr/common/Slider.qml
@@ -0,0 +1,36 @@
+import Qt 4.6
+
+Item {
+ id: slider; width: 400; height: 16
+
+ // value is read/write.
+ property real value
+ onValueChanged: { handle.x = 2 + (value - minimum) * slider.xMax / (maximum - minimum); }
+ property real maximum: 1
+ property real minimum: 1
+ property int xMax: slider.width - handle.width - 4
+
+ Rectangle {
+ anchors.fill: parent
+ border.color: "white"; border.width: 0; radius: 8
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#66343434" }
+ GradientStop { position: 1.0; color: "#66000000" }
+ }
+ }
+
+ Rectangle {
+ id: handle; smooth: true
+ x: slider.width / 2 - handle.width / 2; y: 2; width: 30; height: slider.height-4; radius: 6
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightgray" }
+ GradientStop { position: 1.0; color: "gray" }
+ }
+
+ MouseRegion {
+ anchors.fill: parent; drag.target: parent
+ drag.axis: "XAxis"; drag.minimumX: 2; drag.maximumX: slider.xMax+2
+ onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; }
+ }
+ }
+}
diff --git a/demos/declarative/flickr/common/Star.qml b/demos/declarative/flickr/common/Star.qml
new file mode 100644
index 0000000..c5abcca
--- /dev/null
+++ b/demos/declarative/flickr/common/Star.qml
@@ -0,0 +1,45 @@
+import Qt 4.6
+
+Item {
+ id: container
+ width: 24
+ height: 24
+
+ property int rating
+ property bool on
+ signal clicked
+
+ Image {
+ id: starImage
+ source: "pics/ghns_star.png"
+ x: 6
+ y: 7
+ opacity: 0.4
+ scale: 0.5
+ }
+ MouseRegion {
+ anchors.fill: container
+ onClicked: { container.clicked() }
+ }
+ states: [
+ State {
+ name: "on"
+ when: container.on == true
+ PropertyChanges {
+ target: starImage
+ opacity: 1
+ scale: 1
+ x: 1
+ y: 0
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation {
+ matchProperties: "opacity,scale,x,y"
+ easing: "easeOutBounce"
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/common/pics/background.png b/demos/declarative/flickr/common/pics/background.png
new file mode 100644
index 0000000..5b37072
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/background.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/button-pressed.png b/demos/declarative/flickr/common/pics/button-pressed.png
new file mode 100644
index 0000000..e434d32
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/button-pressed.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/button-pressed.sci b/demos/declarative/flickr/common/pics/button-pressed.sci
new file mode 100644
index 0000000..b8db272
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/button-pressed.sci
@@ -0,0 +1,5 @@
+border.left: 8
+border.top: 4
+border.bottom: 4
+border.right: 8
+source: button.png
diff --git a/demos/declarative/flickr/common/pics/button.png b/demos/declarative/flickr/common/pics/button.png
new file mode 100644
index 0000000..56a63ce
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/button.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/button.sci b/demos/declarative/flickr/common/pics/button.sci
new file mode 100644
index 0000000..b8db272
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/button.sci
@@ -0,0 +1,5 @@
+border.left: 8
+border.top: 4
+border.bottom: 4
+border.right: 8
+source: button.png
diff --git a/demos/declarative/flickr/common/pics/ghns_star.png b/demos/declarative/flickr/common/pics/ghns_star.png
new file mode 100644
index 0000000..4ad43cc
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/ghns_star.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/loading.png b/demos/declarative/flickr/common/pics/loading.png
new file mode 100644
index 0000000..47a1589
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/loading.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/reflection.png b/demos/declarative/flickr/common/pics/reflection.png
new file mode 100644
index 0000000..c143a48
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/reflection.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/shadow-bottom.png b/demos/declarative/flickr/common/pics/shadow-bottom.png
new file mode 100644
index 0000000..523f6e7
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/shadow-bottom.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/shadow-corner.png b/demos/declarative/flickr/common/pics/shadow-corner.png
new file mode 100644
index 0000000..ef8c856
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/shadow-corner.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/shadow-right-screen.png b/demos/declarative/flickr/common/pics/shadow-right-screen.png
new file mode 100644
index 0000000..9856c4f
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/shadow-right-screen.png
Binary files differ
diff --git a/demos/declarative/flickr/common/pics/shadow-right.png b/demos/declarative/flickr/common/pics/shadow-right.png
new file mode 100644
index 0000000..f534a35
--- /dev/null
+++ b/demos/declarative/flickr/common/pics/shadow-right.png
Binary files differ
diff --git a/demos/declarative/flickr/common/qmldir b/demos/declarative/flickr/common/qmldir
new file mode 100644
index 0000000..0c94f60
--- /dev/null
+++ b/demos/declarative/flickr/common/qmldir
@@ -0,0 +1,10 @@
+ImageDetails 0.0 ImageDetails.qml
+LikeOMeter 0.0 LikeOMeter.qml
+Loading 0.0 Loading.qml
+MediaButton 0.0 MediaButton.qml
+MediaLineEdit 0.0 MediaLineEdit.qml
+Progress 0.0 Progress.qml
+RssModel 0.0 RssModel.qml
+ScrollBar 0.0 ScrollBar.qml
+Slider 0.0 Slider.qml
+Star 0.0 Star.qml
diff --git a/demos/declarative/flickr/flickr-desktop.qml b/demos/declarative/flickr/flickr-desktop.qml
new file mode 100644
index 0000000..4e3b6cb
--- /dev/null
+++ b/demos/declarative/flickr/flickr-desktop.qml
@@ -0,0 +1,194 @@
+import Qt 4.6
+
+import "common"
+
+Item {
+ id: mainWindow; width: 800; height: 450
+
+ property bool showPathView : false
+
+ resources: [
+ Component {
+ id: photoDelegate
+ Item {
+ id: wrapper; width: 85; height: 85
+ scale: wrapper.PathView.scale ? wrapper.PathView.scale : 1
+ z: wrapper.PathView.z ? wrapper.PathView.z : 0
+
+ transform: Rotation {
+ id: itemRotation; origin.x: wrapper.width/2; origin.y: wrapper.height/2
+ axis.y: 1; axis.z: 0
+ angle: wrapper.PathView.angle ? wrapper.PathView.angle : 0
+ }
+
+ Connection {
+ sender: imageDetails; signal: "closed()"
+ script: {
+ if (wrapper.state == 'Details') {
+ wrapper.state = '';
+ imageDetails.photoUrl = "";
+ }
+ }
+ }
+
+ Script {
+ function photoClicked() {
+ imageDetails.photoTitle = title;
+ imageDetails.photoDescription = description;
+ imageDetails.photoTags = tags;
+ imageDetails.photoWidth = photoWidth;
+ imageDetails.photoHeight = photoHeight;
+ imageDetails.photoType = photoType;
+ imageDetails.photoAuthor = photoAuthor;
+ imageDetails.photoDate = photoDate;
+ imageDetails.photoUrl = url;
+ imageDetails.rating = 0;
+ wrapper.state = "Details";
+ }
+ }
+
+ Rectangle {
+ id: whiteRect; anchors.fill: parent; color: "white"; radius: 5
+
+ Loading { x: 26; y: 26; visible: thumb.status!=1 }
+ Image { id: thumb; source: imagePath; x: 5; y: 5 }
+
+ Item {
+ id: shadows
+ Image { source: "common/pics/shadow-right.png"; x: whiteRect.width; height: whiteRect.height }
+ Image { source: "common/pics/shadow-bottom.png"; y: whiteRect.height; width: whiteRect.width }
+ Image { id: corner; source: "common/pics/shadow-corner.png"; x: whiteRect.width; y: whiteRect.height }
+ }
+ }
+
+ MouseRegion { anchors.fill: wrapper; onClicked: { photoClicked() } }
+
+ states: [
+ State {
+ name: "Details"
+ PropertyChanges { target: imageDetails; z: 2 }
+ ParentChange { target: wrapper; parent: imageDetails.frontContainer }
+ PropertyChanges { target: wrapper; x: 45; y: 35; scale: 1; z: 1000 }
+ PropertyChanges { target: itemRotation; angle: 0 }
+ PropertyChanges { target: shadows; opacity: 0 }
+ PropertyChanges { target: imageDetails; y: 20 }
+ PropertyChanges { target: photoGridView; y: -480 }
+ PropertyChanges { target: photoPathView; y: -480 }
+ PropertyChanges { target: viewModeButton; opacity: 0 }
+ PropertyChanges { target: tagsEdit; opacity: 0 }
+ PropertyChanges { target: fetchButton; opacity: 0 }
+ PropertyChanges { target: categoryText; y: "-50" }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"; to: "Details"
+ SequentialAnimation {
+ ParentAction { }
+ NumberAnimation { matchProperties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" }
+ }
+ },
+ Transition {
+ from: "Details"; to: "*"
+ SequentialAnimation {
+ ParentAction { }
+ NumberAnimation { matchProperties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" }
+ PropertyAction { matchTargets: wrapper; matchProperties: "z" }
+ }
+ }
+ ]
+
+ }
+ }
+ ]
+
+ Item {
+ id: background
+
+ anchors.fill: parent
+
+ Image { source: "common/pics/background.png"; anchors.fill: parent }
+ RssModel { id: rssModel; tags : tagsEdit.text }
+ Loading { anchors.centerIn: parent; visible: rssModel.status == 2 }
+
+ GridView {
+ id: photoGridView; model: rssModel; delegate: photoDelegate; cacheBuffer: 100
+ cellWidth: 105; cellHeight: 105; x:32; y: 80; width: 800; height: 330; z: 1
+ }
+
+ PathView {
+ id: photoPathView; model: rssModel; delegate: photoDelegate
+ y: -380; width: 800; height: 330; pathItemCount: 10; z: 1
+ path: Path {
+ startX: -50; startY: 40;
+
+ PathAttribute { name: "scale"; value: 1 }
+ PathAttribute { name: "angle"; value: -45 }
+
+ PathCubic {
+ x: 400; y: 220
+ control1X: 140; control1Y: 40
+ control2X: 210; control2Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 1.2 }
+ PathAttribute { name: "z"; value: 1 }
+ PathAttribute { name: "angle"; value: 0 }
+
+ PathCubic {
+ x: 850; y: 40
+ control2X: 660; control2Y: 40
+ control1X: 590; control1Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 1 }
+ PathAttribute { name: "angle"; value: 45 }
+ }
+
+ }
+
+ ImageDetails { id: imageDetails; width: 750; x: 25; y: 500; height: 410 }
+
+ MediaButton {
+ id: viewModeButton; x: 680; y: 410; text: "View Mode"
+ onClicked: { if (mainWindow.showPathView == true) mainWindow.showPathView = false; else mainWindow.showPathView = true }
+ }
+
+ MediaButton {
+ id: fetchButton
+ text: "Update"
+ anchors.right: viewModeButton.left; anchors.rightMargin: 5
+ anchors.top: viewModeButton.top
+ onClicked: { rssModel.reload(); }
+ }
+
+ MediaLineEdit {
+ id: tagsEdit;
+ label: "Tags"
+ anchors.right: fetchButton.left; anchors.rightMargin: 5
+ anchors.top: viewModeButton.top
+ }
+
+ states: State {
+ name: "PathView"
+ when: mainWindow.showPathView == true
+ PropertyChanges { target: photoPathView; y: 80 }
+ PropertyChanges { target: photoGridView; y: -380 }
+ }
+
+ transitions: [
+ Transition {
+ from: "*"; to: "*"
+ NumberAnimation { matchProperties: "y"; duration: 1000; easing: "easeOutBounce(amplitude:0.5)" }
+ }
+ ]
+ }
+
+ Text {
+ id: categoryText; anchors.horizontalCenter: parent.horizontalCenter; y: 15;
+ text: "Flickr - " +
+ (rssModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + rssModel.tags)
+ font.pointSize: 20; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+ }
+}
diff --git a/demos/declarative/flickr/flickr-mobile-90.qml b/demos/declarative/flickr/flickr-mobile-90.qml
new file mode 100644
index 0000000..259ff10
--- /dev/null
+++ b/demos/declarative/flickr/flickr-mobile-90.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+Item {
+ width: 480; height: 320
+
+ Loader {
+ y: 320; rotation: -90
+ source: "flickr-mobile.qml"
+ }
+}
diff --git a/demos/declarative/flickr/flickr-mobile.qml b/demos/declarative/flickr/flickr-mobile.qml
new file mode 100644
index 0000000..583f992
--- /dev/null
+++ b/demos/declarative/flickr/flickr-mobile.qml
@@ -0,0 +1,82 @@
+import Qt 4.6
+import "common" as Common
+import "mobile" as Mobile
+
+Item {
+ id: screen; width: 320; height: 480
+ property bool inListView : false
+
+ Rectangle {
+ id: background
+ anchors.fill: parent; color: "#343434";
+
+ Image { source: "mobile/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 0.3 }
+
+ Common.RssModel { id: rssModel }
+ Common.Loading { anchors.centerIn: parent; visible: rssModel.status == 2 }
+
+ Item {
+ id: views
+ x: 2; width: parent.width - 4
+ anchors.top: titleBar.bottom; anchors.bottom: toolBar.top
+
+ Mobile.GridDelegate { id: gridDelegate }
+ GridView {
+ id: photoGridView; model: rssModel; delegate: gridDelegate; cacheBuffer: 100
+ cellWidth: 79; cellHeight: 79; width: parent.width; height: parent.height - 1; z: 6
+ }
+
+ Mobile.ListDelegate { id: listDelegate }
+ ListView {
+ id: photoListView; model: rssModel; delegate: listDelegate; z: 6
+ width: parent.width; height: parent.height; x: -(parent.width * 1.5); cacheBuffer: 100;
+ }
+ states: State {
+ name: "ListView"; when: screen.inListView == true
+ PropertyChanges { target: photoListView; x: 0 }
+ PropertyChanges { target: photoGridView; x: -(parent.width * 1.5) }
+ }
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "x"; duration: 500; easing: "easeInOutQuad" }
+ }
+ }
+
+ Mobile.ImageDetails { id: imageDetails; width: parent.width; anchors.left: views.right; height: parent.height; z:1 }
+ Mobile.TitleBar { id: titleBar; z: 5; width: parent.width; height: 40; opacity: 0.9 }
+
+ Mobile.ToolBar {
+ id: toolBar; z: 5
+ height: 40; anchors.bottom: parent.bottom; width: parent.width; opacity: 0.9
+ button1Label: "Update"; button2Label: "View mode"
+ onButton1Clicked: rssModel.reload()
+ onButton2Clicked: if (screen.inListView == true) screen.inListView = false; else screen.inListView = true
+ }
+
+ Connection {
+ sender: imageDetails; signal: "closed()"
+ script: {
+ if (background.state == "DetailedView") {
+ background.state = '';
+ imageDetails.photoUrl = "";
+ }
+ }
+ }
+
+ states: State {
+ name: "DetailedView"
+ PropertyChanges { target: views; x: -parent.width }
+ PropertyChanges { target: toolBar; button1Label: "More..." }
+ PropertyChanges {
+ target: toolBar
+ onButton1Clicked: if (imageDetails.state=='') imageDetails.state='Back'; else imageDetails.state=''
+ }
+ PropertyChanges { target: toolBar; button2Label: "Back" }
+ PropertyChanges { target: toolBar; onButton2Clicked: imageDetails.closed() }
+ }
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "x"; duration: 500; easing: "easeInOutQuad" }
+ }
+ }
+}
diff --git a/demos/declarative/flickr/mobile/Button.qml b/demos/declarative/flickr/mobile/Button.qml
new file mode 100644
index 0000000..770330c
--- /dev/null
+++ b/demos/declarative/flickr/mobile/Button.qml
@@ -0,0 +1,38 @@
+import Qt 4.6
+
+Item {
+ id: container
+
+ signal clicked
+
+ property string text
+
+ BorderImage {
+ id: buttonImage
+ source: "images/toolbutton.sci"
+ width: container.width; height: container.height
+ }
+ BorderImage {
+ id: pressed
+ opacity: 0
+ source: "images/toolbutton.sci"
+ width: container.width; height: container.height
+ }
+ MouseRegion {
+ id: mouseRegion
+ anchors.fill: buttonImage
+ onClicked: { container.clicked(); }
+ }
+ Text {
+ color: "white"
+ anchors.centerIn: buttonImage; font.bold: true
+ text: container.text; style: Text.Raised; styleColor: "black"
+ }
+ states: [
+ State {
+ name: "Pressed"
+ when: mouseRegion.pressed == true
+ PropertyChanges { target: pressed; opacity: 1 }
+ }
+ ]
+}
diff --git a/demos/declarative/flickr/mobile/GridDelegate.qml b/demos/declarative/flickr/mobile/GridDelegate.qml
new file mode 100644
index 0000000..3a42507
--- /dev/null
+++ b/demos/declarative/flickr/mobile/GridDelegate.qml
@@ -0,0 +1,72 @@
+ import Qt 4.6
+
+ Component {
+ id: photoDelegate
+ Item {
+ id: wrapper; width: 79; height: 79
+
+ Script {
+ function photoClicked() {
+ imageDetails.photoTitle = title;
+ imageDetails.photoTags = tags;
+ imageDetails.photoWidth = photoWidth;
+ imageDetails.photoHeight = photoHeight;
+ imageDetails.photoType = photoType;
+ imageDetails.photoAuthor = photoAuthor;
+ imageDetails.photoDate = photoDate;
+ imageDetails.photoUrl = url;
+ imageDetails.rating = 0;
+ scaleMe.state = "Details";
+ }
+ }
+
+ Item {
+ anchors.centerIn: parent
+ scale: 0.0
+ scale: Behavior { NumberAnimation { easing: "easeInOutQuad"} }
+ id: scaleMe
+
+ Rectangle { height: 79; width: 79; id: blackRect; anchors.centerIn: parent; color: "black"; smooth: true }
+ Rectangle {
+ id: whiteRect; width: 77; height: 77; anchors.centerIn: parent; color: "#dddddd"; smooth: true
+ Image { id: thumb; source: imagePath; x: 1; y: 1; smooth: true}
+ Image { source: "images/gloss.png" }
+ }
+
+ Connection {
+ sender: toolBar; signal: "button2Clicked()"
+ script: if (scaleMe.state == 'Details' ) scaleMe.state = 'Show';
+ }
+
+ states: [
+ State {
+ name: "Show"; when: thumb.status == 1
+ PropertyChanges { target: scaleMe; scale: 1 }
+ },
+ State {
+ name: "Details"
+ PropertyChanges { target: scaleMe; scale: 1 }
+ ParentChange { target: wrapper; parent: imageDetails.frontContainer }
+ PropertyChanges { target: wrapper; x: 20; y: 60; z: 1000 }
+ PropertyChanges { target: background; state: "DetailedView" }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "Show"; to: "Details"
+ ParentAction { }
+ NumberAnimation { matchProperties: "x,y"; duration: 500; easing: "easeInOutQuad" }
+ },
+ Transition {
+ from: "Details"; to: "Show"
+ SequentialAnimation {
+ ParentAction { }
+ NumberAnimation { matchProperties: "x,y"; duration: 500; easing: "easeInOutQuad" }
+ PropertyAction { matchTargets: wrapper; matchProperties: "z" }
+ }
+ }
+ ]
+ }
+ MouseRegion { anchors.fill: wrapper; onClicked: { photoClicked() } }
+ }
+ }
diff --git a/demos/declarative/flickr/mobile/ImageDetails.qml b/demos/declarative/flickr/mobile/ImageDetails.qml
new file mode 100644
index 0000000..9116428
--- /dev/null
+++ b/demos/declarative/flickr/mobile/ImageDetails.qml
@@ -0,0 +1,124 @@
+import Qt 4.6
+import "../common" as Common
+
+Flipable {
+ id: container
+
+ property var frontContainer: containerFront
+ property string photoTitle: ""
+ property string photoTags: ""
+ property int photoWidth
+ property int photoHeight
+ property string photoType
+ property string photoAuthor
+ property string photoDate
+ property string photoUrl
+ property int rating: 2
+ property var prevScale: 1.0
+
+ signal closed
+
+ transform: Rotation {
+ id: itemRotation
+ origin.x: container.width / 2;
+ axis.y: 1; axis.z: 0
+ }
+
+ front: Item {
+ id: containerFront; anchors.fill: container
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"; opacity: 0.4
+ }
+
+ Column {
+ spacing: 10
+ anchors {
+ left: parent.left; leftMargin: 20
+ right: parent.right; rightMargin: 20
+ top: parent.top; topMargin: 180
+ }
+ Text { font.bold: true; color: "white"; elide: Text.ElideRight; text: container.photoTitle }
+ Text { color: "white"; elide: Text.ElideRight; text: "<b>Size:</b> " + container.photoWidth + 'x' + container.photoHeight }
+ Text { color: "white"; elide: Text.ElideRight; text: "<b>Type:</b> " + container.photoType }
+ Text { color: "white"; elide: Text.ElideRight; text: "<b>Author:</b> " + container.photoAuthor }
+ Text { color: "white"; elide: Text.ElideRight; text: "<b>Published:</b> " + container.photoDate }
+ Text { color: "white"; elide: Text.ElideRight; text: container.photoTags == "" ? "" : "<b>Tags:</b> " }
+ Text { color: "white"; elide: Text.ElideRight; elide: Text.ElideRight; text: container.photoTags }
+ }
+ }
+
+ back: Item {
+ anchors.fill: container
+
+ Rectangle { anchors.fill: parent; color: "black"; opacity: 0.4 }
+
+ Common.Progress { anchors.centerIn: parent; width: 200; height: 18; progress: bigImage.progress; visible: bigImage.status!=1 }
+ Flickable {
+ id: flickable; anchors.fill: parent; clip: true
+ viewportWidth: imageContainer.width; viewportHeight: imageContainer.height
+
+ Item {
+ id: imageContainer
+ width: Math.max(bigImage.width * bigImage.scale, flickable.width);
+ height: Math.max(bigImage.height * bigImage.scale, flickable.height);
+
+ Image {
+ id: bigImage; source: container.photoUrl; scale: slider.value
+ // Center image if it is smaller than the flickable area.
+ x: imageContainer.width > width*scale ? (imageContainer.width - width*scale) / 2 : 0
+ y: imageContainer.height > height*scale ? (imageContainer.height - height*scale) / 2 : 0
+ smooth: !flickable.moving
+ onStatusChanged : {
+ // Default scale shows the entire image.
+ if (status == 1 && width != 0) {
+ slider.minimum = Math.min(flickable.width / width, flickable.height / height);
+ prevScale = Math.min(slider.minimum, 1);
+ slider.value = prevScale;
+ }
+ }
+ }
+ }
+ }
+
+ Text {
+ text: "Image Unavailable"
+ visible: bigImage.status == 'Error'
+ anchors.centerIn: parent; color: "white"; font.bold: true
+ }
+
+ Common.Slider {
+ id: slider; visible: { bigImage.status == 1 && maximum > minimum }
+ anchors {
+ bottom: parent.bottom; bottomMargin: 65
+ left: parent.left; leftMargin: 25
+ right: parent.right; rightMargin: 25
+ }
+ onValueChanged: {
+ if (bigImage.width * value > flickable.width) {
+ var xoff = (flickable.width/2 + flickable.viewportX) * value / prevScale;
+ flickable.viewportX = xoff - flickable.width/2;
+ }
+ if (bigImage.height * value > flickable.height) {
+ var yoff = (flickable.height/2 + flickable.viewportY) * value / prevScale;
+ flickable.viewportY = yoff - flickable.height/2;
+ }
+ prevScale = value;
+ }
+ }
+ }
+
+ states: State {
+ name: "Back"
+ PropertyChanges { target: itemRotation; angle: 180 }
+ }
+
+ transitions: Transition {
+ SequentialAnimation {
+ PropertyAction { target: bigImage; property: "smooth"; value: false }
+ NumberAnimation { easing: "easeInOutQuad"; matchProperties: "angle"; duration: 500 }
+ PropertyAction { target: bigImage; property: "smooth"; value: !flickable.moving }
+ }
+ }
+}
diff --git a/demos/declarative/flickr/mobile/ListDelegate.qml b/demos/declarative/flickr/mobile/ListDelegate.qml
new file mode 100644
index 0000000..75c4572
--- /dev/null
+++ b/demos/declarative/flickr/mobile/ListDelegate.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+Component {
+ Item {
+ id: wrapper; width: wrapper.ListView.view.width; height: 86
+ Item {
+ id: moveMe
+ Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+ Rectangle {
+ x: 6; y: 4; width: 77; height: 77; color: "white"; smooth: true
+
+ Image { source: imagePath; x: 1; y: 1 }
+ Image { source: "images/gloss.png" }
+ }
+ Column {
+ x: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2
+ Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" }
+ Text { text: photoAuthor; color: "white"; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+ Text { text: photoDate; color: "white"; width: parent.width; elide: Text.ElideRight; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+ }
+ }
+ }
+}
diff --git a/demos/declarative/flickr/mobile/TitleBar.qml b/demos/declarative/flickr/mobile/TitleBar.qml
new file mode 100644
index 0000000..0341585
--- /dev/null
+++ b/demos/declarative/flickr/mobile/TitleBar.qml
@@ -0,0 +1,76 @@
+import Qt 4.6
+
+Item {
+ id: titleBar
+ property string untaggedString: "Uploads from everyone"
+ property string taggedString: "Recent uploads tagged "
+
+ BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+
+ Item {
+ id: container
+ width: (parent.width * 2) - 55 ; height: parent.height
+
+ Script {
+ function accept() {
+ titleBar.state = ""
+ background.state = ""
+ rssModel.tags = editor.text
+ }
+ }
+
+ Text {
+ id: categoryText
+ anchors {
+ left: parent.left; right: tagButton.left; leftMargin: 10; rightMargin: 10
+ verticalCenter: parent.verticalCenter
+ }
+ elide: Text.ElideLeft
+ text: (rssModel.tags=="" ? untaggedString : taggedString + rssModel.tags)
+ font.bold: true; color: "White"; style: Text.Raised; styleColor: "Black"
+ }
+
+ Button {
+ id: tagButton; x: titleBar.width - 50; width: 45; height: 32; text: "..."
+ onClicked: if (titleBar.state == "Tags") accept(); else titleBar.state = "Tags"
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Item {
+ id: lineEdit
+ y: 4; height: parent.height - 9
+ anchors { left: tagButton.right; leftMargin: 5; right: parent.right; rightMargin: 5 }
+
+ BorderImage { source: "images/lineedit.sci"; anchors.fill: parent }
+
+ TextInput {
+ id: editor
+ anchors {
+ left: parent.left; right: parent.right; leftMargin: 10; rightMargin: 10
+ verticalCenter: parent.verticalCenter
+ }
+ cursorVisible: true; font.bold: true
+ color: "#151515"; selectionColor: "Green"
+ }
+
+ Keys.forwardTo: [ (returnKey), (editor)]
+
+ Item {
+ id: returnKey
+ Keys.onReturnPressed: accept()
+ Keys.onEscapePressed: titleBar.state = ""
+ }
+ }
+ }
+
+ states: State {
+ name: "Tags"
+ PropertyChanges { target: container; x: -tagButton.x + 5 }
+ PropertyChanges { target: tagButton; text: "OK" }
+ PropertyChanges { target: lineEdit; focus: true }
+ }
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "x"; easing: "easeInOutQuad" }
+ }
+}
diff --git a/demos/declarative/flickr/mobile/ToolBar.qml b/demos/declarative/flickr/mobile/ToolBar.qml
new file mode 100644
index 0000000..f96c767
--- /dev/null
+++ b/demos/declarative/flickr/mobile/ToolBar.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+Item {
+ id: toolbar
+
+ property alias button1Label: button1.text
+ property alias button2Label: button2.text
+ signal button1Clicked
+ signal button2Clicked
+
+ BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+
+ Button {
+ id: button1
+ anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 140; height: 32
+ onClicked: toolbar.button1Clicked()
+ }
+
+ Button {
+ id: button2
+ anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 140; height: 32
+ onClicked: toolbar.button2Clicked()
+ }
+}
diff --git a/demos/declarative/flickr/mobile/images/gloss.png b/demos/declarative/flickr/mobile/images/gloss.png
new file mode 100644
index 0000000..5d370cd
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/gloss.png
Binary files differ
diff --git a/demos/declarative/flickr/mobile/images/lineedit.png b/demos/declarative/flickr/mobile/images/lineedit.png
new file mode 100644
index 0000000..2cc38dc
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/lineedit.png
Binary files differ
diff --git a/demos/declarative/flickr/mobile/images/lineedit.sci b/demos/declarative/flickr/mobile/images/lineedit.sci
new file mode 100644
index 0000000..054bff7
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/lineedit.sci
@@ -0,0 +1,5 @@
+border.left: 10
+border.top: 10
+border.bottom: 10
+border.right: 10
+source: lineedit.png
diff --git a/demos/declarative/flickr/mobile/images/stripes.png b/demos/declarative/flickr/mobile/images/stripes.png
new file mode 100644
index 0000000..9f36727
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/stripes.png
Binary files differ
diff --git a/demos/declarative/flickr/mobile/images/titlebar.png b/demos/declarative/flickr/mobile/images/titlebar.png
new file mode 100644
index 0000000..51c9008
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/titlebar.png
Binary files differ
diff --git a/demos/declarative/flickr/mobile/images/titlebar.sci b/demos/declarative/flickr/mobile/images/titlebar.sci
new file mode 100644
index 0000000..0418d94
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/titlebar.sci
@@ -0,0 +1,5 @@
+border.left: 10
+border.top: 12
+border.bottom: 12
+border.right: 10
+source: titlebar.png
diff --git a/demos/declarative/flickr/mobile/images/toolbutton.png b/demos/declarative/flickr/mobile/images/toolbutton.png
new file mode 100644
index 0000000..1131001
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/toolbutton.png
Binary files differ
diff --git a/demos/declarative/flickr/mobile/images/toolbutton.sci b/demos/declarative/flickr/mobile/images/toolbutton.sci
new file mode 100644
index 0000000..9e4f965
--- /dev/null
+++ b/demos/declarative/flickr/mobile/images/toolbutton.sci
@@ -0,0 +1,5 @@
+border.left: 15
+border.top: 4
+border.bottom: 4
+border.right: 15
+source: toolbutton.png
diff --git a/demos/declarative/minehunt/Description.qml b/demos/declarative/minehunt/Description.qml
new file mode 100644
index 0000000..440dd2e
--- /dev/null
+++ b/demos/declarative/minehunt/Description.qml
@@ -0,0 +1,34 @@
+import Qt 4.6
+
+Item {
+ id: page
+ height: myText.height + 20
+ property var text
+ MouseRegion {
+ anchors.fill: parent
+ drag.target: page
+ drag.axis: "XandYAxis"
+ drag.minimumX: 0
+ drag.maximumX: 1000
+ drag.minimumY: 0
+ drag.maximumY: 1000
+ }
+ Rectangle {
+ radius: 10
+ anchors.fill: parent
+ color: "lightsteelblue"
+ }
+ Item {
+ x: 10
+ y: 10
+ width: parent.width - 20
+ height: parent.height - 20
+ Text {
+ id: myText
+ text: page.text
+ width: parent.width
+ clip: true
+ wrap: true
+ }
+ }
+}
diff --git a/demos/declarative/minehunt/Explosion.qml b/demos/declarative/minehunt/Explosion.qml
new file mode 100644
index 0000000..e337c46
--- /dev/null
+++ b/demos/declarative/minehunt/Explosion.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+Item {
+ property bool explode : false
+
+ Particles {
+ id: particles
+ width: 40
+ height: 40
+ lifeSpan: 1000
+ lifeSpanDeviation: 0
+ source: "pics/star.png"
+ count: 0
+ angle: 270
+ angleDeviation: 360
+ velocity: 100
+ velocityDeviation: 20
+ z: 100
+ opacity: 1
+ }
+ states: [ State { name: "exploding"; when: explode == true
+ StateChangeScript {script: particles.burst(200); }
+ }
+ ]
+
+}
diff --git a/demos/declarative/minehunt/main.cpp b/demos/declarative/minehunt/main.cpp
new file mode 100644
index 0000000..c756e66
--- /dev/null
+++ b/demos/declarative/minehunt/main.cpp
@@ -0,0 +1,350 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qml.h"
+#include <qmlgraphicsitem.h>
+#include <qmlview.h>
+
+#include <QWidget>
+#include <QApplication>
+#include <QFile>
+#include <QTime>
+#include <QTimer>
+#include <QVBoxLayout>
+#include <QFileInfo>
+
+QString fileName = "minehunt.qml";
+
+class Tile : public QObject
+{
+ Q_OBJECT
+public:
+ Tile() : _hasFlag(false), _hasMine(false), _hint(-1), _flipped(false) {}
+
+ Q_PROPERTY(bool hasFlag READ hasFlag WRITE setHasFlag NOTIFY hasFlagChanged);
+ bool hasFlag() const { return _hasFlag; }
+
+ Q_PROPERTY(bool hasMine READ hasMine NOTIFY hasMineChanged);
+ bool hasMine() const { return _hasMine; }
+
+ Q_PROPERTY(int hint READ hint NOTIFY hintChanged);
+ int hint() const { return _hint; }
+
+ Q_PROPERTY(bool flipped READ flipped NOTIFY flippedChanged());
+ bool flipped() const { return _flipped; }
+
+ void setHasFlag(bool flag) {if(flag==_hasFlag) return; _hasFlag = flag; emit hasFlagChanged();}
+ void setHasMine(bool mine) {if(mine==_hasMine) return; _hasMine = mine; emit hasMineChanged();}
+ void setHint(int hint) { if(hint == _hint) return; _hint = hint; emit hintChanged(); }
+ void flip() { if (_flipped) return; _flipped = true; emit flippedChanged(); }
+ void unflip() { if(!_flipped) return; _flipped = false; emit flippedChanged(); }
+
+signals:
+ void flippedChanged();
+ void hasFlagChanged();
+ void hintChanged();
+ void hasMineChanged();
+
+private:
+ bool _hasFlag;
+ bool _hasMine;
+ int _hint;
+ bool _flipped;
+};
+
+QML_DECLARE_TYPE(Tile);
+QML_DEFINE_TYPE(0,0,0,Tile,Tile);
+
+class MyWidget : public QWidget
+{
+Q_OBJECT
+public:
+ MyWidget(int = 370, int = 480, QWidget *parent=0, Qt::WindowFlags flags=0);
+ ~MyWidget();
+
+ Q_PROPERTY(QList<Tile *> *tiles READ tiles CONSTANT);
+ QList<Tile *> *tiles() { return &_tiles; }
+
+ Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged);
+ bool isPlaying() {return playing;}
+
+ Q_PROPERTY(bool hasWon READ hasWon NOTIFY hasWonChanged);
+ bool hasWon() {return won;}
+
+ Q_PROPERTY(int numMines READ numMines NOTIFY numMinesChanged);
+ int numMines() const{return nMines;}
+
+ Q_PROPERTY(int numFlags READ numFlags NOTIFY numFlagsChanged);
+ int numFlags() const{return nFlags;}
+
+public slots:
+ Q_INVOKABLE void flip(int row, int col);
+ Q_INVOKABLE void flag(int row, int col);
+ void setBoard();
+ void reset();
+
+signals:
+ void isPlayingChanged();
+ void hasWonChanged();
+ void numMinesChanged();
+ void numFlagsChanged();
+
+private:
+ bool onBoard( int r, int c ) const { return r >= 0 && r < numRows && c >= 0 && c < numCols; }
+ Tile *tile( int row, int col ) { return onBoard(row, col) ? _tiles[col+numRows*row] : 0; }
+ int getHint(int row, int col);
+ void setPlaying(bool b){if(b==playing) return; playing=b; emit isPlayingChanged();}
+
+ QmlView *canvas;
+
+ QList<Tile *> _tiles;
+ int numCols;
+ int numRows;
+ bool playing;
+ bool won;
+ int remaining;
+ int nMines;
+ int nFlags;
+};
+
+MyWidget::MyWidget(int width, int height, QWidget *parent, Qt::WindowFlags flags)
+: QWidget(parent, flags), canvas(0), numCols(9), numRows(9), playing(true), won(false)
+{
+ setObjectName("mainWidget");
+ srand(QTime(0,0,0).secsTo(QTime::currentTime()));
+
+ //initialize array
+ for(int ii = 0; ii < numRows * numCols; ++ii) {
+ _tiles << new Tile;
+ }
+
+ reset();
+
+ QVBoxLayout *vbox = new QVBoxLayout;
+ vbox->setMargin(0);
+ setLayout(vbox);
+
+ canvas = new QmlView(this);
+ canvas->setFixedSize(width, height);
+ vbox->addWidget(canvas);
+
+ QFile file(fileName);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, fileName);
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->addDefaultObject(this);
+ ctxt->setContextProperty("tiles", QVariant::fromValue<QList<Tile*>*>(&_tiles));//QTBUG-5675
+
+ canvas->execute();
+}
+
+MyWidget::~MyWidget()
+{
+}
+
+void MyWidget::setBoard()
+{
+ foreach(Tile* t, _tiles){
+ t->setHasMine(false);
+ t->setHint(-1);
+ }
+ //place mines
+ int mines = nMines;
+ remaining = numRows*numCols-mines;
+ while ( mines ) {
+ int col = int((double(rand()) / double(RAND_MAX)) * numCols);
+ int row = int((double(rand()) / double(RAND_MAX)) * numRows);
+
+ Tile* t = tile( row, col );
+
+ if (t && !t->hasMine()) {
+ t->setHasMine( true );
+ mines--;
+ }
+ }
+
+ //set hints
+ for (int r = 0; r < numRows; r++)
+ for (int c = 0; c < numCols; c++) {
+ Tile* t = tile(r, c);
+ if (t && !t->hasMine()) {
+ int hint = getHint(r,c);
+ t->setHint(hint);
+ }
+ }
+
+ setPlaying(true);
+}
+
+void MyWidget::reset()
+{
+ foreach(Tile* t, _tiles){
+ t->unflip();
+ t->setHasFlag(false);
+ }
+ nMines = 12;
+ nFlags = 0;
+ setPlaying(false);
+ QTimer::singleShot(600,this, SLOT(setBoard()));
+}
+
+int MyWidget::getHint(int row, int col)
+{
+ int hint = 0;
+ for (int c = col-1; c <= col+1; c++)
+ for (int r = row-1; r <= row+1; r++) {
+ Tile* t = tile(r, c);
+ if (t && t->hasMine())
+ hint++;
+ }
+ return hint;
+}
+
+void MyWidget::flip(int row, int col)
+{
+ if(!playing)
+ return;
+
+ Tile *t = tile(row, col);
+ if (!t || t->hasFlag())
+ return;
+
+ if(t->flipped()){
+ int flags = 0;
+ for (int c = col-1; c <= col+1; c++)
+ for (int r = row-1; r <= row+1; r++) {
+ Tile *nearT = tile(r, c);
+ if(!nearT || nearT == t)
+ continue;
+ if(nearT->hasFlag())
+ flags++;
+ }
+ if(!t->hint() || t->hint() != flags)
+ return;
+ for (int c = col-1; c <= col+1; c++)
+ for (int r = row-1; r <= row+1; r++) {
+ Tile *nearT = tile(r, c);
+ if (nearT && !nearT->flipped() && !nearT->hasFlag()) {
+ flip( r, c );
+ }
+ }
+ return;
+ }
+
+ t->flip();
+
+ if (t->hint() == 0) {
+ for (int c = col-1; c <= col+1; c++)
+ for (int r = row-1; r <= row+1; r++) {
+ Tile* t = tile(r, c);
+ if (t && !t->flipped()) {
+ flip( r, c );
+ }
+ }
+ }
+
+ if(t->hasMine()){
+ for (int r = 0; r < numRows; r++)//Flip all other mines
+ for (int c = 0; c < numCols; c++) {
+ Tile* t = tile(r, c);
+ if (t && t->hasMine()) {
+ flip(r, c);
+ }
+ }
+ won = false;
+ hasWonChanged();
+ setPlaying(false);
+ }
+
+ remaining--;
+ if(!remaining){
+ won = true;
+ hasWonChanged();
+ setPlaying(false);
+ }
+}
+
+void MyWidget::flag(int row, int col)
+{
+ Tile *t = tile(row, col);
+ if(!t)
+ return;
+
+ t->setHasFlag(!t->hasFlag());
+ nFlags += (t->hasFlag()?1:-1);
+ emit numFlagsChanged();
+}
+/////////////////////////////////////////////////////////
+
+int main(int argc, char ** argv)
+{
+ QApplication app(argc, argv);
+
+ bool frameless = false;
+
+ int width = 370;
+ int height = 480;
+
+ for (int i = 1; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-frameless") {
+ frameless = true;
+ } else if(arg == "-width" && i < (argc - 1)) {
+ ++i;
+ width = ::atoi(argv[i]);
+ } else if(arg == "-height" && i < (argc - 1)) {
+ ++i;
+ height = ::atoi(argv[i]);
+ } else if (arg[0] != '-') {
+ fileName = arg;
+ }
+ }
+
+ MyWidget wid(width, height, 0, frameless ? Qt::FramelessWindowHint : Qt::Widget);
+ wid.show();
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/demos/declarative/minehunt/minehunt.pro b/demos/declarative/minehunt/minehunt.pro
new file mode 100644
index 0000000..01791b1
--- /dev/null
+++ b/demos/declarative/minehunt/minehunt.pro
@@ -0,0 +1,9 @@
+SOURCES = main.cpp
+
+QT += script declarative
+contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl
+
+target.path = $$[QT_INSTALL_EXAMPLES]/declarative/minehunt
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS minehunt.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/declarative/minehunt
+INSTALLS += target sources
diff --git a/demos/declarative/minehunt/minehunt.qml b/demos/declarative/minehunt/minehunt.qml
new file mode 100644
index 0000000..ff00d83
--- /dev/null
+++ b/demos/declarative/minehunt/minehunt.qml
@@ -0,0 +1,196 @@
+import Qt 4.6
+
+Item {
+ id: field
+ width: 370
+ height: 480
+
+ property int clickx : 0
+ property int clicky : 0
+
+ resources: [
+ Component {
+ id: tile
+ Flipable {
+ id: flipable
+ width: 40
+ height: 40
+ property int angle: 0;
+ transform: Rotation {
+ origin.x: 20
+ origin.y: 20
+ axis.x: 1
+ axis.z: 0
+ angle: flipable.angle;
+ }
+ front: Image {
+ source: "pics/front.png"
+ width: 40
+ height: 40
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/flag.png"
+ opacity: modelData.hasFlag
+ opacity: Behavior {
+ NumberAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+ }
+ back: Image {
+ source: "pics/back.png"
+ width: 40
+ height: 40
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ text: modelData.hint
+ color: "white"
+ font.bold: true
+ opacity: !modelData.hasMine && modelData.hint > 0
+ }
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/bomb.png"
+ opacity: modelData.hasMine
+ }
+ Explosion {
+ id: expl
+ }
+ }
+ states: [
+ State {
+ name: "back"
+ when: modelData.flipped
+ PropertyChanges { target: flipable; angle: 180 }
+ }
+ ]
+ transitions: [
+ Transition {
+ SequentialAnimation {
+ PauseAnimation {
+ duration: {
+ var ret;
+ if(flipable.parent != null)
+ ret = Math.abs(flipable.parent.x-field.clickx)
+ + Math.abs(flipable.parent.y-field.clicky);
+ else
+ ret = 0;
+ if (ret > 0) {
+ if (modelData.hasMine && modelData.flipped) {
+ ret*3;
+ } else {
+ ret;
+ }
+ } else {
+ 0;
+ }
+ }
+ }
+ NumberAnimation {
+ easing: "easeInOutQuad"
+ matchProperties: "angle"
+ }
+ ScriptAction{
+ script: if(modelData.hasMine && modelData.flipped){expl.explode = true;}
+ }
+ }
+ }
+ ]
+ MouseRegion {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onPressed: {
+ field.clickx = flipable.parent.x;
+ field.clicky = flipable.parent.y;
+ var row = Math.floor(index/9);
+ var col = index - (Math.floor(index/9) * 9);
+ if (mouse.button==undefined || mouse.button==Qt.RightButton) {
+ flag(row,col);
+ } else {
+ flip(row,col);
+ }
+ }
+ }
+ }
+ }
+ ]
+ Image {
+ source: "pics/No-Ones-Laughing-3.jpg"
+ fillMode: Image.Tile
+ }
+ Description {
+ text: "Use the 'minehunt' executable to run this demo!"
+ width: 300
+ opacity: tiles?0:1
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ Repeater {
+ id: repeater
+ model: tiles
+ x: 1
+ y: 1
+ Component {
+ Loader {
+ sourceComponent: tile
+ x: (index - (Math.floor(index/9) * 9)) * 41
+ y: Math.floor(index/9) * 41
+ }
+ }
+ }
+ Row {
+ id: gamedata
+ // width: 370
+ // height: 100
+ y: 400
+ x: 20
+ spacing: 20
+ Column {
+ spacing: 2
+ width: childrenRect.width
+ Image {
+ // x: 100
+ // y: 20
+ source: "pics/bomb-color.png"
+ }
+ Text {
+ // x: 100
+ // y: 60
+ anchors.horizontalCenter: parent.horizontalCenter
+ color: "white"
+ text: numMines
+ }
+ }
+ Column {
+ spacing: 2
+ width: childrenRect.width
+ Image {
+ // x: 140
+ // y: 20
+ source: "pics/flag-color.png"
+ }
+ Text {
+ // x: 140
+ // y: 60
+ anchors.horizontalCenter: parent.horizontalCenter
+ color: "white"
+ text: numFlags
+ }
+ }
+ }
+ Image {
+ y: 390
+ anchors.right: field.right
+ anchors.rightMargin: 20
+ source: isPlaying ? 'pics/face-smile.png' : hasWon ? 'pics/face-smile-big.png': 'pics/face-sad.png'
+ MouseRegion {
+ anchors.fill: parent
+ onPressed: { reset() }
+ }
+ }
+}
diff --git a/demos/declarative/minehunt/pics/No-Ones-Laughing-3.jpg b/demos/declarative/minehunt/pics/No-Ones-Laughing-3.jpg
new file mode 100644
index 0000000..445567f
--- /dev/null
+++ b/demos/declarative/minehunt/pics/No-Ones-Laughing-3.jpg
Binary files differ
diff --git a/demos/declarative/minehunt/pics/back.png b/demos/declarative/minehunt/pics/back.png
new file mode 100644
index 0000000..f6b3f0b
--- /dev/null
+++ b/demos/declarative/minehunt/pics/back.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/bomb-color.png b/demos/declarative/minehunt/pics/bomb-color.png
new file mode 100644
index 0000000..61ad0a9
--- /dev/null
+++ b/demos/declarative/minehunt/pics/bomb-color.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/bomb.png b/demos/declarative/minehunt/pics/bomb.png
new file mode 100644
index 0000000..a992575
--- /dev/null
+++ b/demos/declarative/minehunt/pics/bomb.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/face-sad.png b/demos/declarative/minehunt/pics/face-sad.png
new file mode 100644
index 0000000..cf00aaf
--- /dev/null
+++ b/demos/declarative/minehunt/pics/face-sad.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/face-smile-big.png b/demos/declarative/minehunt/pics/face-smile-big.png
new file mode 100644
index 0000000..f9c2335
--- /dev/null
+++ b/demos/declarative/minehunt/pics/face-smile-big.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/face-smile.png b/demos/declarative/minehunt/pics/face-smile.png
new file mode 100644
index 0000000..3d66d72
--- /dev/null
+++ b/demos/declarative/minehunt/pics/face-smile.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/flag-color.png b/demos/declarative/minehunt/pics/flag-color.png
new file mode 100644
index 0000000..aadad0f
--- /dev/null
+++ b/demos/declarative/minehunt/pics/flag-color.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/flag.png b/demos/declarative/minehunt/pics/flag.png
new file mode 100644
index 0000000..39cde4d
--- /dev/null
+++ b/demos/declarative/minehunt/pics/flag.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/front.png b/demos/declarative/minehunt/pics/front.png
new file mode 100644
index 0000000..834331b
--- /dev/null
+++ b/demos/declarative/minehunt/pics/front.png
Binary files differ
diff --git a/demos/declarative/minehunt/pics/star.png b/demos/declarative/minehunt/pics/star.png
new file mode 100644
index 0000000..3772359
--- /dev/null
+++ b/demos/declarative/minehunt/pics/star.png
Binary files differ
diff --git a/demos/declarative/minehunt/test.qml b/demos/declarative/minehunt/test.qml
new file mode 100644
index 0000000..11ed182
--- /dev/null
+++ b/demos/declarative/minehunt/test.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+ Image {
+ source: "pics/front.png"
+ width: 40
+ height: 40
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/flag.png"
+ opacity: 1
+ }
+ }
diff --git a/demos/declarative/samegame/content/BoomBlock.qml b/demos/declarative/samegame/content/BoomBlock.qml
new file mode 100644
index 0000000..723e62a
--- /dev/null
+++ b/demos/declarative/samegame/content/BoomBlock.qml
@@ -0,0 +1,55 @@
+import Qt 4.6
+
+Item { id:block
+ property bool dying: false
+ property bool spawned: false
+ property int type: 0
+ property int targetX: 0
+ property int targetY: 0
+
+ x: SpringFollow { enabled: spawned; source: targetX; spring: 2; damping: 0.2 }
+ y: SpringFollow { source: targetY; spring: 2; damping: 0.2 }
+
+ Image { id: img
+ source: {
+ if(type == 0){
+ "pics/redStone.png";
+ } else if(type == 1) {
+ "pics/blueStone.png";
+ } else {
+ "pics/greenStone.png";
+ }
+ }
+ opacity: 0
+ opacity: Behavior { NumberAnimation { duration: 200 } }
+ anchors.fill: parent
+ }
+
+ Particles { id: particles
+ width:1; height:1; anchors.centerIn: parent;
+ emissionRate: 0;
+ lifeSpan: 700; lifeSpanDeviation: 600;
+ angle: 0; angleDeviation: 360;
+ velocity: 100; velocityDeviation:30;
+ source: {
+ if(type == 0){
+ "pics/redStar.png";
+ } else if (type == 1) {
+ "pics/blueStar.png";
+ } else {
+ "pics/greenStar.png";
+ }
+ }
+ }
+
+ states: [
+ State{ name: "AliveState"; when: spawned == true && dying == false
+ PropertyChanges { target: img; opacity: 1 }
+ },
+ State{ name: "DeathState"; when: dying == true
+ StateChangeScript { script: particles.burst(50); }
+ PropertyChanges { target: img; opacity: 0 }
+ StateChangeScript { script: block.destroy(1000); }
+ }
+ ]
+}
diff --git a/demos/declarative/samegame/content/Button.qml b/demos/declarative/samegame/content/Button.qml
new file mode 100644
index 0000000..63cd555
--- /dev/null
+++ b/demos/declarative/samegame/content/Button.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+
+ signal clicked
+ property string text: "Button"
+
+ color: activePalette.button; smooth: true
+ width: txtItem.width + 20; height: txtItem.height + 6
+ border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8;
+
+ gradient: Gradient {
+ GradientStop {
+ id: topGrad; position: 0.0
+ color: if (mr.pressed) { activePalette.dark } else { activePalette.light } }
+ GradientStop { position: 1.0; color: activePalette.button }
+ }
+
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: container.clicked() }
+
+ Text {
+ id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+ }
+}
diff --git a/demos/declarative/samegame/content/Dialog.qml b/demos/declarative/samegame/content/Dialog.qml
new file mode 100644
index 0000000..f9a281a
--- /dev/null
+++ b/demos/declarative/samegame/content/Dialog.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ function forceClose() {
+ page.closed();
+ page.opacity = 0;
+ }
+ function show(txt) {
+ myText.text = txt;
+ page.opacity = 1;
+ }
+ signal closed();
+ color: "white"; border.width: 1; width: myText.width + 20; height: myText.height + 40;
+ opacity: 0
+ opacity: Behavior {
+ NumberAnimation { duration: 1000 }
+ }
+ Text { id: myText; anchors.centerIn: parent; text: "Hello World!" }
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: forceClose(); }
+}
diff --git a/demos/declarative/samegame/content/pics/background.png b/demos/declarative/samegame/content/pics/background.png
new file mode 100644
index 0000000..3734a27
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/background.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/blueStar.png b/demos/declarative/samegame/content/pics/blueStar.png
new file mode 100644
index 0000000..ff9588f
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/blueStar.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/blueStone.png b/demos/declarative/samegame/content/pics/blueStone.png
new file mode 100644
index 0000000..20e43c7
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/blueStone.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/greenStar.png b/demos/declarative/samegame/content/pics/greenStar.png
new file mode 100644
index 0000000..cd06854
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/greenStar.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/greenStone.png b/demos/declarative/samegame/content/pics/greenStone.png
new file mode 100644
index 0000000..b568a19
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/greenStone.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/redStar.png b/demos/declarative/samegame/content/pics/redStar.png
new file mode 100644
index 0000000..0a4dffe
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/redStar.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/redStone.png b/demos/declarative/samegame/content/pics/redStone.png
new file mode 100644
index 0000000..36b09a2
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/redStone.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/star.png b/demos/declarative/samegame/content/pics/star.png
new file mode 100644
index 0000000..defbde5
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/star.png
Binary files differ
diff --git a/demos/declarative/samegame/content/pics/yellowStone.png b/demos/declarative/samegame/content/pics/yellowStone.png
new file mode 100644
index 0000000..b1ce762
--- /dev/null
+++ b/demos/declarative/samegame/content/pics/yellowStone.png
Binary files differ
diff --git a/demos/declarative/samegame/content/qmldir b/demos/declarative/samegame/content/qmldir
new file mode 100644
index 0000000..a8f8a98
--- /dev/null
+++ b/demos/declarative/samegame/content/qmldir
@@ -0,0 +1,3 @@
+BoomBlock 0.0 BoomBlock.qml
+Button 0.0 Button.qml
+Dialog 0.0 Dialog.qml
diff --git a/demos/declarative/samegame/content/samegame.js b/demos/declarative/samegame/content/samegame.js
new file mode 100755
index 0000000..0a42e88
--- /dev/null
+++ b/demos/declarative/samegame/content/samegame.js
@@ -0,0 +1,245 @@
+/* This script file handles the game logic */
+//Note that X/Y referred to here are in game coordinates
+var maxX = 10;//Nums are for gameCanvas.tileSize 40
+var maxY = 15;
+var maxIndex = maxX*maxY;
+var board = new Array(maxIndex);
+var tileSrc = "content/BoomBlock.qml";
+var scoresURL = "http://qtfx-nokia.trolltech.com.au/samegame/scores.php";
+var scoresURL = "";
+var timer;
+var component = createComponent(tileSrc);
+
+//Index function used instead of a 2D array
+function index(xIdx,yIdx) {
+ return xIdx + (yIdx * maxX);
+}
+
+function timeStr(msecs) {
+ var secs = Math.floor(msecs/1000);
+ var m = Math.floor(secs/60);
+ var ret = "" + m + "m " + (secs%60) + "s";
+ return ret;
+}
+
+function getTileSize()
+{
+ return tileSize;
+}
+
+function initBoard()
+{
+ for(var i = 0; i<maxIndex; i++){
+ //Delete old blocks
+ if(board[i] != null)
+ board[i].destroy();
+ }
+
+ //Calculate board size
+ maxX = Math.floor(gameCanvas.width/gameCanvas.tileSize);
+ maxY = Math.floor(gameCanvas.height/gameCanvas.tileSize);
+ maxIndex = maxY*maxX;
+
+ //Close dialogs
+ scoreName.forceClose();
+ dialog.forceClose();
+
+ var a = new Date();
+ //Initialize Board
+ board = new Array(maxIndex);
+ gameCanvas.score = 0;
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ for(var yIdx=0; yIdx<maxY; yIdx++){
+ board[index(xIdx,yIdx)] = null;
+ createBlock(xIdx,yIdx);
+ }
+ }
+ timer = new Date();
+
+ //print(timer.valueOf() - a.valueOf());
+}
+
+var fillFound;//Set after a floodFill call to the number of tiles found
+var floodBoard;//Set to 1 if the floodFill reaches off that node
+//NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope
+function handleClick(x,y)
+{
+ var xIdx = Math.floor(x/gameCanvas.tileSize);
+ var yIdx = Math.floor(y/gameCanvas.tileSize);
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return;
+ if(board[index(xIdx, yIdx)] == null)
+ return;
+ //If it's a valid tile, remove it and all connected (does nothing if it's not connected)
+ floodFill(xIdx,yIdx, -1);
+ if(fillFound <= 0)
+ return;
+ gameCanvas.score += (fillFound - 1) * (fillFound - 1);
+ shuffleDown();
+ victoryCheck();
+}
+
+function floodFill(xIdx,yIdx,type)
+{
+ if(board[index(xIdx, yIdx)] == null)
+ return;
+ var first = false;
+ if(type == -1){
+ first = true;
+ type = board[index(xIdx,yIdx)].type;
+
+ //Flood fill initialization
+ fillFound = 0;
+ floodBoard = new Array(maxIndex);
+ }
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return;
+ if(floodBoard[index(xIdx, yIdx)] == 1 || (!first && type != board[index(xIdx,yIdx)].type))
+ return;
+ floodBoard[index(xIdx, yIdx)] = 1;
+ floodFill(xIdx+1,yIdx,type);
+ floodFill(xIdx-1,yIdx,type);
+ floodFill(xIdx,yIdx+1,type);
+ floodFill(xIdx,yIdx-1,type);
+ if(first==true && fillFound == 0)
+ return;//Can't remove single tiles
+ board[index(xIdx,yIdx)].dying = true;
+ board[index(xIdx,yIdx)] = null;
+ fillFound += 1;
+}
+
+function shuffleDown()
+{
+ //Fall down
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ var fallDist = 0;
+ for(var yIdx=maxY-1; yIdx>=0; yIdx--){
+ if(board[index(xIdx,yIdx)] == null){
+ fallDist += 1;
+ }else{
+ if(fallDist > 0){
+ var obj = board[index(xIdx,yIdx)];
+ obj.targetY += fallDist * gameCanvas.tileSize;
+ board[index(xIdx,yIdx+fallDist)] = obj;
+ board[index(xIdx,yIdx)] = null;
+ }
+ }
+ }
+ }
+ //Fall to the left
+ fallDist = 0;
+ for(xIdx=0; xIdx<maxX; xIdx++){
+ if(board[index(xIdx, maxY - 1)] == null){
+ fallDist += 1;
+ }else{
+ if(fallDist > 0){
+ for(yIdx=0; yIdx<maxY; yIdx++){
+ obj = board[index(xIdx,yIdx)];
+ if(obj == null)
+ continue;
+ obj.targetX -= fallDist * gameCanvas.tileSize;
+ board[index(xIdx-fallDist,yIdx)] = obj;
+ board[index(xIdx,yIdx)] = null;
+ }
+ }
+ }
+ }
+}
+
+function victoryCheck()
+{
+ //awards bonuses for no tiles left
+ var deservesBonus = true;
+ for(var xIdx=maxX-1; xIdx>=0; xIdx--)
+ if(board[index(xIdx, maxY - 1)] != null)
+ deservesBonus = false;
+ if(deservesBonus)
+ gameCanvas.score += 500;
+ //Checks for game over
+ if(deservesBonus || !(floodMoveCheck(0,maxY-1, -1))){
+ timer = new Date() - timer;
+ scoreName.show("You won! Please enter your name: ");
+ //dialog.show("Game Over. Your score is " + gameCanvas.score);
+ }
+}
+
+//only floods up and right, to see if it can find adjacent same-typed tiles
+function floodMoveCheck(xIdx, yIdx, type)
+{
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return false;
+ if(board[index(xIdx, yIdx)] == null)
+ return false;
+ var myType = board[index(xIdx, yIdx)].type;
+ if(type == myType)
+ return true;
+ return floodMoveCheck(xIdx + 1, yIdx, myType) ||
+ floodMoveCheck(xIdx, yIdx - 1, board[index(xIdx,yIdx)].type);
+}
+
+function createBlock(xIdx,yIdx){
+ // Note that we don't wait for the component to become ready. This will
+ // only work if the block QML is a local file. Otherwise the component will
+ // not be ready immediately. There is a statusChanged signal on the
+ // component you could use if you want to wait to load remote files.
+ if(component.isReady){
+ var dynamicObject = component.createObject();
+ if(dynamicObject == null){
+ print("error creating block");
+ print(component.errorsString());
+ return false;
+ }
+ dynamicObject.type = Math.floor(Math.random() * 3);
+ dynamicObject.parent = gameCanvas;
+ dynamicObject.x = xIdx*gameCanvas.tileSize;
+ dynamicObject.targetX = xIdx*gameCanvas.tileSize;
+ dynamicObject.targetY = yIdx*gameCanvas.tileSize;
+ dynamicObject.width = gameCanvas.tileSize;
+ dynamicObject.height = gameCanvas.tileSize;
+ dynamicObject.spawned = true;
+ board[index(xIdx,yIdx)] = dynamicObject;
+ }else{//isError or isLoading
+ print("error loading block component");
+ print(component.errorsString());
+ return false;
+ }
+ return true;
+}
+
+function saveHighScore(name) {
+ if(scoresURL!="")
+ sendHighScore(name);
+ //OfflineStorage
+ var db = openDatabaseSync("SameGameScores", "1.0", "Local SameGame High Scores",100);
+ var dataStr = "INSERT INTO Scores VALUES(?, ?, ?, ?)";
+ var data = [name, gameCanvas.score, maxX+"x"+maxY ,Math.floor(timer/1000)];
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(name TEXT, score NUMBER, gridSize TEXT, time NUMBER)');
+ tx.executeSql(dataStr, data);
+
+ var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "12x17" ORDER BY score desc LIMIT 10');
+ var r = "\nHIGH SCORES for a standard sized grid\n\n"
+ for(var i = 0; i < rs.rows.length; i++){
+ r += (i+1)+". " + rs.rows.item(i).name +' got '
+ + rs.rows.item(i).score + ' points in '
+ + rs.rows.item(i).time + ' seconds.\n';
+ }
+ dialog.show(r);
+ }
+ );
+}
+
+function sendHighScore(name) {
+ var postman = new XMLHttpRequest()
+ var postData = "name="+name+"&score="+gameCanvas.score
+ +"&gridSize="+maxX+"x"+maxY +"&time="+Math.floor(timer/1000);
+ postman.open("POST", scoresURL, true);
+ postman.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ postman.onreadystatechange = function() {
+ if (postman.readyState == postman.DONE) {
+ dialog.show("Your score has been uploaded.");
+ }
+ }
+ postman.send(postData);
+}
diff --git a/demos/declarative/samegame/highscores/README b/demos/declarative/samegame/highscores/README
new file mode 100644
index 0000000..eaa00fa
--- /dev/null
+++ b/demos/declarative/samegame/highscores/README
@@ -0,0 +1 @@
+The SameGame example can interface with a simple PHP script to store XML high score data on a remote server. We do not have a publically accessible server available for this use, but if you have access to a PHP capable webserver you can copy the files (score_data.xml, score.php, score_style.xsl) to it and alter the highscore_server variable at the top of the samegame.js file to point to it.
diff --git a/demos/declarative/samegame/highscores/score_data.xml b/demos/declarative/samegame/highscores/score_data.xml
new file mode 100755
index 0000000..c3fd90d
--- /dev/null
+++ b/demos/declarative/samegame/highscores/score_data.xml
@@ -0,0 +1,2 @@
+<record><score>1000000</score><name>Alan the Tester</name><gridSize>0x0</gridSize><seconds>0</seconds></record>
+<record><score>6213</score><name>Alan</name><gridSize>12x17</gridSize><seconds>51</seconds></record>
diff --git a/demos/declarative/samegame/highscores/score_style.xsl b/demos/declarative/samegame/highscores/score_style.xsl
new file mode 100755
index 0000000..670354c
--- /dev/null
+++ b/demos/declarative/samegame/highscores/score_style.xsl
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="/">
+ <html>
+ <head><title>SameGame High Scores</title></head>
+ <body>
+ <h2>SameGame High Scores</h2>
+ <table border="1">
+ <tr bgcolor="lightsteelblue">
+ <th>Name</th>
+ <th>Score</th>
+ <th>Grid Size</th>
+ <th>Time, s</th>
+ </tr>
+ <xsl:for-each select="records/record">
+ <xsl:sort select="score" data-type="number" order="descending"/>
+ <tr>
+ <td><xsl:value-of select="name"/></td>
+ <td><xsl:value-of select="score"/></td>
+ <td><xsl:value-of select="gridSize"/></td>
+ <td><xsl:value-of select="seconds"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/demos/declarative/samegame/highscores/scores.php b/demos/declarative/samegame/highscores/scores.php
new file mode 100755
index 0000000..3cceb2d
--- /dev/null
+++ b/demos/declarative/samegame/highscores/scores.php
@@ -0,0 +1,34 @@
+<?php
+ $score = $_POST["score"];
+ echo "<html>";
+ echo "<head><title>SameGame High Scores</title></head><body>";
+ if($score > 0){#Sending in a new high score
+ $name = $_POST["name"];
+ $grid = $_POST["gridSize"];
+ $time = $_POST["time"];
+ if($name == "")
+ $name = "Anonymous";
+ //if($grid != "10x10"){
+ //Need a standard, so as to reject others?
+ //}
+ $file = fopen("score_data.xml", "a"); #It's XML. Happy?
+ $ret = fwrite($file, "<record><score>". $score . "</score><name>"
+ . $name . "</name><gridSize>" . $grid . "</gridSize><seconds>"
+ . $time . "</seconds></record>\n");
+ echo "Your score has been recorded. Thanks for playing!";
+ if($ret == False)
+ echo "<br/> There was an error though, so don't expect to see that score again.";
+ }else{#Read high score list
+ #Now uses XSLT to display. So just print the file. With XML cruft added.
+ #Note that firefox at least won't apply the XSLT on a php file. So redirecting
+ $file = fopen("scores.xml", "w");
+ $ret = fwrite($file, '<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n"
+ . '<?xml-stylesheet type="text/xsl" href="score_style.xsl"?>' . "\n"
+ . "<records>\n" . file_get_contents("score_data.xml") . "</records>\n");
+ if($ret == False)
+ echo "There was an internal error. Sorry.";
+ else
+ echo '<script type="text/javascript">window.location.replace("scores.xml")</script>';
+ }
+ echo "</body></html>";
+?>
diff --git a/demos/declarative/samegame/samegame.qml b/demos/declarative/samegame/samegame.qml
new file mode 100644
index 0000000..626c76b
--- /dev/null
+++ b/demos/declarative/samegame/samegame.qml
@@ -0,0 +1,85 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ id: screen
+ width: 490; height: 720
+
+ SystemPalette { id: activePalette }
+
+ Item {
+ width: parent.width; anchors.top: parent.top; anchors.bottom: toolBar.top
+
+ Image {
+ id: background
+ anchors.fill: parent; source: "content/pics/background.png"
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ }
+
+ Item {
+ id: gameCanvas
+ property int score: 0
+ property int tileSize: 40
+
+ Script { source: "content/samegame.js" }
+
+ z: 20; anchors.centerIn: parent
+ width: parent.width - (parent.width % getTileSize());
+ height: parent.height - (parent.height % getTileSize());
+
+ MouseRegion {
+ id: gameMR
+ anchors.fill: parent; onClicked: handleClick(mouse.x,mouse.y);
+ }
+ }
+ }
+
+ Dialog { id: dialog; anchors.centerIn: parent; z: 21 }
+ Dialog {
+ id: scoreName; anchors.centerIn: parent; z: 22;
+ Text {
+ id: spacer
+ opacity: 0
+ text: " You won! Please enter your name:"
+ }
+ TextInput {
+ id: editor
+ onAccepted: {
+ if(scoreName.opacity==1&&editor.text!="")
+ saveHighScore(editor.text);
+ scoreName.forceClose();
+ }
+ anchors.verticalCenter: parent.verticalCenter
+ width: 72; focus: true
+ anchors.left: spacer.right
+ }
+ }
+
+ Rectangle {
+ id: toolBar
+ color: activePalette.window
+ height: 32; width: parent.width
+ anchors.bottom: screen.bottom
+
+ Button {
+ id: btnA; text: "New Game"; onClicked: {initBoard();}
+ anchors.left: parent.left; anchors.leftMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Button {
+ id: btnB; text: "Quit"; onClicked: {Qt.quit();}
+ anchors.left: btnA.right; anchors.leftMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Text {
+ id: score
+ text: "Score: " + gameCanvas.score; font.bold: true
+ anchors.right: parent.right; anchors.rightMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ color: activePalette.text
+ }
+ }
+}
diff --git a/demos/declarative/snake/content/Button.qml b/demos/declarative/snake/content/Button.qml
new file mode 100644
index 0000000..63cd555
--- /dev/null
+++ b/demos/declarative/snake/content/Button.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+
+ signal clicked
+ property string text: "Button"
+
+ color: activePalette.button; smooth: true
+ width: txtItem.width + 20; height: txtItem.height + 6
+ border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8;
+
+ gradient: Gradient {
+ GradientStop {
+ id: topGrad; position: 0.0
+ color: if (mr.pressed) { activePalette.dark } else { activePalette.light } }
+ GradientStop { position: 1.0; color: activePalette.button }
+ }
+
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: container.clicked() }
+
+ Text {
+ id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+ }
+}
diff --git a/demos/declarative/snake/content/Cookie.qml b/demos/declarative/snake/content/Cookie.qml
new file mode 100644
index 0000000..7f0aadf
--- /dev/null
+++ b/demos/declarative/snake/content/Cookie.qml
@@ -0,0 +1,48 @@
+import Qt 4.6
+
+Item {
+ id: root
+ property bool dying: false
+ property int row;
+ property int column;
+ x: margin + column * gridSize
+ y: margin + row * gridSize
+
+ width: gridSize
+ height: gridSize
+ property int value : 1;
+
+ Image {
+ id: img
+ anchors.fill: parent
+ source: "pics/cookie.png"
+ opacity: 0
+ opacity: Behavior { NumberAnimation { duration: 100 } }
+ Text {
+ font.bold: true
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: value
+ }
+ }
+
+
+ Particles { id: particles
+ width:1; height:1; anchors.centerIn: parent;
+ emissionRate: 0;
+ lifeSpan: 700; lifeSpanDeviation: 600;
+ angle: 0; angleDeviation: 360;
+ velocity: 100; velocityDeviation:30;
+ source: "pics/yellowStar.png";
+ }
+
+ states: [
+ State{ name: "AliveState"; when: dying == false
+ PropertyChanges { target: img; opacity: 1 }
+ },
+ State{ name: "DeathState"; when: dying == true
+ StateChangeScript { script: particles.burst(50); }
+ PropertyChanges { target: img; opacity: 0 }
+ }
+ ]
+}
diff --git a/demos/declarative/snake/content/HighScoreModel.qml b/demos/declarative/snake/content/HighScoreModel.qml
new file mode 100644
index 0000000..f585ce8
--- /dev/null
+++ b/demos/declarative/snake/content/HighScoreModel.qml
@@ -0,0 +1,100 @@
+import Qt 4.6
+
+// Models a high score table.
+//
+// Use this component like this:
+//
+// HighScoreModel {
+// id: highScores
+// game: "MyCoolGame"
+// }
+//
+// Then use either use the top-score properties:
+//
+// Text { text: "HI: " + highScores.topScore }
+//
+// or, use the model in a view:
+//
+// ListView {
+// model: highScore
+// delegate: Component {
+// ... player ... score ...
+// }
+// }
+//
+// Add new scores via:
+//
+// saveScore(newScore)
+//
+// or:
+//
+// savePlayerScore(playerName,newScore)
+//
+// The best maxScore scores added by this method will be retained in an SQL database,
+// and presented in the model and in the topScore/topPlayer properties.
+//
+
+ListModel {
+ id: model
+ property string game: ""
+ property int topScore: 0
+ property string topPlayer: ""
+ property int maxScores: 10
+
+ Script {
+ function db()
+ {
+ return openDatabaseSync("HighScoreModel", "1.0", "Generic High Score Functionality for QML", 1000000);
+ }
+ function ensureTables(tx)
+ {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS HighScores(game TEXT, score INT, player TEXT)', []);
+ }
+ }
+
+ function fillModel() {
+ db().transaction(
+ function(tx) {
+ ensureTables(tx);
+ var rs = tx.executeSql("SELECT score,player FROM HighScores WHERE game=? ORDER BY score DESC", [game]);
+ model.clear();
+ if (rs.rows.length > 0) {
+ topScore = rs.rows.item(0).score
+ topPlayer = rs.rows.item(0).player
+ for (var i=0; i<rs.rows.length; ++i) {
+ if (i < maxScores)
+ model.append(rs.rows.item(i))
+ }
+ if (rs.rows.length > maxScores)
+ tx.executeSql("DELETE FROM HighScores WHERE game=? AND score <= ?",
+ [rs.rows.item(maxScores).score]);
+ }
+ }
+ )
+ }
+
+ function savePlayerScore(player,score) {
+ db().transaction(
+ function(tx) {
+ ensureTables(tx);
+ tx.executeSql("INSERT INTO HighScores VALUES(?,?,?)", [game,score,player]);
+ fillModel();
+ }
+ )
+ }
+
+ function saveScore(score) {
+ savePlayerScore("player",score);
+ }
+
+ function clearScores() {
+ db().transaction(
+ function(tx) {
+ tx.executeSql("DELETE FROM HighScores WHERE game=?", [game]);
+ fillModel();
+ }
+ )
+ }
+
+ Component.onCompleted: { fillModel() }
+}
diff --git a/demos/declarative/snake/content/Link.qml b/demos/declarative/snake/content/Link.qml
new file mode 100644
index 0000000..1b3f7bf
--- /dev/null
+++ b/demos/declarative/snake/content/Link.qml
@@ -0,0 +1,75 @@
+import Qt 4.6
+
+Item { id:link
+ property bool dying: false
+ property bool spawned: false
+ property int type: 0
+ property int row: 0
+ property int column: 0
+ property int rotation;
+
+ width: 40;
+ height: 40
+
+ x: margin - 3 + gridSize * column
+ y: margin - 3 + gridSize * row
+ x: Behavior { NumberAnimation { duration: spawned ? heartbeatInterval : 0} }
+ y: Behavior { NumberAnimation { duration: spawned ? heartbeatInterval : 0 } }
+
+
+ Item {
+ id: img
+ anchors.fill: parent
+ Image {
+ source: {
+ if(type == 1) {
+ "pics/blueStone.png";
+ } else if (type == 2) {
+ "pics/head.png";
+ } else {
+ "pics/redStone.png";
+ }
+ }
+
+ transform: Rotation {
+ id: actualImageRotation
+ origin.x: width/2; origin.y: height/2;
+ angle: rotation * 90
+ angle: Behavior{ NumberAnimation { duration: spawned ? 200 : 0} }
+ }
+ }
+
+ Image {
+ source: "pics/stoneShadow.png"
+ }
+
+ opacity: 0
+ opacity: Behavior { NumberAnimation { duration: 200 } }
+ }
+
+
+ Particles { id: particles
+ width:1; height:1; anchors.centerIn: parent;
+ emissionRate: 0;
+ lifeSpan: 700; lifeSpanDeviation: 600;
+ angle: 0; angleDeviation: 360;
+ velocity: 100; velocityDeviation:30;
+ source: {
+ if(type == 1){
+ "pics/blueStar.png";
+ } else {
+ "pics/redStar.png";
+ }
+ }
+ }
+
+ states: [
+ State{ name: "AliveState"; when: spawned == true && dying == false
+ PropertyChanges { target: img; opacity: 1 }
+ },
+ State{ name: "DeathState"; when: dying == true
+ StateChangeScript { script: particles.burst(50); }
+ PropertyChanges { target: img; opacity: 0 }
+ }
+ ]
+}
diff --git a/demos/declarative/snake/content/Skull.qml b/demos/declarative/snake/content/Skull.qml
new file mode 100644
index 0000000..585e7d3
--- /dev/null
+++ b/demos/declarative/snake/content/Skull.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Image {
+ property bool spawned: false
+ property int row;
+ property int column;
+ property int verticalMovement;
+ property int horizontalMovement;
+
+ x: margin + column * gridSize + 2
+ y: margin + row * gridSize - 3
+ x: Behavior { NumberAnimation { duration: spawned ? halfbeatInterval : 0} }
+ y: Behavior { NumberAnimation { duration: spawned ? halfbeatInterval : 0 } }
+
+ opacity: spawned ? 1 : 0
+ opacity: Behavior { NumberAnimation { duration: 200 } }
+
+ source: "pics/skull.png"
+ width: 24
+ height: 40
+}
diff --git a/demos/declarative/snake/content/pics/README b/demos/declarative/snake/content/pics/README
new file mode 100644
index 0000000..0215132
--- /dev/null
+++ b/demos/declarative/snake/content/pics/README
@@ -0,0 +1 @@
+snake.jpg: This image is based on the picture "Eastern Green Mamba.jpg" from the free media databse Wikimedia Commons and is published under the terms of the GNU Free Documentation License. The original picture was taken by Danleo.
diff --git a/demos/declarative/snake/content/pics/background.png b/demos/declarative/snake/content/pics/background.png
new file mode 100644
index 0000000..72dffaa
--- /dev/null
+++ b/demos/declarative/snake/content/pics/background.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/blueStar.png b/demos/declarative/snake/content/pics/blueStar.png
new file mode 100644
index 0000000..ba7acab
--- /dev/null
+++ b/demos/declarative/snake/content/pics/blueStar.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/blueStone.png b/demos/declarative/snake/content/pics/blueStone.png
new file mode 100644
index 0000000..356affd
--- /dev/null
+++ b/demos/declarative/snake/content/pics/blueStone.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/cookie.png b/demos/declarative/snake/content/pics/cookie.png
new file mode 100644
index 0000000..aec2957
--- /dev/null
+++ b/demos/declarative/snake/content/pics/cookie.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/eyes.svg b/demos/declarative/snake/content/pics/eyes.svg
new file mode 100644
index 0000000..1078692
--- /dev/null
+++ b/demos/declarative/snake/content/pics/eyes.svg
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ width="40"
+ height="40"
+ version="1.0"
+ sodipodi:docname="eyes.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/ettrich/dev/research/qml-validate/snake/pics/eyes.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective9" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="838"
+ inkscape:window-width="907"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="12.35"
+ inkscape:cx="20"
+ inkscape:cy="20"
+ inkscape:window-x="117"
+ inkscape:window-y="45"
+ inkscape:current-layer="svg2" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path2384"
+ sodipodi:cx="18.056681"
+ sodipodi:cy="9.5141697"
+ sodipodi:rx="7.1255059"
+ sodipodi:ry="11.295547"
+ d="M 25.182187,9.5141697 A 7.1255059,11.295547 0 1 1 10.931175,9.5141697 A 7.1255059,11.295547 0 1 1 25.182187,9.5141697 z"
+ transform="matrix(1.0089865,0,0,0.5462656,-4.9233835,3.3301401)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path3158"
+ sodipodi:cx="18.056681"
+ sodipodi:cy="9.5141697"
+ sodipodi:rx="7.1255059"
+ sodipodi:ry="11.295547"
+ d="M 25.182187,9.5141697 A 7.1255059,11.295547 0 1 1 10.931175,9.5141697 A 7.1255059,11.295547 0 1 1 25.182187,9.5141697 z"
+ transform="matrix(1.0089865,0,0,0.5462656,9.6190931,3.3522563)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1"
+ id="path3182"
+ sodipodi:cx="16.275303"
+ sodipodi:cy="12.307693"
+ sodipodi:rx="2.2672064"
+ sodipodi:ry="3.4008098"
+ d="M 18.542509,12.307693 A 2.2672064,3.4008098 0 0 1 14.008446,12.367372"
+ sodipodi:start="0"
+ sodipodi:end="3.1240432"
+ transform="translate(11.65992,-9.740891)"
+ sodipodi:open="true" />
+ <rect
+ style="fill:#000000;fill-opacity:0"
+ id="rect2382"
+ width="40"
+ height="40"
+ x="0"
+ y="-7.1054274e-15"
+ inkscape:export-filename="/home/ettrich/dev/research/qml-validate/snake/pics/eyes.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1"
+ id="path2383"
+ sodipodi:cx="16.275303"
+ sodipodi:cy="12.307693"
+ sodipodi:rx="2.2672064"
+ sodipodi:ry="3.4008098"
+ d="M 18.542509,12.307693 A 2.2672064,3.4008098 0 0 1 14.008446,12.367372"
+ sodipodi:start="0"
+ sodipodi:end="3.1240432"
+ transform="translate(-3.3200119,-9.821862)"
+ sodipodi:open="true" />
+</svg>
diff --git a/demos/declarative/snake/content/pics/head.png b/demos/declarative/snake/content/pics/head.png
new file mode 100644
index 0000000..550e002
--- /dev/null
+++ b/demos/declarative/snake/content/pics/head.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/head.svg b/demos/declarative/snake/content/pics/head.svg
new file mode 100644
index 0000000..3bf0bd2
--- /dev/null
+++ b/demos/declarative/snake/content/pics/head.svg
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ width="40"
+ height="40"
+ version="1.0"
+ sodipodi:docname="head.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/ettrich/dev/research/qml-validate/snake/pics/head.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective9" />
+ <inkscape:perspective
+ id="perspective2444"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="838"
+ inkscape:window-width="907"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="12.35"
+ inkscape:cx="20"
+ inkscape:cy="20"
+ inkscape:window-x="117"
+ inkscape:window-y="45"
+ inkscape:current-layer="svg2" />
+ <image
+ y="0.21862352"
+ x="-0.048582077"
+ id="image2446"
+ height="40"
+ width="40"
+ sodipodi:absref="/home/ettrich/dev/research/qml-validate/snake/pics/redStone.png"
+ xlink:href="redStone.png" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path2384"
+ sodipodi:cx="18.056681"
+ sodipodi:cy="9.5141697"
+ sodipodi:rx="7.1255059"
+ sodipodi:ry="11.295547"
+ d="M 25.182187,9.5141697 A 7.1255059,11.295547 0 1 1 10.931175,9.5141697 A 7.1255059,11.295547 0 1 1 25.182187,9.5141697 z"
+ transform="matrix(1.0089865,0,0,0.5462656,-4.9233835,3.3301401)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path3158"
+ sodipodi:cx="18.056681"
+ sodipodi:cy="9.5141697"
+ sodipodi:rx="7.1255059"
+ sodipodi:ry="11.295547"
+ d="M 25.182187,9.5141697 A 7.1255059,11.295547 0 1 1 10.931175,9.5141697 A 7.1255059,11.295547 0 1 1 25.182187,9.5141697 z"
+ transform="matrix(1.0089865,0,0,0.5462656,9.6190931,3.3522563)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1"
+ id="path3182"
+ sodipodi:cx="16.275303"
+ sodipodi:cy="12.307693"
+ sodipodi:rx="2.2672064"
+ sodipodi:ry="3.4008098"
+ d="M 18.542509,12.307693 A 2.2672064,3.4008098 0 0 1 14.008446,12.367372"
+ sodipodi:start="0"
+ sodipodi:end="3.1240432"
+ transform="translate(11.65992,-9.740891)"
+ sodipodi:open="true" />
+ <rect
+ style="fill:#000000;fill-opacity:0"
+ id="rect2382"
+ width="40"
+ height="40"
+ x="0"
+ y="-7.1054274e-15"
+ inkscape:export-filename="/home/ettrich/dev/research/qml-validate/snake/pics/eyes.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1"
+ id="path2383"
+ sodipodi:cx="16.275303"
+ sodipodi:cy="12.307693"
+ sodipodi:rx="2.2672064"
+ sodipodi:ry="3.4008098"
+ d="M 18.542509,12.307693 A 2.2672064,3.4008098 0 0 1 14.008446,12.367372"
+ sodipodi:start="0"
+ sodipodi:end="3.1240432"
+ transform="translate(-3.3200119,-9.821862)"
+ sodipodi:open="true" />
+</svg>
diff --git a/demos/declarative/snake/content/pics/redStar.png b/demos/declarative/snake/content/pics/redStar.png
new file mode 100644
index 0000000..cd06854
--- /dev/null
+++ b/demos/declarative/snake/content/pics/redStar.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/redStone.png b/demos/declarative/snake/content/pics/redStone.png
new file mode 100644
index 0000000..9bb7fe4
--- /dev/null
+++ b/demos/declarative/snake/content/pics/redStone.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/skull.png b/demos/declarative/snake/content/pics/skull.png
new file mode 100644
index 0000000..6318616
--- /dev/null
+++ b/demos/declarative/snake/content/pics/skull.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/snake.jpg b/demos/declarative/snake/content/pics/snake.jpg
new file mode 100644
index 0000000..e91a784
--- /dev/null
+++ b/demos/declarative/snake/content/pics/snake.jpg
Binary files differ
diff --git a/demos/declarative/snake/content/pics/star.png b/demos/declarative/snake/content/pics/star.png
new file mode 100644
index 0000000..defbde5
--- /dev/null
+++ b/demos/declarative/snake/content/pics/star.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/stoneShadow.png b/demos/declarative/snake/content/pics/stoneShadow.png
new file mode 100644
index 0000000..1bd56af
--- /dev/null
+++ b/demos/declarative/snake/content/pics/stoneShadow.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/yellowStar.png b/demos/declarative/snake/content/pics/yellowStar.png
new file mode 100644
index 0000000..52fb9c4
--- /dev/null
+++ b/demos/declarative/snake/content/pics/yellowStar.png
Binary files differ
diff --git a/demos/declarative/snake/content/pics/yellowStone.png b/demos/declarative/snake/content/pics/yellowStone.png
new file mode 100644
index 0000000..c56124a
--- /dev/null
+++ b/demos/declarative/snake/content/pics/yellowStone.png
Binary files differ
diff --git a/demos/declarative/snake/content/snake.js b/demos/declarative/snake/content/snake.js
new file mode 100644
index 0000000..a65aebc
--- /dev/null
+++ b/demos/declarative/snake/content/snake.js
@@ -0,0 +1,308 @@
+
+var snake = new Array;
+var board = new Array;
+var links = new Array;
+var scheduledDirections = new Array;
+var numRows = 1;
+var numColumns = 1;
+var linkComponent = createComponent("content/Link.qml"); // XXX should resolve relative to script, not component
+var cookieComponent = createComponent("content/Cookie.qml");
+var cookie;
+var linksToGrow = 0;
+var linksToDie = 0;
+var waitForCookie = 0;
+var growType = 0;
+var skullMovementsBeforeDirectionChange = 0;
+
+
+function rand(n)
+{
+ return (Math.floor(Math.random() * n));
+}
+
+function scheduleDirection(dir)
+{
+ direction = dir;
+ if(scheduledDirections[scheduledDirections.length-1]!=direction)
+ scheduledDirections.push(direction);
+}
+
+function startNewGame()
+{
+ if (state == "starting")
+ return;
+
+ if (heartbeat.running) {
+ endGame();
+ startNewGameTimer.running = true;
+ return;
+ }
+ numRows = numRowsAvailable;
+ numColumns = numColumnsAvailable;
+ board = new Array(numRows * numColumns);
+ snake = new Array;
+ scheduledDirections = new Array;
+ growType = 0;
+
+ skull.z = numRows * numColumns + 1;
+
+ for (var i = 0; i < numRows * numColumns; ++i) {
+ if (i < links.length) {
+ var link = links[i];
+ link.spawned = false;
+ link.dying = false;
+ } else {
+ if(linkComponent.isReady == false){
+ if(linkComponent.isError == true)
+ print(linkComponent.errorString());
+ else
+ print("Still loading linkComponent");
+ continue;//TODO: Better error handling?
+ }
+ var link = linkComponent.createObject();
+ link.parent = playfield;
+ link.z = numRows * numColumns + 1 - i;
+ link.type = i == 0 ? 2 : 0;
+ link.spawned = false;
+ link.dying = false;
+ links.push(link);
+ }
+ }
+
+ head = links[0];
+ snake.push(head);
+ head.row = numRows/2 -1;
+ head.column = numColumns/2 -1;
+ head.spawned = true;
+
+ linksToGrow = 5;
+ linksToDie = 0;
+ waitForCookie = 5;
+ score = 0;
+ startHeartbeatTimer.running = true;
+ heartbeat.running = true;
+}
+
+function endGame()
+{
+ heartbeat.running = false;
+ for(var i in snake)
+ snake[i].dying = true;
+ if (cookie) {
+ cookie.dying = true;
+ cookie = 0;
+ }
+ lastScore = score;
+ highScores.saveScore(lastScore);
+}
+
+function move() {
+
+ if (!head)
+ return;
+
+ var dir = direction;
+
+ if (scheduledDirections.length) {
+ dir = scheduledDirections.shift();
+ }
+
+ if (state == "starting") {
+ var turn = (dir - headDirection);
+ head.rotation += turn == -3 ? 1 : (turn == 3 ? -1 : turn );
+ headDirection = dir;
+ return;
+ }
+
+ var row = head.row;
+ var column = head.column;
+
+ if (dir == 0) {
+ row = row - 1;
+ } else if (dir == 1) {
+ column = column + 1
+ } else if (dir == 2) {
+ row = row + 1;
+ } else if (dir == 3) {
+ column = column - 1;
+ }
+
+ //validate the new position
+ if (row < 0 || row >= numRows
+ || column < 0 || column >= numColumns
+ || (row == skull.row && column == skull.column)
+ || !isFree(row, column)) {
+ var turn = (dir - headDirection);
+ head.rotation += turn == -3 ? 1 : (turn == 3 ? -1 : turn );
+ headDirection = dir;
+ endGame();
+ return;
+ }
+
+ var newLink;
+ if (linksToGrow > 0) {
+ --linksToGrow;
+ newLink = links[snake.length];
+ newLink.spawned = false;
+ newLink.rotation = snake[snake.length-1].rotation;
+ newLink.type = growType;
+ newLink.dying = false;
+ snake.push(newLink);
+ } else {
+ var lastLink = snake[snake.length-1];
+ board[lastLink.row * numColumns + lastLink.column] = Undefined;
+ }
+
+ if (waitForCookie > 0) {
+ if (--waitForCookie == 0)
+ createCookie(cookie? (cookie.value+1) : 1);
+ }
+
+ for (var i = snake.length-1; i > 0; --i) {
+ snake[i].row = snake[i-1].row;
+ snake[i].column = snake[i-1].column;
+ snake[i].rotation = snake[i-1].rotation;
+ }
+
+ if (newLink) {
+ newLink.spawned = true;
+ }
+
+ // move the head
+ head.row = row;
+ head.column = column;
+ board[row * numColumns + column] = head;
+
+ var turn = (dir - headDirection);
+ head.rotation += turn == -3 ? 1 : (turn == 3 ? -1 : turn );
+ headDirection = dir;
+
+ var value = testCookie(row, column);
+ if (value > 0) {
+ linksToGrow += value;
+ score += value;
+ }
+}
+
+function isFree(row, column)
+{
+ return board[row * numColumns + column] == Undefined;
+}
+
+function isHead(row, column)
+{
+ return head.column == column && head.row == row;
+}
+
+function testCookie(row, column)
+{
+ if (cookie && !cookie.dying && cookie.row == row && cookie.column == column) {
+ var value = cookie.value;
+ waitForCookie = value;
+ growType = snake[snake.length-1].type == 1 ? 0 : 1;
+ cookie.dying = true;
+ cookie.z = numRows * numColumns + 2;
+ return value;
+ }
+ return 0;
+}
+
+function moveSkull()
+{
+
+ if (linksToDie > 0) {
+ --linksToDie;
+ var link = snake.pop();
+ link.dying = true;
+ board[link.row * numColumns + link.column] = Undefined;
+ if (score > 0)
+ --score;
+ if (snake.length == 0) {
+ endGame();
+ return;
+ }
+ }
+
+ var row = skull.row;
+ var column = skull.column;
+ if (isHead(row, column)) {
+ endGame();
+ return;
+ }
+ row += skull.verticalMovement;
+ column += skull.horizontalMovement;
+
+ var attempts = 4;
+
+ while (skullMovementsBeforeDirectionChange == 0 || row < 0 || row >= numRows
+ || column < 0 || column >= numColumns
+ || (!isFree(row, column) && !isHead(row, column))) {
+ var d = rand(8);
+ skull.verticalMovement = 0;
+ skull.horizontalMovement = 0;
+ skullMovementsBeforeDirectionChange = rand(20)+1;
+ if (d == 0) {
+ skull.verticalMovement = -1
+ } else if (d == 1) {
+ skull.horizontalMovement = -1;
+ } else if (d == 2) {
+ skull.verticalMovement = 1
+ } else if (d == 3){
+ skull.horizontalMovement = 1;
+ } else if (cookie) {
+ var rd = cookie.row - skull.row;
+ var rc = cookie.column - skull.column;
+ if (Math.abs(rd) > Math.abs(rc)) {
+ skull.verticalMovement = rd > 0 ? 1 : -1;
+ skullMovementsBeforeDirectionChange = Math.abs(rd);
+ } else {
+ skull.horizontalMovement= rc > 0 ? 1 : -1;
+ skullMovementsBeforeDirectionChange = Math.abs(rc);
+ }
+ }
+ row = skull.row + skull.verticalMovement;
+ column = skull.column + skull.horizontalMovement;
+ if (--attempts == 0)
+ return;
+ }
+
+ skull.row = row;
+ skull.column = column;
+ --skullMovementsBeforeDirectionChange;
+ var value = testCookie(row, column);
+ if (value > 0)
+ linksToDie += value/2;
+
+ if (isHead(row, column))
+ endGame();
+}
+
+function createCookie(value) {
+ if (numRows * numColumns - snake.length < 10)
+ return;
+
+ var column = rand(numColumns);
+ var row = rand(numRows);
+ while (!isFree(row, column)) {
+ column++;
+ if (column == numColumns) {
+ column = 0;
+ row++;
+ if (row == numRows)
+ row = 0;
+ }
+ }
+
+ if(cookieComponent.isReady == false){
+ if(cookieComponent.isError == true)
+ print(cookieComponent.errorString());
+ else
+ print("Still loading cookieComponent");
+ return;//TODO: Better error handling?
+ }
+ cookie = cookieComponent.createObject();
+ cookie.parent = head.parent;
+ cookie.value = value;
+ cookie.row = row;
+ cookie.column = column;
+}
diff --git a/demos/declarative/snake/snake.qml b/demos/declarative/snake/snake.qml
new file mode 100644
index 0000000..58827a7
--- /dev/null
+++ b/demos/declarative/snake/snake.qml
@@ -0,0 +1,190 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ id: screen;
+ SystemPalette { id: activePalette }
+ color: activePalette.window
+
+ Script { source: "content/snake.js" }
+
+ property int gridSize : 34
+ property int margin: 4
+ property int numRowsAvailable: Math.floor((height-32-2*margin)/gridSize)
+ property int numColumnsAvailable: Math.floor((width-2*margin)/gridSize)
+
+ property int lastScore : 0
+
+ property int score: 0;
+ property int heartbeatInterval: 200
+ property int halfbeatInterval: 160
+
+ width: 480
+ height: 750
+
+ property int direction
+ property int headDirection
+
+ property var head;
+
+ HighScoreModel {
+ id: highScores
+ game: "Snake"
+ }
+
+ Timer {
+ id: heartbeat;
+ interval: heartbeatInterval;
+ repeat: true
+ onTriggered: { move() }
+ }
+ Timer {
+ id: halfbeat;
+ interval: halfbeatInterval;
+ repeat: true
+ running: heartbeat.running
+ onTriggered: { moveSkull() }
+ }
+ Timer {
+ id: startNewGameTimer;
+ interval: 700;
+ onTriggered: {startNewGame(); }
+ }
+
+ Timer {
+ id: startHeartbeatTimer;
+ interval: 1000 ;
+ }
+
+
+ Image {
+ Image {
+ id: title
+ source: "content/pics/snake.jpg"
+ fillMode: "PreserveAspectCrop"
+ anchors.fill: parent
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ opacity: Behavior { NumberAnimation { duration: 500 } }
+
+ Text {
+ color: "white"
+ font.pointSize: 24
+ horizontalAlignment: "AlignHCenter"
+ text: "Last Score:\t" + lastScore + "\nHighscore:\t" + highScores.topScore;
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: gridSize
+ }
+ }
+
+ source: "content/pics/background.png"
+ fillMode: "PreserveAspectCrop"
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: toolbar.top
+
+ Rectangle {
+ id: playfield
+ border.width: 1
+ border.color: "white"
+ color: "transparent"
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: (screen.height - 32 - height)/2;
+ width: numColumnsAvailable * gridSize + 2*margin
+ height: numRowsAvailable * gridSize + 2*margin
+
+
+ Skull {
+ id: skull
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onPressed: {
+ if (!head || !heartbeat.running) {
+ startNewGame();
+ return;
+ }
+ if (direction == 0 || direction == 2)
+ scheduleDirection((mouseX > (head.x + head.width/2)) ? 1 : 3);
+ else
+ scheduleDirection((mouseY > (head.y + head.height/2)) ? 2 : 0);
+ }
+ }
+ }
+
+ }
+
+ Rectangle {
+ id: progressBar
+ opacity: 0
+ opacity: Behavior { NumberAnimation { duration: 200 } }
+ color: "transparent"
+ border.width: 2
+ border.color: "#221edd"
+ x: 50
+ y: 50
+ width: 200
+ height: 30
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: 40
+
+ Rectangle {
+ id: progressIndicator
+ color: "#221edd";
+ width: 0;
+ width: Behavior { NumberAnimation { duration: startHeartbeatTimer.running ? 1000 : 0}}
+ height: 30;
+ }
+ }
+
+ Rectangle {
+ id: toolbar
+ color: activePalette.window
+ height: 32; width: parent.width
+ anchors.bottom: screen.bottom
+
+ Button {
+ id: btnA; text: "New Game"; onClicked: {startNewGame();}
+ anchors.left: parent.left; anchors.leftMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Text {
+ color: activePalette.text
+ text: "Score: " + score; font.bold: true
+ anchors.right: parent.right; anchors.rightMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ focus: true
+ Keys.onSpacePressed: startNewGame();
+ Keys.onLeftPressed: if (state == "starting" || direction != 1) scheduleDirection(3);
+ Keys.onRightPressed: if (state == "starting" || direction != 3) scheduleDirection(1);
+ Keys.onUpPressed: if (state == "starting" || direction != 2) scheduleDirection(0);
+ Keys.onDownPressed: if (state == "starting" || direction != 0) scheduleDirection(2);
+
+ states: [
+ State {
+ name: "starting"
+ when: startHeartbeatTimer.running;
+ PropertyChanges {target: progressIndicator; width: 200}
+ PropertyChanges {target: title; opacity: 0}
+ PropertyChanges {target: progressBar; opacity: 1}
+ },
+ State {
+ name: "running"
+ when: heartbeat.running
+ PropertyChanges {target: progressIndicator; width: 200}
+ PropertyChanges {target: title; opacity: 0}
+ PropertyChanges {target: skull; row: 0; column: 0; }
+ PropertyChanges {target: skull; spawned: 1}
+ }
+ ]
+
+}
diff --git a/demos/declarative/twitter/content/AuthView.qml b/demos/declarative/twitter/content/AuthView.qml
new file mode 100644
index 0000000..bcf4646
--- /dev/null
+++ b/demos/declarative/twitter/content/AuthView.qml
@@ -0,0 +1,99 @@
+import Qt 4.6
+
+Item {
+ id: wrapper
+ Column {
+ anchors.centerIn: parent
+ spacing: 20
+ Column{
+ spacing: 4
+ Text {
+ text: "Screen name:"
+ font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+ horizontalAlignment: Qt.AlignRight
+ }
+ Item {
+ width: 220
+ height: 28
+ BorderImage { source: "images/lineedit.sci"; anchors.fill: parent }
+ TextInput{
+ id: nameIn
+ width: parent.width - 8
+ anchors.centerIn: parent
+ maximumLength:21
+ font.pixelSize: 16;
+ font.bold: true
+ color: "#151515"; selectionColor: "green"
+ KeyNavigation.down: passIn
+ focus: true
+ }
+ }
+ }
+ Column{
+ spacing: 4
+ Text {
+ text: "Password:"
+ font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+ horizontalAlignment: Qt.AlignRight
+ }
+ Item {
+ width: 220
+ height: 28
+ BorderImage { source: "images/lineedit.sci"; anchors.fill: parent }
+ TextInput{
+ id: passIn
+ width: parent.width - 8
+ anchors.centerIn: parent
+ maximumLength:21
+ echoMode: TextInput.Password
+ font.pixelSize: 16;
+ font.bold: true
+ color: "#151515"; selectionColor: "green"
+ KeyNavigation.down: login
+ KeyNavigation.up: nameIn
+ }
+ }
+ }
+ Row{
+ spacing: 10
+ Button {
+ width: 100
+ height: 32
+ id: login
+ keyUsing: true;
+ function doLogin(){
+ rssModel.authName=nameIn.text;
+ rssModel.authPass=passIn.text;
+ rssModel.tags='my timeline';
+ screen.focus = true;
+ }
+ text: "Log in"
+ KeyNavigation.right: guest
+ KeyNavigation.up: passIn
+ Keys.onReturnPressed: login.doLogin();
+ Keys.onSelectPressed: login.doLogin();
+ Keys.onSpacePressed: login.doLogin();
+ onClicked: login.doLogin();
+ }
+ Button {
+ width: 100
+ height: 32
+ id: guest
+ keyUsing: true;
+ function doGuest()
+ {
+ rssModel.authName='-';
+ screen.focus = true;
+ screen.setMode(true);
+ }
+ text: "Guest"
+ KeyNavigation.left: login
+ KeyNavigation.up: passIn
+ Keys.onReturnPressed: guest.doGuest();
+ Keys.onSelectPressed: guest.doGuest();
+ Keys.onSpacePressed: guest.doGuest();
+ onClicked: guest.doGuest();
+ }
+ }
+ }
+}
diff --git a/demos/declarative/twitter/content/Button.qml b/demos/declarative/twitter/content/Button.qml
new file mode 100644
index 0000000..09d471c
--- /dev/null
+++ b/demos/declarative/twitter/content/Button.qml
@@ -0,0 +1,49 @@
+import Qt 4.6
+
+Item {
+ id: container
+
+ signal clicked
+
+ property string text
+ property bool keyUsing: false
+
+ BorderImage {
+ id: buttonImage
+ source: "images/toolbutton.sci"
+ width: container.width; height: container.height
+ }
+ BorderImage {
+ id: pressed
+ opacity: 0
+ source: "images/toolbutton.sci"
+ width: container.width; height: container.height
+ }
+ MouseRegion {
+ id: mouseRegion
+ anchors.fill: buttonImage
+ onClicked: { container.clicked(); }
+ }
+ Text {
+ id: btnText
+ color: if(container.keyUsing){"#DDDDDD";} else {"#FFFFFF";}
+ anchors.centerIn: buttonImage; font.bold: true
+ text: container.text; style: Text.Raised; styleColor: "black"
+ font.pixelSize: 12
+ }
+ states: [
+ State {
+ name: "Pressed"
+ when: mouseRegion.pressed == true
+ PropertyChanges { target: pressed; opacity: 1 }
+ },
+ State {
+ name: "Focused"
+ when: container.focus == true
+ PropertyChanges { target: btnText; color: "#FFFFFF" }
+ }
+ ]
+ transitions: Transition {
+ ColorAnimation { target: btnText; }
+ }
+}
diff --git a/demos/declarative/twitter/content/FatDelegate.qml b/demos/declarative/twitter/content/FatDelegate.qml
new file mode 100644
index 0000000..2b9288b
--- /dev/null
+++ b/demos/declarative/twitter/content/FatDelegate.qml
@@ -0,0 +1,46 @@
+import Qt 4.6
+
+Component {
+ id: listDelegate
+ Item {
+ id: wrapper; width: wrapper.ListView.view.width; height: if(txt.height > 58){txt.height+8}else{58}//50+4+4
+ Script {
+ function handleLink(link){
+ if(link.slice(0,3) == 'app'){
+ setUser(link.slice(7));
+ screen.setMode(true);
+ }else if(link.slice(0,4) == 'http'){
+ Qt.openUrlExternally(link);
+ }
+ }
+ function addTags(str){
+ var ret = str.replace(/@[a-zA-Z0-9_]+/g, '<a href="app://$&">$&</a>');//click to jump to user?
+ var ret2 = ret.replace(/http:\/\/[^ \n\t]+/g, '<a href="$&">$&</a>');//surrounds http links with html link tags
+ return ret2;
+ }
+ }
+ Item {
+ id: moveMe; height: parent.height
+ Rectangle {
+ id: blackRect
+ color: "black"; opacity: wrapper.ListView.index % 2 ? 0.2 : 0.3; height: wrapper.height-2; width: wrapper.width; y: 1
+ }
+ Rectangle {
+ id: whiteRect; x: 6; width: 50; height: 50; color: "white"; smooth: true
+ anchors.verticalCenter: parent.verticalCenter
+
+ Loading { x: 1; y: 1; width: 48; height: 48; visible: realImage.status != 1 }
+ Image { id: realImage; source: userImage; x: 1; y: 1; width:48; height:48 }
+ }
+ Text { id:txt; y:4; x: 56
+ text: '<html><style type="text/css">a:link {color:"#aaccaa"}; a:visited {color:"#336633"}</style>'
+ + '<a href="app://@'+userScreenName+'"><b>'+userScreenName + "</b></a> from " +source
+ + "<br /><b>" + addTags(statusText) + "</b></html>";
+ textFormat: Qt.RichText
+ color: "white"; color: "#cccccc"; style: Text.Raised; styleColor: "black"; wrap: true
+ anchors.left: whiteRect.right; anchors.right: blackRect.right; anchors.leftMargin: 6; anchors.rightMargin: 6
+ onLinkActivated: handleLink(link)
+ }
+ }
+ }
+}
diff --git a/demos/declarative/twitter/content/HomeTitleBar.qml b/demos/declarative/twitter/content/HomeTitleBar.qml
new file mode 100644
index 0000000..c48befd
--- /dev/null
+++ b/demos/declarative/twitter/content/HomeTitleBar.qml
@@ -0,0 +1,121 @@
+import Qt 4.6
+
+Item {
+ id: titleBar
+
+ signal update()
+ onYChanged: state="" //When switching titlebars
+
+ BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+ Item {
+ id: container
+ width: (parent.width * 2) - 55 ; height: parent.height
+
+ Script {
+ function accept() {
+ if(rssModel.authName == '' || rssModel.authPass == '')
+ return false;//Can't login like that
+
+ var postData = "status=" + editor.text;
+ var postman = new XMLHttpRequest();
+ postman.open("POST", "http://twitter.com/statuses/update.xml", true, rssModel.authName, rssModel.authPass);
+ postman.onreadystatechange = function() {
+ if (postman.readyState == postman.DONE) {
+ titleBar.update();
+ }
+ }
+ postman.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ postman.send(postData);
+
+ editor.text = ""
+ titleBar.state = ""
+ }
+ }
+
+ Rectangle {
+ x: 6; width: 50; height: 50; color: "white"; smooth: true
+ anchors.verticalCenter: parent.verticalCenter
+
+ UserModel { user: rssModel.authName; id: userModel }
+ Component { id: imgDelegate;
+ Item {
+ Loading { width:48; height:48; visible: realImage.status != 1 }
+ Image { source: image; width:48; height:48; id: realImage }
+ }
+ }
+ ListView { model: userModel.model; x:1; y:1; delegate: imgDelegate }
+ }
+
+ Text {
+ id: categoryText
+ anchors.left: parent.left; anchors.right: tagButton.left
+ anchors.leftMargin: 58; anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideLeft
+ text: "Timeline for " + rssModel.authName
+ font.pixelSize: 12; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+ }
+
+ Button {
+ id: tagButton; x: titleBar.width - 90; width: 85; height: 32; text: "New Post..."
+ anchors.verticalCenter: parent.verticalCenter;
+ onClicked: if (titleBar.state == "Posting") accept(); else titleBar.state = "Posting"
+ }
+
+ Text {
+ id: charsLeftText; anchors.horizontalCenter: tagButton.horizontalCenter;
+ anchors.top: tagButton.bottom; anchors.topMargin: 2
+ text: {140 - editor.text.length;} visible: titleBar.state == "Posting"
+ font.pointSize: 10; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+ }
+ Item {
+ id: txtEdit;
+ anchors.left: tagButton.right; anchors.leftMargin: 5; y: 4
+ anchors.right: parent.right; anchors.rightMargin: 40; height: parent.height - 9
+ BorderImage { source: "images/lineedit.sci"; anchors.fill: parent }
+
+ Binding {//TODO: Can this be a function, which also resets the cursor? And flashes?
+ when: editor.text.length > 140
+ target: editor
+ property: "text"
+ value: editor.text.slice(0,140)
+ }
+ TextEdit {
+ id: editor
+ anchors.left: parent.left;
+ anchors.leftMargin: 8;
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 4;
+ cursorVisible: true; font.bold: true
+ width: parent.width - 12
+ height: parent.height - 8
+ font.pointSize: 10
+ wrap: true
+ color: "#151515"; selectionColor: "green"
+ }
+ Keys.forwardTo: [(returnKey), (editor)]
+ Item {
+ id: returnKey
+ Keys.onReturnPressed: accept()
+ Keys.onEscapePressed: titleBar.state = ""
+ }
+ }
+ }
+ states: [
+ State {
+ name: "Posting"
+ PropertyChanges { target: container; x: -tagButton.x + 5 }
+ PropertyChanges { target: titleBar; height: 80 }
+ PropertyChanges { target: tagButton; text: "OK" }
+ PropertyChanges { target: tagButton; width: 28 }
+ PropertyChanges { target: tagButton; height: 24 }
+ PropertyChanges { target: txtEdit; focus: true }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"; to: "*"
+ NumberAnimation { matchProperties: "x,y,width,height"; easing: "easeInOutQuad" }
+ }
+ ]
+}
diff --git a/demos/declarative/twitter/content/Loading.qml b/demos/declarative/twitter/content/Loading.qml
new file mode 100644
index 0000000..8b22e70
--- /dev/null
+++ b/demos/declarative/twitter/content/Loading.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Image {
+ id: loading; source: "images/loading.png"; transformOrigin: "Center"
+ rotation: NumberAnimation {
+ id: "RotationAnimation"; from: 0; to: 360; running: loading.visible == true; repeat: true; duration: 900
+ }
+}
diff --git a/demos/declarative/twitter/content/MultiTitleBar.qml b/demos/declarative/twitter/content/MultiTitleBar.qml
new file mode 100644
index 0000000..ef8a450
--- /dev/null
+++ b/demos/declarative/twitter/content/MultiTitleBar.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+Item {
+ height: homeBar.height
+ HomeTitleBar { id: homeBar; width: parent.width; height: 60;
+ onUpdate: rssModel.reload()
+ }
+ TitleBar { id: titleBar; width: parent.width; height: 60;
+ y: -80
+ untaggedString: "Latest tweets from everyone"
+ taggedString: "Latest tweets from "
+ }
+ states: [
+ State {
+ name: "search"; when: screen.userView
+ PropertyChanges { target: titleBar; y: 0 }
+ PropertyChanges { target: homeBar; y: -80 }
+ }
+ ]
+ transitions: [
+ Transition { NumberAnimation { matchProperties: "x,y"; duration: 500; easing: "easeInOutQuad" } }
+ ]
+}
+
diff --git a/demos/declarative/twitter/content/RssModel.qml b/demos/declarative/twitter/content/RssModel.qml
new file mode 100644
index 0000000..9d88bb7
--- /dev/null
+++ b/demos/declarative/twitter/content/RssModel.qml
@@ -0,0 +1,44 @@
+import Qt 4.6
+
+Item { id: wrapper
+ property var model: xmlModel
+ property string tags : ""
+ property string authName : ""
+ property string authPass : ""
+ property string mode : "everyone"
+ property int status: xmlModel.status
+ function reload() { xmlModel.reload(); }
+XmlListModel {
+ id: xmlModel
+
+ source:{
+ if (wrapper.authName == ""){
+ ""; //Avoid worthless calls to twitter servers
+ }else if(wrapper.mode == 'user'){
+ "https://"+ ((wrapper.authName!="" && wrapper.authPass!="")? (wrapper.authName+":"+wrapper.authPass+"@") : "" )+"twitter.com/statuses/user_timeline.xml?screen_name="+wrapper.tags;
+ }else if(wrapper.mode == 'self'){
+ "https://"+ ((wrapper.authName!="" && wrapper.authPass!="")? (wrapper.authName+":"+wrapper.authPass+"@") : "" )+"twitter.com/statuses/friends_timeline.xml";
+ }else{//everyone/public
+ "http://twitter.com/statuses/public_timeline.xml";
+ }
+ }
+ query: "/statuses/status"
+
+ XmlRole { name: "statusText"; query: "text/string()" }
+ XmlRole { name: "timestamp"; query: "created_at/string()" }
+ XmlRole { name: "source"; query: "source/string()" }
+ XmlRole { name: "userName"; query: "user/name/string()" }
+ XmlRole { name: "userScreenName"; query: "user/screen_name/string()" }
+ XmlRole { name: "userImage"; query: "user/profile_image_url/string()" }
+ XmlRole { name: "userLocation"; query: "user/location/string()" }
+ XmlRole { name: "userDescription"; query: "user/description/string()" }
+ XmlRole { name: "userFollowers"; query: "user/followers_count/string()" }
+ XmlRole { name: "userStatuses"; query: "user/statuses_count/string()" }
+ //TODO: Could also get the user's color scheme, timezone and a few other things
+}
+Binding {
+ property: "mode"
+ target: wrapper
+ value: {if(wrapper.tags==''){"everyone";}else if(wrapper.tags=='my timeline'){"self";}else{"user";}}
+}
+}
diff --git a/demos/declarative/twitter/content/TitleBar.qml b/demos/declarative/twitter/content/TitleBar.qml
new file mode 100644
index 0000000..28e7389
--- /dev/null
+++ b/demos/declarative/twitter/content/TitleBar.qml
@@ -0,0 +1,77 @@
+import Qt 4.6
+
+Item {
+ id: titleBar
+ property string untaggedString: "Uploads from everyone"
+ property string taggedString: "Recent uploads tagged "
+
+ BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+
+ Item {
+ id: container
+ width: (parent.width * 2) - 55 ; height: parent.height
+
+ Script {
+ function accept() {
+ titleBar.state = ""
+ background.state = ""
+ rssModel.tags = editor.text
+ }
+ }
+
+ Text {
+ id: categoryText
+ anchors {
+ left: parent.left; right: tagButton.left; leftMargin: 10; rightMargin: 10
+ verticalCenter: parent.verticalCenter
+ }
+ elide: Text.ElideLeft
+ text: (rssModel.tags=="" ? untaggedString : taggedString + rssModel.tags)
+ font.bold: true; color: "White"; style: Text.Raised; styleColor: "Black"
+ font.pixelSize: 12
+ }
+
+ Button {
+ id: tagButton; x: titleBar.width - 50; width: 45; height: 32; text: "..."
+ onClicked: if (titleBar.state == "Tags") accept(); else titleBar.state = "Tags"
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Item {
+ id: lineEdit
+ y: 4; height: parent.height - 9
+ anchors { left: tagButton.right; leftMargin: 5; right: parent.right; rightMargin: 5 }
+
+ BorderImage { source: "images/lineedit.sci"; anchors.fill: parent }
+
+ TextInput {
+ id: editor
+ anchors {
+ left: parent.left; right: parent.right; leftMargin: 10; rightMargin: 10
+ verticalCenter: parent.verticalCenter
+ }
+ cursorVisible: true; font.bold: true
+ color: "#151515"; selectionColor: "Green"
+ }
+
+ Keys.forwardTo: [ (returnKey), (editor)]
+
+ Item {
+ id: returnKey
+ Keys.onReturnPressed: accept()
+ Keys.onEscapePressed: titleBar.state = ""
+ }
+ }
+ }
+
+ states: State {
+ name: "Tags"
+ PropertyChanges { target: container; x: -tagButton.x + 5 }
+ PropertyChanges { target: tagButton; text: "OK" }
+ PropertyChanges { target: lineEdit; focus: true }
+ }
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "x"; easing: "easeInOutQuad" }
+ }
+}
diff --git a/demos/declarative/twitter/content/ToolBar.qml b/demos/declarative/twitter/content/ToolBar.qml
new file mode 100644
index 0000000..f96c767
--- /dev/null
+++ b/demos/declarative/twitter/content/ToolBar.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+Item {
+ id: toolbar
+
+ property alias button1Label: button1.text
+ property alias button2Label: button2.text
+ signal button1Clicked
+ signal button2Clicked
+
+ BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+
+ Button {
+ id: button1
+ anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 140; height: 32
+ onClicked: toolbar.button1Clicked()
+ }
+
+ Button {
+ id: button2
+ anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 140; height: 32
+ onClicked: toolbar.button2Clicked()
+ }
+}
diff --git a/demos/declarative/twitter/content/UserModel.qml b/demos/declarative/twitter/content/UserModel.qml
new file mode 100644
index 0000000..c146b84
--- /dev/null
+++ b/demos/declarative/twitter/content/UserModel.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+//This "model" gets the user information about the searched user. Mainly for the icon.
+//Copied from RssModel
+
+Item { id: wrapper
+ property var model: xmlModel
+ property string user : ""
+ property int status: xmlModel.status
+ function reload() { xmlModel.reload(); }
+XmlListModel {
+ id: xmlModel
+
+ source: {if(user!="") {"http://twitter.com/users/show.xml?screen_name="+user;}else{"";}}
+ query: "/user"
+
+ XmlRole { name: "name"; query: "name/string()" }
+ XmlRole { name: "screenName"; query: "screen_name/string()" }
+ XmlRole { name: "image"; query: "profile_image_url/string()" }
+ XmlRole { name: "location"; query: "location/string()" }
+ XmlRole { name: "description"; query: "description/string()" }
+ XmlRole { name: "followers"; query: "followers_count/string()" }
+ //XmlRole { name: "protected"; query: "protected/bool()" }
+ //TODO: Could also get the user's color scheme, timezone and a few other things
+}
+}
diff --git a/demos/declarative/twitter/content/images/gloss.png b/demos/declarative/twitter/content/images/gloss.png
new file mode 100644
index 0000000..5d370cd
--- /dev/null
+++ b/demos/declarative/twitter/content/images/gloss.png
Binary files differ
diff --git a/demos/declarative/twitter/content/images/lineedit.png b/demos/declarative/twitter/content/images/lineedit.png
new file mode 100644
index 0000000..2cc38dc
--- /dev/null
+++ b/demos/declarative/twitter/content/images/lineedit.png
Binary files differ
diff --git a/demos/declarative/twitter/content/images/lineedit.sci b/demos/declarative/twitter/content/images/lineedit.sci
new file mode 100644
index 0000000..054bff7
--- /dev/null
+++ b/demos/declarative/twitter/content/images/lineedit.sci
@@ -0,0 +1,5 @@
+border.left: 10
+border.top: 10
+border.bottom: 10
+border.right: 10
+source: lineedit.png
diff --git a/demos/declarative/twitter/content/images/loading.png b/demos/declarative/twitter/content/images/loading.png
new file mode 100644
index 0000000..47a1589
--- /dev/null
+++ b/demos/declarative/twitter/content/images/loading.png
Binary files differ
diff --git a/demos/declarative/twitter/content/images/stripes.png b/demos/declarative/twitter/content/images/stripes.png
new file mode 100644
index 0000000..9f36727
--- /dev/null
+++ b/demos/declarative/twitter/content/images/stripes.png
Binary files differ
diff --git a/demos/declarative/twitter/content/images/titlebar.png b/demos/declarative/twitter/content/images/titlebar.png
new file mode 100644
index 0000000..51c9008
--- /dev/null
+++ b/demos/declarative/twitter/content/images/titlebar.png
Binary files differ
diff --git a/demos/declarative/twitter/content/images/titlebar.sci b/demos/declarative/twitter/content/images/titlebar.sci
new file mode 100644
index 0000000..0418d94
--- /dev/null
+++ b/demos/declarative/twitter/content/images/titlebar.sci
@@ -0,0 +1,5 @@
+border.left: 10
+border.top: 12
+border.bottom: 12
+border.right: 10
+source: titlebar.png
diff --git a/demos/declarative/twitter/content/images/toolbutton.png b/demos/declarative/twitter/content/images/toolbutton.png
new file mode 100644
index 0000000..1131001
--- /dev/null
+++ b/demos/declarative/twitter/content/images/toolbutton.png
Binary files differ
diff --git a/demos/declarative/twitter/content/images/toolbutton.sci b/demos/declarative/twitter/content/images/toolbutton.sci
new file mode 100644
index 0000000..9e4f965
--- /dev/null
+++ b/demos/declarative/twitter/content/images/toolbutton.sci
@@ -0,0 +1,5 @@
+border.left: 15
+border.top: 4
+border.bottom: 4
+border.right: 15
+source: toolbutton.png
diff --git a/demos/declarative/twitter/twitter.qml b/demos/declarative/twitter/twitter.qml
new file mode 100644
index 0000000..bb7da9c
--- /dev/null
+++ b/demos/declarative/twitter/twitter.qml
@@ -0,0 +1,95 @@
+import Qt 4.6
+import "content" as Twitter
+
+Item {
+ id: screen; width: 320; height: 480
+ property bool userView : false
+ property var tmpStr
+ function setMode(m){
+ screen.userView = m;
+ if(m == false){
+ rssModel.tags='my timeline';
+ rssModel.reload();
+ toolBar.button2Label = "View others";
+ } else {
+ toolBar.button2Label = "Return home";
+ }
+ }
+ //Workaround for bug 260266
+ Timer{ interval: 1; running: false; repeat: false; onTriggered: reallySetUser(); id:hack }
+ Script {
+ function setUser(str){hack.running = true; tmpStr = str}
+ function reallySetUser(){rssModel.tags = tmpStr;}
+ }
+
+ //TODO: better way to return to the auth screen
+ Keys.onEscapePressed: rssModel.authName=''
+ Rectangle {
+ id: background
+ anchors.fill: parent; color: "#343434";
+
+ Image { source: "content/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 0.3 }
+
+ Twitter.RssModel { id: rssModel }
+ Twitter.Loading { anchors.centerIn: parent; visible: rssModel.status==XmlListModel.Loading && state!='unauthed'}
+ Text {
+ width: 180
+ text: "Could not access twitter using this screen name and password pair.";
+ color: "white"; color: "#cccccc"; style: Text.Raised; styleColor: "black"; wrap: true
+ visible: rssModel.status==XmlListModel.Error; anchors.centerIn: parent
+ }
+
+ Item {
+ id: views
+ x: 2; width: parent.width - 4
+ y:60 //Below the title bars
+ height: 380
+
+ Twitter.AuthView{
+ id: authView
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width; height: parent.height-60;
+ x: -(screen.width * 1.5)
+ }
+
+ Twitter.FatDelegate { id: fatDelegate }
+ ListView {
+ id: mainView; model: rssModel.model; delegate: fatDelegate;
+ width: parent.width; height: parent.height; x: 0; cacheBuffer: 100;
+ }
+ }
+
+ Twitter.MultiTitleBar { id: titleBar; width: parent.width }
+ Twitter.ToolBar { id: toolBar; height: 40;
+ //anchors.bottom: parent.bottom;
+ //TODO: Use anchor changes instead of hard coding
+ y: screen.height - 40
+ width: parent.width; opacity: 0.9
+ button1Label: "Update"
+ button2Label: "View others"
+ onButton1Clicked: rssModel.reload();
+ onButton2Clicked:
+ {
+ if(screen.userView == true){
+ screen.setMode(false);
+ }else{
+ rssModel.tags='';
+ screen.setMode(true);
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "unauthed"; when: rssModel.authName==""
+ PropertyChanges { target: authView; x: 0 }
+ PropertyChanges { target: mainView; x: -(parent.width * 1.5) }
+ PropertyChanges { target: titleBar; y: -80 }
+ PropertyChanges { target: toolBar; y: screen.height }
+ }
+ ]
+ transitions: [
+ Transition { NumberAnimation { matchProperties: "x,y"; duration: 500; easing: "easeInOutQuad" } }
+ ]
+ }
+}
diff --git a/demos/declarative/webbrowser/content/FlickableWebView.qml b/demos/declarative/webbrowser/content/FlickableWebView.qml
new file mode 100644
index 0000000..7c46d4c
--- /dev/null
+++ b/demos/declarative/webbrowser/content/FlickableWebView.qml
@@ -0,0 +1,162 @@
+import Qt 4.6
+
+Flickable {
+ property alias title: webView.title
+ property alias progress: webView.progress
+ property alias url: webView.url
+ property alias back: webView.back
+ property alias reload: webView.reload
+ property alias forward: webView.forward
+
+ id: flickable
+ width: parent.width
+ viewportWidth: Math.max(parent.width,webView.width*webView.scale)
+ viewportHeight: Math.max(parent.height,webView.height*webView.scale)
+ anchors.top: headerSpace.bottom
+ anchors.bottom: footer.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ pressDelay: 200
+
+ WebView {
+ id: webView
+ pixelCacheSize: 4000000
+
+ Script {
+ function fixUrl(url)
+ {
+ if (url == "") return url
+ if (url[0] == "/") return "file://"+url
+ if (url.indexOf(":")<0) {
+ if (url.indexOf(".")<0 || url.indexOf(" ")>=0) {
+ // Fall back to a search engine; hard-code Wikipedia
+ return "http://en.wikipedia.org/w/index.php?search="+url
+ } else {
+ return "http://"+url
+ }
+ }
+ return url
+ }
+ }
+
+ url: fixUrl(webBrowser.urlString)
+ smooth: false // We don't want smooth scaling, since we only scale during (fast) transitions
+ smoothCache: true // We do want smooth rendering
+ fillColor: "white"
+ focus: true
+ zoomFactor: 4
+
+ onAlert: console.log(message)
+
+ function doZoom(zoom,centerX,centerY)
+ {
+ if (centerX) {
+ var sc = zoom/contentsScale;
+ scaleAnim.to = sc;
+ flickVX.from = flickable.viewportX
+ flickVX.to = Math.max(0,Math.min(centerX-flickable.width/2,webView.width*sc-flickable.width))
+ finalX.value = flickVX.to
+ flickVY.from = flickable.viewportY
+ flickVY.to = Math.max(0,Math.min(centerY-flickable.height/2,webView.height*sc-flickable.height))
+ finalY.value = flickVY.to
+ finalZoom.value = zoom
+ quickZoom.start()
+ }
+ }
+
+ Keys.onLeftPressed: webView.contentsScale -= 0.1
+ Keys.onRightPressed: webView.contentsScale += 0.1
+
+ preferredWidth: flickable.width*zoomFactor
+ preferredHeight: flickable.height*zoomFactor
+ contentsScale: 1/zoomFactor
+ onContentsSizeChanged: {
+ // zoom out
+ contentsScale = Math.min(0.25,flickable.width / contentsSize.width)
+ }
+ onUrlChanged: {
+ // got to topleft
+ flickable.viewportX = 0
+ flickable.viewportY = 0
+ if (url != null) { header.editUrl = url.toString(); }
+ }
+ onDoubleClick: {
+ if (!heuristicZoom(clickX,clickY,2.5)) {
+ var zf = flickable.width / contentsSize.width
+ if (zf >= contentsScale)
+ zf = 2.0/zoomFactor // zoom in (else zooming out)
+ doZoom(zf,clickX*zf,clickY*zf)
+ }
+ }
+
+ SequentialAnimation {
+ id: quickZoom
+
+ PropertyAction {
+ target: webView
+ property: "renderingEnabled"
+ value: false
+ }
+ ParallelAnimation {
+ NumberAnimation {
+ id: scaleAnim
+ target: webView
+ property: "scale"
+ from: 1
+ to: 0 // set before calling
+ easing: "easeLinear"
+ duration: 200
+ }
+ NumberAnimation {
+ id: flickVX
+ target: flickable
+ property: "viewportX"
+ easing: "easeLinear"
+ duration: 200
+ from: 0 // set before calling
+ to: 0 // set before calling
+ }
+ NumberAnimation {
+ id: flickVY
+ target: flickable
+ property: "viewportY"
+ easing: "easeLinear"
+ duration: 200
+ from: 0 // set before calling
+ to: 0 // set before calling
+ }
+ }
+ PropertyAction {
+ id: finalZoom
+ target: webView
+ property: "contentsScale"
+ }
+ PropertyAction {
+ target: webView
+ property: "scale"
+ value: 1.0
+ }
+ // Have to set the viewportXY, since the above 2
+ // size changes may have started a correction if
+ // contentsScale < 1.0.
+ PropertyAction {
+ id: finalX
+ target: flickable
+ property: "viewportX"
+ value: 0 // set before calling
+ }
+ PropertyAction {
+ id: finalY
+ target: flickable
+ property: "viewportY"
+ value: 0 // set before calling
+ }
+ PropertyAction {
+ target: webView
+ property: "renderingEnabled"
+ value: true
+ }
+ }
+ onZoomTo: doZoom(zoom,centerX,centerY)
+ }
+}
diff --git a/demos/declarative/webbrowser/content/RectSoftShadow.qml b/demos/declarative/webbrowser/content/RectSoftShadow.qml
new file mode 100644
index 0000000..5b6d4ec
--- /dev/null
+++ b/demos/declarative/webbrowser/content/RectSoftShadow.qml
@@ -0,0 +1,32 @@
+import Qt 4.6
+
+Item {
+ BorderImage {
+ source: "pics/softshadow-left.sci"
+ x: -16
+ y: -16
+ width: 16
+ height: parent.height+32
+ }
+ BorderImage {
+ source: "pics/softshadow-right.sci"
+ x: parent.width
+ y: -16
+ width: 16
+ height: parent.height+32
+ }
+ Image {
+ source: "pics/softshadow-top.png"
+ x: 0
+ y: -16
+ width: parent.width
+ height: 16
+ }
+ Image {
+ source: "pics/softshadow-bottom.png"
+ x: 0
+ y: parent.height
+ width: parent.width
+ height: 16
+ }
+}
diff --git a/demos/declarative/webbrowser/content/RetractingWebBrowserHeader.qml b/demos/declarative/webbrowser/content/RetractingWebBrowserHeader.qml
new file mode 100644
index 0000000..a7e6a97
--- /dev/null
+++ b/demos/declarative/webbrowser/content/RetractingWebBrowserHeader.qml
@@ -0,0 +1,106 @@
+import Qt 4.6
+
+import "fieldtext"
+
+Image {
+ property alias editUrl: editUrl.text
+
+ id: header
+ source: "pics/header.png"
+ width: parent.width
+ height: 60
+ x: webView.viewportX < 0 ? -webView.viewportX : webView.viewportX > webView.viewportWidth-webView.width
+ ? -webView.viewportX+webView.viewportWidth-webView.width : 0
+ y: webView.viewportY < 0 ? -webView.viewportY : progressOff*
+ (webView.viewportY>height?-height:-webView.viewportY)
+ Text {
+ id: headerText
+
+ text: webView.title!='' || webView.progress == 1.0 ? webView.title : 'Loading...'
+ elide: Text.ElideRight
+
+ color: "white"
+ styleColor: "black"
+ style: Text.Raised
+
+ font.family: "Helvetica"
+ font.pointSize: 10
+ font.bold: true
+
+ anchors.left: header.left
+ anchors.right: header.right
+ anchors.leftMargin: 4
+ anchors.rightMargin: 4
+ anchors.top: header.top
+ anchors.topMargin: 4
+ horizontalAlignment: Text.AlignHCenter
+ }
+ Item {
+ width: parent.width
+ anchors.top: headerText.bottom
+ anchors.topMargin: 2
+ anchors.bottom: parent.bottom
+
+ Item {
+ id: urlBox
+ height: 31
+ anchors.left: parent.left
+ anchors.leftMargin: 12
+ anchors.right: parent.right
+ anchors.rightMargin: 12
+ anchors.top: parent.top
+ clip: true
+ property bool mouseGrabbed: false
+
+ BorderImage {
+ source: "pics/addressbar.sci"
+ anchors.fill: urlBox
+ }
+
+ BorderImage {
+ id: urlBoxhl
+ source: "pics/addressbar-filled.sci"
+ width: parent.width*webView.progress
+ height: parent.height
+ opacity: 1-header.progressOff
+ clip: true
+ }
+
+ FieldText {
+ id: editUrl
+ mouseGrabbed: parent.mouseGrabbed
+
+ text: webBrowser.urlString
+ label: "url:"
+ onConfirmed: { webBrowser.urlString = editUrl.text; webView.focus=true }
+ onCancelled: { webView.focus=true }
+ onStartEdit: { webView.focus=false }
+
+ anchors.left: urlBox.left
+ anchors.right: urlBox.right
+ anchors.leftMargin: 6
+ anchors.verticalCenter: urlBox.verticalCenter
+ anchors.verticalCenterOffset: 1
+ }
+ }
+ }
+
+ property real progressOff : 1
+ states: [
+ State {
+ name: "ProgressShown"
+ when: webView.progress < 1.0
+ PropertyChanges { target: header; progressOff: 0; }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation {
+ matchTargets: header
+ matchProperties: "progressOff"
+ easing: "easeInOutQuad"
+ duration: 300
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/webbrowser/content/fieldtext/FieldText.qml b/demos/declarative/webbrowser/content/fieldtext/FieldText.qml
new file mode 100644
index 0000000..6b1d271
--- /dev/null
+++ b/demos/declarative/webbrowser/content/fieldtext/FieldText.qml
@@ -0,0 +1,161 @@
+import Qt 4.6
+
+Item {
+ id: fieldText
+ height: 30
+ property string text: ""
+ property string label: ""
+ property bool mouseGrabbed: false
+ signal confirmed
+ signal cancelled
+ signal startEdit
+
+ Script {
+
+ function edit() {
+ if (!mouseGrabbed) {
+ fieldText.startEdit();
+ fieldText.state='editing';
+ mouseGrabbed=true;
+ }
+ }
+
+ function confirm() {
+ fieldText.state='';
+ fieldText.text = textEdit.text;
+ mouseGrabbed=false;
+ fieldText.confirmed();
+ }
+
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ mouseGrabbed=false;
+ fieldText.cancelled();
+ }
+
+ }
+
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/cancel.png"
+ opacity: 0
+ }
+
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/ok.png"
+ opacity: 0
+ }
+
+ TextInput {
+ id: textEdit
+ text: fieldText.text
+ focus: false
+ anchors.left: parent.left
+ anchors.leftMargin: 0
+ anchors.right: parent.right
+ anchors.rightMargin: 0
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ font.bold: true
+ readOnly: true
+ onAccepted: confirm()
+ Keys.onEscapePressed: reset()
+ }
+
+ Text {
+ id: textLabel
+ x: 5
+ width: parent.width-10
+ anchors.verticalCenter: parent.verticalCenter
+ horizontalAlignment: Text.AlignHCenter
+ color: fieldText.state == "editing" ? "#505050" : "#AAAAAA"
+ font.italic: true
+ font.bold: true
+ text: label
+ opacity: textEdit.text == '' ? 1 : 0
+ opacity: Behavior {
+ NumberAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+
+ MouseRegion {
+ anchors.fill: cancelIcon
+ onClicked: { reset() }
+ }
+
+ MouseRegion {
+ anchors.fill: confirmIcon
+ onClicked: { confirm() }
+ }
+
+ MouseRegion {
+ id: editRegion
+ anchors.fill: textEdit
+ onClicked: { edit() }
+ }
+
+ states: [
+ State {
+ name: "editing"
+ PropertyChanges {
+ target: confirmIcon
+ opacity: 1
+ }
+ PropertyChanges {
+ target: cancelIcon
+ opacity: 1
+ }
+ PropertyChanges {
+ target: textEdit
+ color: "black"
+ readOnly: false
+ focus: true
+ selectionStart: 0
+ selectionEnd: -1
+ }
+ PropertyChanges {
+ target: editRegion
+ opacity: 0
+ }
+ PropertyChanges {
+ target: textEdit.anchors
+ leftMargin: 34
+ }
+ PropertyChanges {
+ target: textEdit.anchors
+ rightMargin: 34
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: ""
+ to: "*"
+ reversible: true
+ NumberAnimation {
+ matchProperties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ property: "color"
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/webbrowser/content/fieldtext/pics/cancel.png b/demos/declarative/webbrowser/content/fieldtext/pics/cancel.png
new file mode 100644
index 0000000..ecc9533
--- /dev/null
+++ b/demos/declarative/webbrowser/content/fieldtext/pics/cancel.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/fieldtext/pics/ok.png b/demos/declarative/webbrowser/content/fieldtext/pics/ok.png
new file mode 100644
index 0000000..5795f04
--- /dev/null
+++ b/demos/declarative/webbrowser/content/fieldtext/pics/ok.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/addressbar-filled.png b/demos/declarative/webbrowser/content/pics/addressbar-filled.png
new file mode 100644
index 0000000..d8452ec
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar-filled.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/addressbar-filled.sci b/demos/declarative/webbrowser/content/pics/addressbar-filled.sci
new file mode 100644
index 0000000..96c5efb
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar-filled.sci
@@ -0,0 +1,6 @@
+border.left: 7
+border.top: 7
+border.bottom: 7
+border.right: 7
+source: addressbar-filled.png
+
diff --git a/demos/declarative/webbrowser/content/pics/addressbar.png b/demos/declarative/webbrowser/content/pics/addressbar.png
new file mode 100644
index 0000000..3278f58
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/addressbar.sci b/demos/declarative/webbrowser/content/pics/addressbar.sci
new file mode 100644
index 0000000..8f1cd18
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/addressbar.sci
@@ -0,0 +1,6 @@
+border.left: 7
+border.top: 7
+border.bottom: 7
+border.right: 7
+source: addressbar.png
+
diff --git a/demos/declarative/webbrowser/content/pics/back-disabled.png b/demos/declarative/webbrowser/content/pics/back-disabled.png
new file mode 100644
index 0000000..91b9e76
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/back-disabled.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/back.png b/demos/declarative/webbrowser/content/pics/back.png
new file mode 100644
index 0000000..9988dd3
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/back.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/footer.png b/demos/declarative/webbrowser/content/pics/footer.png
new file mode 100644
index 0000000..8391a93
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/footer.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/footer.sci b/demos/declarative/webbrowser/content/pics/footer.sci
new file mode 100644
index 0000000..7be58f1
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/footer.sci
@@ -0,0 +1,6 @@
+border.left: 5
+border.top: 0
+border.bottom: 0
+border.right: 5
+source: footer.png
+
diff --git a/demos/declarative/webbrowser/content/pics/forward-disabled.png b/demos/declarative/webbrowser/content/pics/forward-disabled.png
new file mode 100644
index 0000000..cb87f4f
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/forward-disabled.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/forward.png b/demos/declarative/webbrowser/content/pics/forward.png
new file mode 100644
index 0000000..83870ee
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/forward.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/header.png b/demos/declarative/webbrowser/content/pics/header.png
new file mode 100644
index 0000000..26588c3
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/header.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/reload.png b/demos/declarative/webbrowser/content/pics/reload.png
new file mode 100644
index 0000000..45b5535
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/reload.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-bottom.png b/demos/declarative/webbrowser/content/pics/softshadow-bottom.png
new file mode 100644
index 0000000..85b0b44
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-bottom.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-left.png b/demos/declarative/webbrowser/content/pics/softshadow-left.png
new file mode 100644
index 0000000..02926d1
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-left.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-left.sci b/demos/declarative/webbrowser/content/pics/softshadow-left.sci
new file mode 100644
index 0000000..45c88d5
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-left.sci
@@ -0,0 +1,5 @@
+border.left: 0
+border.top: 16
+border.bottom: 16
+border.right: 0
+source: softshadow-left.png
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-right.png b/demos/declarative/webbrowser/content/pics/softshadow-right.png
new file mode 100644
index 0000000..e459f4f
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-right.png
Binary files differ
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-right.sci b/demos/declarative/webbrowser/content/pics/softshadow-right.sci
new file mode 100644
index 0000000..4d459c0
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-right.sci
@@ -0,0 +1,5 @@
+border.left: 0
+border.top: 16
+border.bottom: 16
+border.right: 0
+source: softshadow-right.png
diff --git a/demos/declarative/webbrowser/content/pics/softshadow-top.png b/demos/declarative/webbrowser/content/pics/softshadow-top.png
new file mode 100644
index 0000000..9a9e232
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/softshadow-top.png
Binary files differ
diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml
new file mode 100644
index 0000000..3b3790c
--- /dev/null
+++ b/demos/declarative/webbrowser/webbrowser.qml
@@ -0,0 +1,169 @@
+import Qt 4.6
+
+import "content"
+
+Item {
+ id: webBrowser
+
+ property string urlString : "http://qt.nokia.com/"
+
+ width: 640
+ height: 480
+
+ Item {
+ id: webPanel
+ anchors.fill: parent
+ clip: true
+ Rectangle {
+ color: "#555555"
+ anchors.fill: parent
+ }
+ Image {
+ source: "content/pics/softshadow-bottom.png"
+ width: webPanel.width
+ height: 16
+ }
+ Image {
+ source: "content/pics/softshadow-top.png"
+ width: webPanel.width
+ height: 16
+ anchors.bottom: footer.top
+ }
+ RectSoftShadow {
+ x: -webView.viewportX
+ y: -webView.viewportY
+ width: webView.viewportWidth
+ height: webView.viewportHeight+headerSpace.height
+ }
+ Item {
+ id: headerSpace
+ width: parent.width
+ height: 60
+ z: 1
+
+ RetractingWebBrowserHeader { id: header }
+ }
+ FlickableWebView {
+ id: webView
+ width: parent.width
+ anchors.top: headerSpace.bottom
+ anchors.bottom: footer.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+ BorderImage {
+ id: footer
+ source: "content/pics/footer.sci"
+ width: parent.width
+ height: 43
+ anchors.bottom: parent.bottom
+ Rectangle {
+ y: -1
+ width: parent.width
+ height: 1
+ color: "#555555"
+ }
+ Item {
+ id: backbutton
+ width: back_e.width
+ height: back_e.height
+ anchors.right: reload.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ Image {
+ id: back_e
+ source: "content/pics/back.png"
+ anchors.fill: parent
+ }
+ Image {
+ id: back_d
+ source: "content/pics/back-disabled.png"
+ anchors.fill: parent
+ }
+ states: [
+ State {
+ name: "Enabled"
+ when: webView.back.enabled==true
+ PropertyChanges { target: back_e; opacity: 1 }
+ PropertyChanges { target: back_d; opacity: 0 }
+ },
+ State {
+ name: "Disabled"
+ when: webView.back.enabled==false
+ PropertyChanges { target: back_e; opacity: 0 }
+ PropertyChanges { target: back_d; opacity: 1 }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation {
+ matchProperties: "opacity"
+ easing: "easeInOutQuad"
+ duration: 300
+ }
+ }
+ ]
+ MouseRegion {
+ anchors.fill: back_e
+ onClicked: { if (webView.back.enabled) webView.back.trigger() }
+ }
+ }
+ Image {
+ id: reload
+ source: "content/pics/reload.png"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ MouseRegion {
+ anchors.fill: reload
+ onClicked: { webView.reload.trigger() }
+ }
+ Item {
+ id: forwardbutton
+ width: forward_e.width
+ height: forward_e.height
+ anchors.left: reload.right
+ anchors.leftMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ Image {
+ id: forward_e
+ source: "content/pics/forward.png"
+ anchors.fill: parent
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ Image {
+ id: forward_d
+ source: "content/pics/forward-disabled.png"
+ anchors.fill: parent
+ }
+ states: [
+ State {
+ name: "Enabled"
+ when: webView.forward.enabled==true
+ PropertyChanges { target: forward_e; opacity: 1 }
+ PropertyChanges { target: forward_d; opacity: 0 }
+ },
+ State {
+ name: "Disabled"
+ when: webView.forward.enabled==false
+ PropertyChanges { target: forward_e; opacity: 0 }
+ PropertyChanges { target: forward_d; opacity: 1 }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation {
+ matchProperties: "opacity"
+ easing: "easeInOutQuad"
+ duration: 320
+ }
+ }
+ ]
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { if (webView.forward.enabled) webView.forward.trigger() }
+ }
+ }
+ }
+ }
+}
diff --git a/demos/embedded/fluidlauncher/fluidlauncher.pro b/demos/embedded/fluidlauncher/fluidlauncher.pro
index 92d6e1e..f71388c 100644
--- a/demos/embedded/fluidlauncher/fluidlauncher.pro
+++ b/demos/embedded/fluidlauncher/fluidlauncher.pro
@@ -213,5 +213,7 @@ symbian {
DEPLOYMENT += config files executables viewerimages saxbookmarks reg_resource resource \
mifs desktopservices_music desktopservices_images fluidbackup
+ DEPLOYMENT.installer_header = 0xA000D7CD
+
TARGET.EPOCHEAPSIZE = 100000 20000000
}
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 00509ed..657aafc 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -1,7 +1,7 @@
Qt 4.6.2 is a bug-fix release. It maintains both forward and backward
-compatibility (source and binary) with Qt 4.6.0. For more details,
-refer to the online documentation included in this distribution. The
-documentation is also available online:
+compatibility (source and binary) with Qt 4.6.0 and 4.6.1. For more
+details, refer to the online documentation included in this
+distribution. The documentation is also available online:
http://qt.nokia.com/doc/4.6
@@ -16,22 +16,6 @@ Qt Bug Tracker: http://bugreports.qt.nokia.com
Task Tracker: http://qt.nokia.com/developer/task-tracker
Merge Request: http://qt.gitorious.org
-****************************************************************************
-* General *
-****************************************************************************
-
-New features
-------------
-
- - SomeClass, SomeOtherClass
- * New classes for foo, bar and baz
-
-Optimizations
--------------
-
- - Optimized foo in QSomeClass
- * See list of Important Behavior Changes below
-
****************************************************************************
* Library *
@@ -40,34 +24,90 @@ Optimizations
QtCore
------
+ - QAtomicPointer
+ * [QTBUG-7356] Fixed a compilation failure when using the Intel
+ compiler on IA-64
+ - QFile
+ * Fixed double-buffering issue when opening files in buffered mode.
+ * [QTBUG-7285] QFile::remove would() fail if an unrelated operation on the
+ same instance had been previously failed. This manifested itself in
+ QTemporaryFile failing to auto-remove files and QFile::copy() leaving
+ temporary files behind in certain situations.
+ - QFSFileEngine
+ * Fix typo that made realpath() not be used.
+ - QIODevice
+ * Optimized readAll().
+ - QReadWriteLock
+ * [MR 426] Fixed documentation.
- QXmlStreamWriter
- * [QTBUG-6893] Fixed adding extra Byte Order Marks when writing to a xml file.
+ * [QTBUG-6893] Fixed adding extra Byte Order Marks when writing to a
+ .xml file.
QtGui
-----
- - foo
- * bar
-
- * [QTBUG-7029] Fixed a crash when re-creating QApplication object due to a
- dangling gesture manager pointer.
+ - QApplication
+ * [QTBUG-6098] Added a flag to avoid construction of application panes.
+ * [QTBUG-7029] Fixed a crash when re-creating QApplication object due
+ to a dangling gesture manager pointer.
+ - QAbstractScrollArea
+ * [QTBUG-1760] Reverted horizontal scrolling with mouse wheel when vertical
+ scrollbar is hidden
+ - QBmpHandler
+ * [QTBUG-7530] Fixed an infinite loop that could occur when reading invalid
+ BMP images.
+ - QGraphicsEffect
+ * [QTBUG-6901] Fixed performance problem when translating items with
+ graphics effects.
+ - QImage
+ * [QTBUG-7231] Avoid an unnecessary copy in QImage::scaled().
+ - QInputContext
+ * [QTBUG-7439] Avoided the loss of preedit text when losing focus on
+ Symbian.
+ - QPDFEngine
+ * [QTBUG-7249] Fixed the encoding of the Tile and Creator tags in the PDF
+ engine.
+ - [QT-2629] Implemented event filter functions for Symbian.
+ - [QTBUG-7198] Setting a style sheet could break the checkbox position in
+ item views.
+ - [QTBUG-7253] Fixed wrong stroke clipping with the raster engine when using
+ a QPen with a style other than SolidLine.
QtDBus
------
- - foo
- * bar
+ - QDBusConnection
+ * [QT-2307] Fixed sending of D-Bus method calls with QDBus::BlockWithGui.
QtNetwork
---------
- - foo
- * bar
+ - QNetworkAccessManager
+ * Optimizations
+ * HTTP: Get rid of QAbstractSocket warnings that were sometimes displayed.
+ * HTTP: setReadBufferSize() of the QNetworkReply finally is working on all
+ layers.
+ * [QTBUG-7713] HTTP: Fix bug related to re-sending a request.
+ * [QTBUG-7060] Fixed an issue with parsing of HTTP headers like
+ "private, max-age=300".
+ - QSslCertificate
+ * [QTBUG-6466] Fix issuerInfo() and subjectInfo().
+ - QTcpSocket
+ * [QTBUG-7344] Fix performance degredation with write() on Windows.
+ * [QTBUG-7316,QTBUG-7317] Handle unknown errors from socket engine.
QtOpenGL
--------
- [QTBUG-7490] Better support for user-generated binary shaders.
+ - QGLPixelBuffer
+ * [QTBUG-7476] Fixed a crash under X11 when drawing QPixmaps to
+ QGLPixelBuffers.
+ - QGL2PaintEngineEx
+ * [QTBUG-7203] Reset the GL stencil mask, op and function in resetGLState().
+ - QGLWidget
+ * [QTBUG-7213] Fixed QGLWidget::renderPixmap() on Windows.
+
QtOpenVG
--------
@@ -75,116 +115,113 @@ QtOpenVG
- [QTBUG-7791] Optimize single-rect IntersectClip in OpenVG using the scissor.
- [QTBUG-7864] Use OpenVG scissor on 90/180/270 rotations and simple clips.
-QtScript
---------
-
- - foo
- * bar
-
-QtSql
------
-
- - foo
- * bar
-
-QtXml
------
-
- - foo
- * bar
-
QtMultimedia
------------
- QAudioInput
- * [QTBUG-7044]: QAudioInput stopped working correctly after suspend()/resume() on linux.
+ * [QTBUG-7044]: QAudioInput stopped working correctly after
+ suspend()/resume() on linux.
-Qt Plugins
-----------
-
- - foo
- * bar
-
-Third party components
-----------------------
-
- - Updated foo to version 2.3.9.
+Examples
+--------
- - Updated bar to the latest version from baz.org.
+ - QtMultimedia
+ * [MR 418] Fixed the example for QAudioOutput.
+ - WebKit
+ * [MR 2235] Added the framecapture example to the default build.
****************************************************************************
* Platform Specific Changes *
****************************************************************************
-Qt for Unix (X11 and Mac OS X)
-------------------------------
-
- -
-
Qt for Linux/X11
----------------
- * Fix a bug where QPixmap::serialNumber was not set on a transformed pixmap
- in Qt/X11.
-
- * Fixed a crash when an input method tries to create a widget after the
- application is destroyed.
-
-Qt for Windows
---------------
-
- -
+ - Fix a bug where QPixmap::serialNumber was not set on a transformed pixmap
+ in Qt/X11.
+ - Fixed a crash when an input method tries to create a widget after the
+ application is destroyed.
+ - [QTBUG-6952] Fixed a problem using NoButtons in spinbox with QGtkStyle.
+ - [QTBUG-7504] Fixed missing focus rect on check- and radiobutton with
+ some GTK+ themes.
+ - [QTBUG-6522] Fixed missing menu separator in some GTK+ themes.
Qt for Mac OS X
---------------
- - [QTBUG-7312]: Menubar and dock disappear after hiding a fullscreen widget on Cocoa.
- - [QTBUG-7522]: Drawing fake buttons using QMacStyle+QStyleOptionViewItemV4 lead to crash.
- - [QTBUG-7625]: Calling showFullScreen() then showNormal() on a widget results in top menu hiding.
-
-
-Qt for Embedded Linux
----------------------
-
- -
+ - [QTBUG-7832]: Restored missing margins around non-unified toolbars.
+ - [QTBUG-7312]: Menubar and dock disappear after hiding a fullscreen widget
+ on Cocoa.
+ - [QTBUG-7481]: Re-added the Close button in QPrintPreviewDialog for
+ Mac/Carbon.
+ - [QTBUG-7522]: Drawing fake buttons using QMacStyle+QStyleOptionViewItemV4
+ lead to crash.
+ - [QTBUG-7625]: Calling showFullScreen() then showNormal() on a widget results
+ in top menu hiding.
+ - [QTBUG-7086]: QFileDialog now correctly responds to fileMode & acceptMode
+ changes.
+ - [QTBUG-7162]: Fixed a crash in Designer when previewing a QMainWindow with
+ native toolbar.
+ - [QTBUG-7305]: Fixed a crash when deleting QMainWindow with native toolbar
+ on Cocoa.
+ - [QTBUG-6882]: Fixed a text layout issue with QHeaderView in right-to-left
+ mode.
DirectFB
--------
- * Fix a bug where QPixmap::serialNumber was not set on a transformed pixmap
- in DirectFB.
- * Reimplement QPixmapData::scroll for QDirectFBPixmapData which optimizes
- QPixmap::scroll
- * Fix a rendering issue for semi-transparent top level windows in DirectFB.
- * Make it possible to fall back to the raster engine for stretch blits in
- DirectFB using QT_NO_DIRECTFB_STRETCHBLIT
- -
-Qt for Windows CE
------------------
+ - Fix a bug where QPixmap::serialNumber was not set on a transformed pixmap
+ in DirectFB.
+ - Reimplement QPixmapData::scroll for QDirectFBPixmapData which optimizes
+ QPixmap::scroll.
+ - Fix a rendering issue for semi-transparent top level windows in DirectFB.
+ - Make it possible to fall back to the raster engine for stretch blits in
+ DirectFB using QT_NO_DIRECTFB_STRETCHBLIT.
+
+Qt for Symbian
+--------------
+
+ - [QTBUG-6556] Improve the DEF file handling scheme, to allow simple enable/
+ disable of DEF file usage (for use _during development only_ to decouple
+ the need to update the DEF files at the precise point that symbols are
+ removed, therefore allowing builds by CI systems to succeed even if symbols
+ have been removed. This does not remove the need to update the DEF files
+ before release. NOTE: Builds generated using this flag are not binary
+ compatible with previous versions of Qt.)
+ - QProcess
+ * [QTBUG-7667] Fixed no-timeout case for QProcess::waitForFinished.
+ - qmake
+ * [QTBUG-7695] Added support for ifdeffing for manufacturer in generated
+ pkg files.
+ * [QTBUG-7908] Smart installer package generation support.
+ - Patch_capabilities script
+ * Added support for embedded sis name/uid patching.
+ - Qt deployment
+ * [QTBUG-7518] Backup and restore support for Qt libs.
- -
****************************************************************************
* Tools *
****************************************************************************
- Designer
- * [QTBUG-6965] Enabled editing seconds of QDateTime-type properties
+ * [QTBUG-6965] Enabled editing seconds of QDateTime-type properties.
* [QTBUG-6757] Fixed bug where selection handles would be affected by
a style sheet set on the main form.
- uic3
* [QTBUG-7404] Added option to preserve layout names set by Qt 3 Designer.
- - qdoc3
- * bar
-
- - Linguist
- * baz
-
****************************************************************************
* Important Behavior Changes *
****************************************************************************
- -
+ - QNetworkAccessManager cache
+ * QNetworkAccessManager will no longer return expired pages, as
+ stated in the documentation
+ * The behaviour of PreferCache and PreferNetwork modes now match
+ the documentation more closely
+ - QUrl
+ * QUrl will now accept hostnames ending in dot and will not treat
+ those as invalid hostnames
diff --git a/dist/changes-4.7.0 b/dist/changes-4.7.0
index 92f5244..3504763 100644
--- a/dist/changes-4.7.0
+++ b/dist/changes-4.7.0
@@ -24,6 +24,9 @@ General Improvements
- Documentation and Examples
+- Support for the GL_EXT_geometry_shader4, aka Geometry Shaders, was added
+ to QGLShaderProgram.
+
Third party components
----------------------
diff --git a/doc/doc.pri b/doc/doc.pri
index 463c447..9d7d5da 100644
--- a/doc/doc.pri
+++ b/doc/doc.pri
@@ -21,13 +21,14 @@ $$unixstyle {
}
ADP_DOCS_QDOCCONF_FILE = qt-build-docs.qdocconf
QT_DOCUMENTATION = ($$QDOC qt-api-only.qdocconf assistant.qdocconf designer.qdocconf \
- linguist.qdocconf qmake.qdocconf) && \
+ linguist.qdocconf qmake.qdocconf qml.qdocconf) && \
(cd $$QT_BUILD_TREE && \
$$GENERATOR doc-build/html-qt/qt.qhp -o doc/qch/qt.qch && \
$$GENERATOR doc-build/html-assistant/assistant.qhp -o doc/qch/assistant.qch && \
$$GENERATOR doc-build/html-designer/designer.qhp -o doc/qch/designer.qch && \
$$GENERATOR doc-build/html-linguist/linguist.qhp -o doc/qch/linguist.qch && \
- $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch \
+ $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch && \
+ $$GENERATOR doc-build/html-qml/qml.qhp -o doc/qch/qml.qch \
)
win32-g++:isEmpty(QMAKE_SH) {
diff --git a/doc/src/declarative/advtutorial.qdoc b/doc/src/declarative/advtutorial.qdoc
new file mode 100644
index 0000000..1456eae9
--- /dev/null
+++ b/doc/src/declarative/advtutorial.qdoc
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page advtutorial.html
+\title Advanced Tutorial
+
+This tutorial goes step-by-step through creating a full application using just QML.
+It is assumed that you already know basic QML (such as from doing the simple tutorial) and the focus is on showing
+how to turn that knowledge into a complete and functioning application.
+
+This tutorial involves a significant amount of JavaScript to implement the game logic. An understanding of JavaScript is helpful to understand the JavaScript parts of this tutorial, but if you don't understand JavaScript you can still get a feel for how to integrate QML elements with backend logic which creates and controls them. From the QML perspective, there is little difference between integrating with backend logic written in C++ and backend logic written in JavaScript.
+
+In this tutorial we recreate, step by step, the Same Game demo in $QTDIR/demos/declarative/samegame.qml.
+The results of the individual steps are in the $QTDIR/examples/declarative/tutorials/samegame directory.
+
+Tutorial chapters:
+
+\list
+\o \l {Advanced Tutorial 1 - Creating the Game Canvas and Blocks}
+\o \l {Advanced Tutorial 2 - Populating the Game Canvas}
+\o \l {Advanced Tutorial 3 - Implementing the Game Logic}
+\o \l {Advanced Tutorial 4 - Finishing Touches}
+\endlist
+
+*/
diff --git a/doc/src/declarative/advtutorial1.qdoc b/doc/src/declarative/advtutorial1.qdoc
new file mode 100644
index 0000000..86d14ad
--- /dev/null
+++ b/doc/src/declarative/advtutorial1.qdoc
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page advtutorial1.html
+\title Advanced Tutorial 1 - Creating the Game Canvas and Blocks
+
+The first step is to create the items in your application. In Same Game we have a main game screen and the blocks that populate it.
+
+\image declarative-adv-tutorial1.png
+
+Here is the QML code for the basic elements. The game window:
+
+\snippet declarative/tutorials/samegame/samegame1/samegame.qml 0
+
+This gives you a basic game window, with room for the game canvas. A new game
+button and room to display the score. The one thing you may not recognize here
+is the \l SystemPalette item. This item provides access to the Qt system palette
+and is used to make the button look more like a system button (for exact native
+feel you would use a \l QPushButton). Since we want a fully QML button, and QML does
+not include a button, we had to write our own. Below is the code which we wrote to do this:
+
+\snippet declarative/tutorials/samegame/samegame1/Button.qml 0
+
+Note that this Button component was written to be fairly generic, in case we
+want to use a similarly styled button later.
+
+And here is a simple block:
+
+\snippet declarative/tutorials/samegame/samegame1/Block.qml 0
+
+Since it doesn't do anything yet it's very simple, just an image. As the
+tutorial progresses and the block starts doing things the file will become
+more than just an image. Note that we've set the image to be the size of the item.
+This will be used later, when we dynamically create and size the block items the image will be scaled automatically
+to the correct size.
+
+You should be familiar with all that goes on in these files so far. This is a
+very basic start and doesn't move at all - next we will populate the game canvas
+with some blocks.
+
+[\l {advtutorial.html}{Advanced Tutorial}] [Next: \l {Advanced Tutorial 2 - Populating the Game Canvas}]
+*/
+
diff --git a/doc/src/declarative/advtutorial2.qdoc b/doc/src/declarative/advtutorial2.qdoc
new file mode 100644
index 0000000..2aa68f3
--- /dev/null
+++ b/doc/src/declarative/advtutorial2.qdoc
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page advtutorial2.html
+\title Advanced Tutorial 2 - Populating the Game Canvas
+
+Now that we've written some basic elements, let's start writing the game. The
+first thing to do is to generate all of the blocks. Now we need to dynamically
+generate all of these blocks, because you have a new, random set of blocks
+every time. As they are dynamically generated every time the new game button is
+clicked, as opposed to on startup, we will be dynamically generating the blocks
+in the JavaScript, as opposed to using a \l Repeater.
+
+This adds enough script to justify a new file, \c{samegame.js}, the intial version
+of which is shown below
+
+\snippet declarative/tutorials/samegame/samegame2/samegame.js 0
+
+The gist of this code is that we create the blocks dynamically, as many as will fit, and then store them in an array for future reference.
+The \c initBoard function will be hooked up to the new game button soon, and should be fairly straight forward.
+
+The \c createBlock function is a lot bigger, and I'll explain it block by block.
+First we ensure that the component has been constructed. QML elements, including composite ones like the \c Block.qml
+that we've written, are never created directly in script. While there is a function to parse and create an arbitrary QML string,
+in the case where you are repeatedly creating the same item you will want to use the \c createComponent function. \c createComponent is
+a built-in function in the declarative JavaScript, and returns a component object.
+A component object prepares and stores a QML element (usually a composite element) for easy and efficient use.
+When the component is ready, you can create a new instance of the loaded QML with the \c createObject method.
+If the component is loaded remotely (over HTTP for example) then you will have to wait for the component to finish loading
+before calling \c createObject. Since we don't wait here (the waiting is asyncronous, the component object will send a signal to tell
+you when it's done) this code will only work if the block QML is a local file.
+
+As we aren't waiting for the component, the next block of code creates a game block with \c{component.createObject}.
+Since there could be an error in the QML file you are trying to load, success is not guaranteed.
+The first bit of error checkign code comes right after \c{createObject()}, to ensure that the object loaded correctly.
+If it did not load correctly the function returns false, but we don't have that hooked up to the main UI to indicate
+that something has gone wrong. Instead we print out error messages to the console, because an error here means an invalid
+QML file and should only happen while you are developing and testing the UI.
+
+Next we start to set up our dynamically created block.
+Because the \c{Block.qml} file is generic it needs to be placed in the main scene, and in the right place.
+This is why \c parent, \c x, \c y, \c width and \c height are set. We then store it in the board array for later use.
+
+Finally, we have some more error handling. You can only call \c{createObject} if the component has loaded.
+If it has not loaded, either it is still loading or there was an error loading (such as a missing file).
+Since we don't request remote files the problem is likely to be a missing or misplaced file.
+Again we print this to the console to aid debugging.
+
+You now have the code to create a field of blocks dynamically, like below:
+
+\image declarative-adv-tutorial2.png
+
+To hook this code up to the \e{New Game} button, you alter it as below:
+
+\snippet declarative/tutorials/samegame/samegame2/samegame.qml 1
+
+We have just replaced the \c{onClicked: console.log("Implement me!")} with \c{onClicked: initBoard()}.
+Note that in order to have the function available, you'll need to include the script in the main file,
+by adding a script element to it.
+
+\snippet declarative/tutorials/samegame/samegame2/samegame.qml 2
+
+With those two changes, and the script file, you are now dynamically creating a field of blocks you can play with.
+They don't do anything now though; the next chapter will add the game mechanics.
+
+[Previous: \l {Advanced Tutorial 1 - Creating the Game canvas and block}] [\l {advtutorial.html}{Advanced Tutorial}] [Next: \l {Advanced Tutorial 3 - Implementing the Game Logic}]
+
+*/
diff --git a/doc/src/declarative/advtutorial3.qdoc b/doc/src/declarative/advtutorial3.qdoc
new file mode 100644
index 0000000..e6e4e97
--- /dev/null
+++ b/doc/src/declarative/advtutorial3.qdoc
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page advtutorial3.html
+\title Advanced Tutorial 3 - Implementing the Game Logic
+
+First we add to the \c initBoard function clearing of the board before filling it up again, so that clicking new game won't leave the previous game
+lying around in the background. To the \c createComponent function we have added setting the type of the block to a number between
+one and three - it's fundamental to the game logic that the blocks be different types if you want a fun game.
+
+The main change was adding the following game logic functions:
+\list
+\o function \c{handleClick(x,y)}
+\o function \c{floodFill(xIdx,yIdx,type)}
+\o function \c{shuffleDown()}
+\o function \c{victoryCheck()}
+\o function \c{floodMoveCheck(xIdx, yIdx, type)}
+\endlist
+
+As this is a tutorial about QML, not game design, these functions will not be discussed in detail. The game logic here
+was written in script, but it could have been written in C++ and had these functions exposed in the same way (except probably faster).
+The interfacing of these functions and QML is what we will focus on. Of these functions, only \c handleClick and \c victoryCheck
+interface closely with the QML. Those functions are shown below (the rest are still in the code for this tutorial located at
+\c{$QTDIR/examples/declarative/tutorials/samegame}).
+
+\snippet declarative/tutorials/samegame/samegame3/samegame.js 1
+\snippet declarative/tutorials/samegame/samegame3/samegame.js 2
+
+You'll notice them referring to the \c gameCanvas item. This is an item that has been added to the QML for easier interfacing with the game logic.
+It is placed next to the background image and replaces the background as the item to create the blocks in.
+Its code is shown below:
+
+\snippet declarative/tutorials/samegame/samegame3/samegame.qml 1
+
+This item is the exact size of the board, contains a score property, and a mouse region for input.
+The blocks are now created as its children, and its size is used to determining the board size, so as to scale to the available screen size.
+Since it needs to bind its size to a multiple of \c tileSize, \c tileSize needs to be moved into a QML property and out of the script file.
+Note that it can still be accessed from the script.
+
+The mouse region simply calls \c{handleClick()}, which deals with the input events.
+Should those events cause the player to score, \c{gameCanvas.score} is updated.
+The score display text item has also been changed to bind its text property to \c{gamecanvas.score}.
+Note that if score was a global variable in the \c{samegame.js} file you could not bind to it. You can only bind to QML properties.
+
+\c victoryCheck() primarily updates the score variable. But it also pops up a dialog saying \e {Game Over} when the game is over.
+In this example we wanted a pure-QML, animated dialog, and since QML doesn't contain one, we wrote our own.
+Below is the code for the \c Dialog element, note how it's designed so as to be usable imperatively from within the script file (via the functions and signals):
+
+\snippet declarative/tutorials/samegame/samegame3/Dialog.qml 0
+
+And this is how it's used in the main QML file:
+
+\snippet declarative/tutorials/samegame/samegame3/samegame.qml 2
+
+Combined with the line of code in \c victoryCheck, this causes a dialog to appear when the game is over, informing the user of that fact.
+
+We now have a working game! The blocks can be clicked, the player can score, and the game can end (and then you start a new one).
+Below is a screenshot of what has been accomplished so far:
+
+\image declarative-adv-tutorial3.png
+
+Here is the QML code as it is now for the main file:
+
+\snippet declarative/tutorials/samegame/samegame3/samegame.qml 0
+
+And the code for the block:
+
+\snippet declarative/tutorials/samegame/samegame3/Block.qml 0
+
+The game works, but it's a little boring right now. Where are the smooth animated transitions? Where are the high scores?
+If you were a QML expert you could have written these in for the first iteration, but in this tutorial they've been saved
+until the next chapter - where your application becomes alive!
+
+[Previous: \l {Advanced Tutorial 2 - Populating the Game Canvas}] [\l {advtutorial.html}{Advanced Tutorial}] [Next: \l {Advanced Tutorial 4 - Finishing Touches}]
+
+*/
+
diff --git a/doc/src/declarative/advtutorial4.qdoc b/doc/src/declarative/advtutorial4.qdoc
new file mode 100644
index 0000000..855963c
--- /dev/null
+++ b/doc/src/declarative/advtutorial4.qdoc
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page advtutorial4.html
+\title Advanced Tutorial 4 - Finishing Touches
+
+Now we're going to do two things to liven the game up. Animate the blocks and add a web-based high score system.
+
+If you compare the \c samegame3 directory with \c samegame4, you'll noticed that we've cleaned the directory structure up.
+We now have a lot of files, and so they've been split up into folders - the most notable one being a content folder
+which we've placed all the QML but the main file.
+
+\section2 Animated Blocks
+
+The most vital animations are that the blocks move fluidly around the board. QML has many tools for fluid behavior,
+and in this case we're going to use the \l SpringFollow element. By having the script set \c targetX and \c targetY, instead of \c x
+and \c y directly, we can set the \c x and \c y of the block to a follow. \l SpringFollow is a property value source, which means
+that you can set a property to be one of these elements and it will automatically bind the property to the element's value.
+The SpringFollow's value follows another value over time, when the value it is tracking changes the SpringFollow's
+value will also change, but it will move smoothly there over time with a spring-like movement (based on the spring
+parameters specified). This is shown in the below snippet of code from \c Block.qml:
+
+\code
+ property int targetX: 0
+ property int targetY: 0
+
+ x: SpringFollow { source: targetX; spring: 2; damping: 0.2 }
+ y: SpringFollow { source: targetY; spring: 2; damping: 0.2 }
+\endcode
+
+We also have to change the \c{samegame.js} code, so that wherever it was setting the \c x or \c y it now sets \c targetX and \c targetY
+(including when creating the block). This simple change is all you need to get spring moving blocks that no longer teleport
+around the board. If you try doing just this though, you'll notice that they now never jump from one point to another, even in
+the initialization! This gives an odd effect of having them all slide out of the corner (0,0) on start up. We'd rather that they
+fall down from the top in rows. To do this, we disable the \c x follow (but not the \c y follow) and only enable it after we've set
+the \c x in the \c createBlock function. The above snippet now becomes:
+
+\snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 1
+
+The next-most vital animation is a smooth exit. For this animation, we'll use a \l Behavior element. A Behavior is also a property
+value source, and it is much like SpringFollow except that it doesn't model the behavior of a spring. You specify how a Behavior
+transitions using the standard animations. As we want the blocks to smoothly fade in and out we'll set a Behavior on the block
+image's opacity, like so:
+
+\snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 2
+
+Note that the \c{opacity: 0} makes it start out transparent. We could set the opacity in the script file when we create and destroy the blocks,
+but instead we use states (as this is useful for the next animation we'll implement). The below snippet is set on the root
+element of \c{Block.qml}:
+\code
+ property bool dying: false
+ states: [
+ State{ name: "AliveState"; when: spawned == true && dying == false
+ PropertyChanges { target: img; opacity: 1 }
+ }, State{ name: "DeathState"; when: dying == true
+ PropertyChanges { target: img; opacity: 0 }
+ }
+ ]
+\endcode
+
+Now it will automatically fade in, as we set spawned to true already when implementing the block movement animations.
+To fade out, we set 'dying' to true instead of setting opacity to 0 when a block is destroyed (in the \c floodFill function).
+
+The least vital animations are a cool-looking particle effect when they get destroyed. First we create a \l Particles element in
+the block, like so:
+
+\snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 3
+
+To fully understand this you'll want to look at the Particles element documentation, but it's important to note that emissionRate is set
+to zero, so that no particles are emitted normally.
+We next extend the 'dying' state, which creates a burst of particles by calling the burst method on the particles element. The code for the states now look
+like this:
+
+\snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 4
+
+And now the game should be beautifully animated and smooth, with a subtle (or not-so-subtle) animation added for all of the
+player's actions. The end result is shown below, with a different set of images to demonstrate basic themeing:
+
+\image declarative-adv-tutorial4.gif
+
+The basic theme change there is the result of simply replacing the images. This can be done at run time by setting the source property, so a further advanced feature to try on your own is to add a button which toggles between two different themes.
+
+\section2 Offline High Scores
+Another extension we might want for the game is some way of storing and retrieving high scores. This tutorial contains both online and offline high score storage.
+
+For better high score data, we want the name and time of the player. The time is obtained in the script fairly simply, but we
+have to ask the player for their name. We thus re-use the dialog QML file to pop up a dialog asking for the player's name (and
+if they exit this dialog without entering it they have a way to opt out of posting their high score). When the dialog is closed we store the name and high score, using the code below.
+
+\snippet declarative/tutorials/samegame/samegame4/content/samegame.js 2
+
+For offline storage, we use the HTML 5 offline storage JavaScript API to maintain a persistant SQL database unique to this application. This first line in this function calls the function for the web-based high scores, described later, if it has been setup. Next we create an offline storage database for the high scores using openDatabase and prepare the data and SQL query that we want to use to save it. The offline storage API uses SQL queries for data manipulation and retrival, and in the db.transaction call we use three SQL queries to initialize the database (if necessary), and then add to and retrieve high scores. To use the returned data, we turn it into a string with one line per row returned, and show a dialog containing that string. For a more detailed explanation of the offline storage API in QML, consult the global object documentation.
+
+This is one way of storing and displaying high scores locally, but not the only way. A more complex alternative would have been to create a high score dialog component, and pass the results to it for processing and display (instead of resusing the Dialog). This would allow a more themable dialog that could present the high scores better. If your QML is the UI for a C++ application, you could also have passed the score to a C++ function to store it locally in a variety of ways, including a simple format without SQL or in another SQL database.
+
+\section2 Web-based High Scores
+
+You've seen how to store high scores locally, but it is also easy to integrate a web enabled high score storage into your QML application. This tutorial also shows you how to communicate the high scores to a web server. The implementation we've done is very
+simple - the high score data is posted to a php script running on a server somewhere, and that server then stores it and
+displays it to visitors. You could request an XML or QML file from that same server, which contained and displayed the scores,
+but that's beyond the scope of this tutorial. The php script we've used is available in the examples directory.
+
+if the player entered their name we can send the data to the web service in the following snippet out of the script file:
+
+\snippet declarative/tutorials/samegame/samegame4/content/samegame.js 1
+
+This is the same \c XMLHttpRequest() as you'll find in browser JavaScript, and can be used in the same way to dynamically get XML
+or QML from the web service to display the high scores. We don't worry about the response in this case, we just post the high
+score data to the web server. If it had returned a QML file (or a URL to a QML file) you could instantiate it in much the same
+way as you did the blocks.
+
+An alternate way to access and submit web-based data would be to use QML elements designed for this purpose - XmlListModel
+makes it very easy to fetch and display XML based data such as RSS in a QML application (see the Flickr demo for an example).
+
+By following this tutorial you've now ben shown how to write a fully functional application in QML, with the application logic
+written in a script file and with both many fluid animations and being web-enabled. Congratulations, you should now be skilled
+enough to write entire applications in QML.
+
+[Previous: \l {Advanced Tutorial 3 - Implementing the Game Logic}] [\l {advtutorial.html}{Advanced Tutorial}]
+*/
diff --git a/doc/src/declarative/anchor-layout.qdoc b/doc/src/declarative/anchor-layout.qdoc
new file mode 100644
index 0000000..2bd0ec5
--- /dev/null
+++ b/doc/src/declarative/anchor-layout.qdoc
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page anchor-layout.html
+\target anchor-layout
+\title Anchor-based Layout in QML
+
+In addition to the more traditional \l Grid, \l Row, and \l Column, QML also provides a way to layout items using the concept of \e anchors. Each item can be thought of as having a set of 6 invisible "anchor lines": \e left, \e horizontalCenter, \e right, \e top, \e verticalCenter, and \e bottom.
+
+\image edges_qml.png
+
+The QML anchoring system allows you to define relationships between the anchor lines of different items. For example, you can write:
+
+\code
+Rectangle { id: rect1; ... }
+Rectangle { id: rect2; anchors.left: rect1.right; ... }
+\endcode
+
+In this case, the left edge of \e rect2 is bound to the right edge of \e rect1, producing the following:
+
+\image edge1.png
+
+The anchoring system also allows you to specify margins and offsets. Margins specify the amount of empty space to leave to the outside of an item, while offsets allow you to manipulate positioning using the center anchor lines. Note that margins specified using the anchor layout system only have meaning for anchors; they won't have any effect when using other layouts or absolute positioning.
+
+\image margins_qml.png
+
+The following example specifies a left margin:
+
+\code
+Rectangle { id: rect1; ... }
+Rectangle { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }
+\endcode
+
+In this case, a margin of 5 pixels is reserved to the left of \e rect2, producing the following:
+
+\image edge2.png
+
+You can specify multiple anchors. For example:
+
+\code
+Rectangle { id: rect1; ... }
+Rectangle { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... }
+\endcode
+
+\image edge3.png
+
+By specifying multiple horizontal or vertical anchors you can control the size of an item. For example:
+
+\code
+Rectangle { id: rect1; x: 0; ... }
+Rectangle { id: rect2; anchors.left: rect1.right; anchors.right: rect3.left; ... }
+Rectangle { id: rect3; x: 150; ... }
+\endcode
+
+\image edge4.png
+
+\section1 Limitations
+
+For performance reasons, you can only anchor an item to its siblings and direct parent. For example, the following anchor would be considered invalid and would produce a warning:
+
+\badcode
+Item {
+ id: group1
+ Rectangle { id: rect1; ... }
+}
+Item {
+ id: group2
+ Rectangle { id: rect2; anchors.left: rect1.right; ... } // invalid anchor!
+}
+\endcode
+
+*/
diff --git a/doc/src/declarative/animation.qdoc b/doc/src/declarative/animation.qdoc
new file mode 100644
index 0000000..bf5907d
--- /dev/null
+++ b/doc/src/declarative/animation.qdoc
@@ -0,0 +1,268 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlanimation.html
+\title QML Animation
+
+Animation in QML is done by animating properties of objects. Properties of type
+real, int, color, rect, point, and size can all be animated.
+
+QML supports three different forms of animation - basic property animation,
+transitions, and property behaviors.
+
+\tableofcontents
+
+\section1 Basic Property Animation
+
+The simplest form of animation is directly using \l PropertyAnimation, which can animate all of the property
+types listed above. If the property you are animating is a number or color, you can alternatively use
+NumberAnimation or ColorAnimation. These elements don't add any additional functionality,
+but will help enforce type correctness and are slightly more efficient.
+
+A property animation can be specified as a value source. This is especially useful for repeating animations.
+
+The following example creates a bouncing effect:
+\qml
+Rectangle {
+ id: rect
+ width: 120; height: 200;
+ Image {
+ id: img
+ source: "qt-logo.png"
+ x: 60-img.width/2
+ y: 0
+ y: SequentialAnimation {
+ running: true
+ repeat: true
+ NumberAnimation { to: 200-img.height; easing: "easeOutBounce"; duration: 2000 }
+ PauseAnimation { duration: 1000 }
+ NumberAnimation { to: 0; easing: "easeOutQuad"; duration: 1000 }
+ }
+ }
+}
+\endqml
+
+\image propanim.gif
+
+When you assign an animation as a value source, you do not need to specify \c property
+or \c target; they are automatically selected for you. You do, however, need to specify \c to, and explicitly
+start the animation (usually via the \c running property).
+
+\qml
+Rectangle {
+ id: rect
+ width: 200; height: 200;
+ Rectangle {
+ color: "red"
+ width: 50; height: 50
+ x: NumberAnimation { to: 50; running: true }
+ }
+}
+\endqml
+
+A property animation can also be specified as a resource that is manipulated from script.
+
+\qml
+PropertyAnimation {
+ id: animation
+ target: image
+ property: "scale"
+ from: 1; to: .5
+}
+Image {
+ id: image
+ source: "image.png"
+ MouseRegion {
+ anchors.fill: parent
+ onPressed: animation.start()
+ }
+}
+\endqml
+
+As can be seen, when an animation is used like this (as opposed to as a value source) you will need
+to explicitly set the \c target and \c property to animate.
+
+Animations can be joined into a group using SequentialAnimation and ParallelAnimation.
+
+\target state-transitions
+\section1 Transitions
+
+QML transitions describe animations to perform when \l{qmlstates}{state} changes occur. A transition
+can only be triggered by a state change.
+
+For example, a transition could describe how an item moves from its initial position to its new position:
+
+\code
+transitions: [
+ Transition {
+ NumberAnimation {
+ matchProperties: "x,y"
+ easing: "easeOutBounce"
+ duration: 200
+ }
+ }
+]
+\endcode
+
+As you can see from the above example, transitions make use of the same basic animation classes introduced
+above. However, you generally use a different set of properties when working with transitions. In the example,
+no \c target or \c property has been specified. Instead, we have specified \c matchProperties,
+which (along with \c matchTargets) acts as a selector to determine which property changes to animate;
+in this case, we will animate any x,y properties that have changed on any objects.
+
+QML transitions also have selectors to determine which state changes a transition should apply to:
+
+\code
+Transition {
+ from: "*"
+ to: "details"
+ ...
+}
+\endcode
+
+Transitions can happen in parallel, in sequence, or in any combination of the two. By default, the top-level
+animations in a transition will happen in parallel. The following example shows a rather complex transition
+making use of both sequential and parallel animations:
+
+\code
+Transition {
+ from: "*"
+ to: "MyState"
+ reversible: true
+ SequentialAnimation {
+ ColorAnimation { duration: 1000 }
+ PauseAnimation { duration: 1000 }
+ ParallelAnimation {
+ NumberAnimation {
+ duration: 1000
+ easing: "easeOutBounce"
+ matchTargets: box1
+ matchProperties: "x,y"
+ }
+ NumberAnimation {
+ duration: 1000
+ matchTargets: box2
+ matchProperties: "x,y"
+ }
+ }
+ }
+}
+\endcode
+
+To insert an explicit animation into your transition, you can use \c target and \c property as normal.
+
+\code
+Transition {
+ from: "*"
+ to: "MyState"
+ reversible: true
+ SequentialAnimation {
+ NumberAnimation {
+ duration: 1000
+ easing: "easeOutBounce"
+ // animate myItem's x and y if they have changed in the state
+ matchTargets: myItem
+ matchProperties: "x,y"
+ }
+ NumberAnimation {
+ duration: 1000
+ // animate myItem2's y to 200, regardless of what happens in the state
+ target: myItem2
+ property: "y"
+ to: 200
+ }
+ }
+}
+\endcode
+
+\section1 Property Behaviors
+
+A \l{Behavior}{property behavior} specifies a default animation to run whenever the property's value changes, regardless
+of what caused the change. Unlike Transition, \l Behavior doesn't provide a way to indicate that a Behavior
+should only apply under certain circumstances.
+
+In the following snippet, we specify that we want the x position of redRect to be animated
+whenever it changes. The animation will last 300 milliseconds and use an InOutQuad easing curve.
+
+\qml
+Rectangle {
+ id: redRect
+ color: "red"
+ width: 100; height: 100
+ x: Behavior { NumberAnimation { duration: 300; easing: "InOutQuad" } }
+}
+\endqml
+
+Like using an animation as a value source, when used in a Behavior and animation does not need to specify
+a \c target or \c property.
+
+To trigger this behavior, we could:
+\list
+\o Enter a state that changes x
+
+\qml
+State {
+ name: "myState"
+ PropertyChanges {
+ target: redRect
+ x: 200
+ ...
+ }
+}
+\endqml
+
+\o Update x from a script
+
+\qml
+MouseRegion {
+ ....
+ onClicked: redRect.x = 24;
+}
+\endqml
+\endlist
+
+If x were bound to another property, triggering the binding would also trigger the behavior.
+
+If a state change has a transition animation matching a property with a Behavior, the transition animation
+will override the Behavior for that state change.
+
+*/
diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc
new file mode 100644
index 0000000..de5a959
--- /dev/null
+++ b/doc/src/declarative/basictypes.qdoc
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+ \page qmlbasictypes.html
+ \title QML Basic Types
+
+ QML uses a set of property types, which are primitive within QML.
+ These basic types are referenced throughout the documentation of the
+ QML elements. Almost all of them are exactly what you would expect.
+
+ \annotatedlist qmlbasictypes
+*/
+
+/*!
+ \qmlbasictype int
+ \ingroup qmlbasictypes
+
+ \brief An integer is a whole number, e.g. 0, 10, or -20.
+
+ An integer is a whole number, e.g. 0, 10, or -20. The possible \c
+ int values range from around -2000000000 to around 2000000000,
+ although most elements will only accept a reduced range (which they
+ mention in their documentation).
+
+ Example:
+ \qml
+ Item { width: 100; height: 200 }
+ \endqml
+*/
+
+/*!
+ \qmlbasictype bool
+ \ingroup qmlbasictypes
+
+ \brief A boolean is a binary true/false value.
+
+ A boolean is a binary true/false value.
+
+ Example:
+ \qml
+ Item { focus: true; clip: false }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype real
+ \ingroup qmlbasictypes
+
+ \brief A real number has a decimal point, e.g. 1.2 or -29.8.
+
+ A real number has a decimal point, e.g. 1.2 or -29.8.
+
+ Example:
+ \qml
+ Item { width: 100.45; height: 150.82 }
+ \endqml
+
+ \note In QML all reals are stored in single precision, \l
+ {http://en.wikipedia.org/wiki/IEEE_754} {IEEE floating point}
+ format.
+
+*/
+
+/*!
+ \qmlbasictype string
+ \ingroup qmlbasictypes
+
+ \brief A string is a free form text in quotes, e.g. "Hello world!".
+
+ A string is a free form text in quotes, e.g. "Hello world!".
+
+ Example:
+ \qml
+ Text { text: "Hello world!" }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype url
+ \ingroup qmlbasictypes
+
+ \brief A URL is a resource locator, like a file name.
+
+ A URL is a resource locator, like a file name. It can be either
+ absolute, e.g. "http://qtsoftware.com", or relative, e.g.
+ "pics/logo.png". A relative URL is resolved relative to the URL of
+ the component where the URL is converted from a JavaScript string
+ expression to a url property value.
+
+ Example:
+ \qml
+ Image { source: "pics/logo.png" }
+ \endqml
+
+ \raw HTML
+ \endraw
+
+*/
+
+/*!
+ \qmlbasictype color
+ \ingroup qmlbasictypes
+
+ \brief A color is a standard color name in quotes.
+
+ A color is a standard color name in quotes. It is normally specified
+ as an \l {http://www.w3.org/TR/SVG/types.html#ColorKeywords} {SVG
+ color name}. These names include colors like "red", "green" and
+ "lightsteelblue".
+
+ If the color you want isn't part of this list, colors can also be
+ specified in hexidecimal triplets or quads that take the form \c
+ "#RRGGBB" and \c "#AARRGGBB" respectively. For example, the color
+ red corresponds to a triplet of \c "#FF0000" and a slightly
+ transparent blue to a quad of \c "#800000FF".
+
+ Example:
+ \qml
+ Rectangle { color: "steelblue" }
+ Rectangle { color: "#FF0000" }
+ Rectangle { color: "#800000FF" }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype point
+ \ingroup qmlbasictypes
+
+ \brief A point is specified as "x,y".
+
+ A point is specified as "x,y".
+
+ Example:
+ \qml
+ Widget { pos: "0,20" }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype size
+ \ingroup qmlbasictypes
+
+ \brief A size is specified as "width x height".
+
+ A size is specified as "width x height".
+
+ Example:
+ \qml
+ Widget { size: "150x50" }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype rect
+ \ingroup qmlbasictypes
+
+ \brief A rect is specified as "x, y, width x height".
+
+ A rect is specified as "x, y, width x height".
+
+ Example:
+ \qml
+ Widget { geometry: "50,50,100x100" }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype date
+ \ingroup qmlbasictypes
+
+ \brief A date is specified as "YYYY-MM-DD".
+
+ A date is specified as "YYYY-MM-DD".
+
+ Example:
+ \qml
+ DatePicker { minDate: "2000-01-01"; maxDate: "2020-12-31" }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype time
+ \ingroup qmlbasictypes
+
+ \brief A time is specified as "hh:mm:ss".
+
+ A time is specified as "hh:mm:ss".
+
+ Example:
+ \qml
+ TimePicker { time: "14:22:15" }
+ \endqml
+
+ */
+
+/*!
+ \qmlbasictype font
+ \ingroup qmlbasictypes
+
+ \brief A font type has the properties of a QFont.
+
+ A font type has the properties of a QFont. The properties are:
+
+ \list
+ \o \c string font.family
+ \o \c bool font.bold
+ \o \c bool font.italic
+ \o \c bool font.underline
+ \o \c real font.pointSize
+ \o \c int font.pixelSize
+ \endlist
+
+ Example:
+ \qml
+ Text { font.family: "Helvetica"; font.pointSize: 13; font.bold: true }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype action
+ \ingroup qmlbasictypes
+
+ \brief The action type has all the properties of QAction.
+
+ The action type has all the properties of QAction. The properties
+ are:
+
+ \list
+ \o \c slot action.trigger - invoke the action
+ \o \c bool action.enabled - true if the action is enabled
+ \o \c string action.text - the text associated with the action
+ \endlist
+
+ Actions are used like this:
+
+ \qml
+ MouseRegion { onClicked: MyItem.myaction.trigger() }
+ State { name: "enabled"; when: MyItem.myaction.enabled == true }
+ Text { text: MyItem.someaction.text }
+ \endqml
+
+*/
+
+/*!
+ \qmlbasictype list
+ \ingroup qmlbasictypes
+
+ \brief A list of objects.
+
+ A list of objects. While not technically a basic type, QML also
+ supports lists of object types. When used from QML, the engine
+ automatically appends each value to the list.
+
+ For example, the \l Item class contains a list property named
+ children that can be used like this:
+
+ \qml
+ Item {
+ children: [
+ Item { id: child1 },
+ Rectangle { id: child2 },
+ Text { id: child3 }
+ ]
+ }
+ \endqml
+ \c Child1, \c Child2 and \c Child3 will all be added to the children list
+ in the order in which they appear.
+
+*/
+
+/*!
+ \qmlbasictype vector3d
+ \ingroup qmlbasictypes
+
+ \brief A vector3d is specified as "x,y,z".
+
+ A vector3d is specified as "x,y,z".
+
+ \qml
+ Rotation { angle: 60; axis: "0,1,0" }
+ \endqml
+
+ or with the \c{Qt.vector3d()} helper function:
+
+ \qml
+ Rotation { angle: 60; axis: Qt.vector3d(0, 1, 0) }
+ \endqml
+
+ or as separate \c x, \c y, and \c z components:
+
+ \qml
+ Rotation { angle: 60; axis.x: 0; axis.y: 1; axis.z: 0 }
+ \endqml
+*/
diff --git a/doc/src/declarative/declarativeui.qdoc b/doc/src/declarative/declarativeui.qdoc
new file mode 100644
index 0000000..8228c11
--- /dev/null
+++ b/doc/src/declarative/declarativeui.qdoc
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\title Declarative UI (QML)
+\page declarativeui.html
+
+\brief The Qt Declarative module provides a declarative framework for building
+highly dynamic, custom user interfaces.
+
+Qt Declarative UI provides a declarative framework for building highly dynamic, custom
+user interfaces. Declarative UI helps programmers and designers collaborate to build
+the animation rich, fluid user interfaces that are becoming common in portable
+consumer devices, such as mobile phones, media players, set-top boxes and netbooks.
+The Qt Declarative module provides an engine for interpreting the declarative QML
+language, and a rich set of \l {QML Elements}{QML elements} that can be used
+from QML.
+
+QML is an extension to \l {http://www.ecma-international.org/publications/standards/Ecma-262.htm}
+{JavaScript}, that provides a mechanism to declaratively build an object tree
+of QML elements. QML improves the integration between JavaScript and Qt's
+existing QObject based type system, adds support for automatic
+\l {Property Binding}{property bindings} and provides \l {Network Transparency}{network transparency} at the language
+level.
+
+The QML elements are a sophisticated set of graphical and behavioral building
+blocks. These different elements are combined together in \l {QML Documents}{QML documents} to build components
+ranging in complexity from simple buttons and sliders, to complete
+internet-enabled applications like a \l {http://www.flickr.com}{Flickr} photo browser.
+
+Qt Declarative builds on \l {QML for Qt programmers}{Qt's existing strengths}.
+QML can be be used to incrementally extend an existing application or to build
+completely new applications. QML is fully \l {Extending QML}{extensible from C++}.
+
+\section1 Getting Started:
+\list
+\o \l {Introduction to the QML language}
+\o \l {Tutorial}{Tutorial: 'Hello World'}
+\o \l {advtutorial.html}{Tutorial: 'Same Game'}
+\o \l {QML Examples and Walkthroughs}
+\o \l {Using QML in C++ Applications}
+\endlist
+
+\section1 Core QML Features:
+\list
+\o \l {QML Documents}
+\o \l {Property Binding}
+\o \l {JavaScript Blocks}
+\o \l {QML Scope}
+\o \l {Network Transparency}
+\o \l {Data Models}
+\o \l {anchor-layout.html}{Anchor-based Layout}
+\o \l {qmlstates.html}{States}
+\o \l {qmlanimation.html}{Animation}
+\o \l {qmlmodules.html}{Modules}
+\o \l {qmlfocus.html}{Keyboard Focus}
+\o \l {Extending types from QML}
+\o \l {Dynamic Object Creation}
+\endlist
+
+\section1 Reference:
+\list
+\o \l {QML Elements}
+\o \l {QML Global Object}
+\o \l {Extending QML}
+\o \l {QML Internationalization}
+\o \l {QtDeclarative Module}
+\o \l {Debugging QML}
+\endlist
+*/
diff --git a/doc/src/declarative/dynamicobjects.qdoc b/doc/src/declarative/dynamicobjects.qdoc
new file mode 100644
index 0000000..fede2cd
--- /dev/null
+++ b/doc/src/declarative/dynamicobjects.qdoc
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmldynamicobjects.html
+\title Dynamic Object Creation
+
+QML has some support for dynamically loading and managing QML objects from
+within Javascript blocks. It is preferable to use the existing QML elements for
+dynamic object management wherever possible; these are \l{Loader},
+\l{Repeater}, \l{ListView}, \l{GridView} and \l{PathView}. It is also possible
+to dynamically create and manage objects from C++, and this is preferable for
+hybrid QML/C++ applications - see \l{Using QML in C++ Applications}.
+Dynamically creating and managing objects from
+within Javascript blocks is intended for when none of the existing QML elements
+fit the needs of your application, and you do not desire for your application
+to involve C++ code.
+
+\section1 Creating Objects Dynamically
+There are two ways of creating objects dynamically. You can either create
+a component which instantiates items, or create an item from a string of QML.
+Creating a component is better for the situation where you have a predefined
+item which you want to manage dynamic instances of, and creating an item from
+a string of QML is intended for when the QML itself is generated at runtime.
+
+If you have a component specified in a QML file, you can dynamically load it with
+the createComponent function on the \l{QML Global Object}.
+This function takes the URL of the QML file as its only argument and returns
+a component object which can be used to create and load that QML file.
+
+You can also create a component by placing your QML inside a Component element.
+Referencing that component element by id will be the same as referencing the variable
+which you save the result of createComponent into.
+
+Once you have a component you can use its createObject method to create an instance of
+the component. Example QML script is below. Remember that QML files that might be loaded
+ over the network cannot be expected to be ready immediately.
+ \code
+ var component;
+ var sprite;
+ function finishCreation(){
+ if(component.isReady()){
+ sprite = component.createObject();
+ if(sprite == 0){
+ // Error Handling
+ }else{
+ sprite.parent = page;
+ sprite.x = 200;
+ //...
+ }
+ }else if(component.isError()){
+ // Error Handling
+ }
+ }
+
+ component = createComponent("Sprite.qml");
+ if(component.isReady()){
+ finishCreation();
+ }else{
+ component.statusChanged.connect(finishCreation);
+ }
+ \endcode
+
+ If you are certain the files will be local, you could simplify to
+
+ \code
+ component = createComponent("Sprite.qml");
+ sprite = component.createObject();
+ if(sprite == 0){
+ // Error Handling
+ console.log(component.errorsString());
+ }else{
+ sprite.parent = page;
+ sprite.x = 200;
+ //...
+ }
+ \endcode
+
+After creating the item, remember to set its parent to an item within the scene.
+Otherwise your dynamically created item will not appear in the scene. When using files with relative paths, the path should
+be relative to the file where createComponent is executed.
+
+If the QML does not exist until runtime, you can create a QML item from
+a string of QML using the createQmlObject function, as in the following example:
+
+ \code
+ newObject = createQmlObject('import Qt 4.6; Rectangle {color: "red"; width: 20; height: 20}',
+ targetItem, "dynamicSnippet1");
+ \endcode
+The first argument is the string of QML to create. Just like in a new file, you will need to
+import any types you wish to use. For importing files with relative paths, the path should
+be relative to the file where the item in the second argument is defined. Remember to set the parent after
+creating the item. The second argument is another item in the scene, and the new item is created
+in the same QML Context as this item. The third argument is the file path associated with this
+item, which is used for error reporting.
+
+\section1 Maintaining Dynamically Created Objects
+
+Dynamically created objects may be used the same as other objects, however they
+will not have an id in QML.
+
+A restriction which you need to manage with dynamically created items,
+is that the creation context must outlive the
+created item. The creation context is the QmlContext in which createComponent
+was called, or the context in which the Component element, or the item used as the
+second argument to createQmlObject, was specified. If the creation
+context is destroyed before the dynamic item is, then bindings in the dynamic item will
+fail to work.
+
+\section1 Deleting Objects Dynamically
+You should generally avoid dynamically deleting objects that you did not
+dynamically create. In many UIs, it is sufficient to set the opacity to 0 or
+to move the item off of the edge of the screen. If you have lots of dynamically
+created items however, deleting them when they are no longer used will provide
+a worthwhile performance benefit. Note that you should never manually delete
+items which were dynamically created by QML Elements such as \l{Loader}.
+
+To manually delete a QML item, call its destroy method. This method has one
+argument, which is an approximate delay in ms and which defaults to zero. This
+allows you to wait until the completion of an animation or transition. An example:
+
+\code
+ Component{ id:fadesOut
+ Rectangle{
+ id: rect
+ width: 40; height: 40;
+ opacity: NumberAnimation{from:1; to:0; duration: 1000;}
+ Component.onCompleted: rect.destroy(1000);
+ }
+ }
+ function createFadesOut(parentItem)
+ {
+ var object = fadesOut.createObject();
+ object.parent = parentItem;
+ }
+\endcode
+In the above example, the dynamically created rectangle calls destroy as soon as it's created,
+ but delays long enough for its fade out animation to play.
+
+*/
+
diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc
new file mode 100644
index 0000000..cfbabf2
--- /dev/null
+++ b/doc/src/declarative/elements.qdoc
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlelements.html
+\target elements
+\title QML Elements
+
+The following table lists the QML elements provided by the Qt Declarative module.
+
+\bold {Standard Qt Declarative Elements}
+
+\table 80%
+\header
+\o \bold {States}
+\o \bold {Animation and Transitions}
+\o \bold {Working with Data}
+\o \bold {Utility}
+\row
+
+\o
+\list
+\o \l State
+\o \l PropertyChanges
+\o \l StateGroup
+\o \l ParentChange (Item-specific)
+\o \l StateChangeScript (Item-specific)
+\o \l AnchorChanges (Item-specific)
+\endlist
+
+\o
+\list
+\o \l PropertyAnimation
+\o \l NumberAnimation
+\o \l ColorAnimation
+\o \l SequentialAnimation
+\o \l ParallelAnimation
+\o \l PauseAnimation
+\o \l PropertyAction
+\o \l ParentAction
+\o \l ScriptAction
+\o \l Transition
+\o \l SpringFollow
+\o \l EaseFollow
+\o \l Behavior
+\endlist
+
+\o
+\list
+\o \l Binding
+\o \l ListModel, \l ListElement
+\o \l VisualItemModel
+\o \l XmlListModel and XmlRole
+\o \l DateTimeFormatter
+\o \l NumberFormatter
+\endlist
+
+\o
+\list
+\o \l Script
+\o \l Connection
+\o \l Component
+\o \l Timer
+\o \l QtObject
+\endlist
+\endtable
+
+\bold {QML Items}
+
+\table 80%
+\header
+\o \bold {Basic Visual Items}
+\o \bold {Basic Interaction Items}
+\o \bold {Widgets}
+\o \bold {Utility}
+
+\row
+\o
+\list
+\o \l Item
+\o \l Rectangle
+\o \l Image
+\o \l BorderImage
+\o \l Text
+\o \l TextInput
+\o \l TextEdit
+\endlist
+
+\o
+\list
+\o \l MouseRegion
+\o \l FocusScope
+\endlist
+
+\o
+\list
+\o \l Flickable
+\o \l Flipable
+\o \l WebView
+\endlist
+
+\o
+\list
+\o \l Loader
+\o \l Repeater
+\o \l SystemPalette
+\o \l GraphicsObjectContainer
+\endlist
+
+\header
+\o \bold {Views}
+\o \bold {Positioners}
+\o \bold {Transforms}
+\o \bold {Effects}
+
+\row
+\o
+
+\target xmlViews
+\list
+\o \l ListView
+\o \l GridView
+\o \l PathView
+ \list
+ \o \l Path
+ \list
+ \o \l PathLine
+ \o \l PathQuad
+ \o \l PathCubic
+ \o \l PathAttribute
+ \o \l PathPercent
+ \endlist
+ \endlist
+\endlist
+
+\o
+\list
+\o \l Column
+\o \l Row
+\o \l Grid
+\endlist
+
+\o
+\list
+\o \l Scale
+\o \l Rotation
+\endlist
+
+\o
+\list
+\o \l Blur
+\o \l Colorize
+\o \l DropShadow
+\o \l Opacity
+\o \l Particles
+ \list
+ \o \l ParticleMotionLinear
+ \o \l ParticleMotionGravity
+ \o \l ParticleMotionWander
+ \endlist
+\endlist
+\endtable
+
+*/
diff --git a/doc/src/declarative/example-slideswitch.qdoc b/doc/src/declarative/example-slideswitch.qdoc
new file mode 100644
index 0000000..41a8574
--- /dev/null
+++ b/doc/src/declarative/example-slideswitch.qdoc
@@ -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$
+**
+****************************************************************************/
+
+/*!
+\page qmlexampletoggleswitch.html
+\title QML Example - Toggle Switch
+
+This example shows how to create a reusable switch component in QML.
+
+The code for this example can be found in the \c $QTDIR/examples/declarative/slideswitch directory.
+
+\section1 Overview
+
+The elements that composed the switch are:
+
+\list
+\o a \c on property (the interface to interact with the switch),
+\o two images (the background image and the knob),
+\o two mouse regions for user interation (on the background image and on the knob),
+\o two states (a \e on state and a \e off state),
+\o two functions or slots to react to the user interation (\c toggle() and \c dorelease()),
+\o and a transition that describe how to go from one state to the other.
+\endlist
+
+\section1 Switch.qml
+\snippet examples/declarative/slideswitch/content/Switch.qml 0
+
+\section1 Walkthrough
+
+\section2 Interface
+\snippet examples/declarative/slideswitch/content/Switch.qml 1
+
+This property is the interface of the switch. By default, the switch is off and this property is \c false.
+It can be used to activate/disactivate the switch or to query its current state.
+
+In this example:
+
+\qml
+Switch { id: mySwitch; on: true }
+Text { text: "The switch is on"; visible: mySwitch.on == true }
+\endqml
+
+the text will only be visible when the switch is on.
+
+\section2 Images and user interaction
+\snippet examples/declarative/slideswitch/content/Switch.qml 4
+
+First, we create the background image of the switch.
+In order for the switch to toggle when the user clicks on the background, we add a \l{MouseRegion} as a child item of the image.
+A \c MouseRegion has a \c onClicked property that is triggered when the item is clicked. For the moment we will just call a
+\c toggle() function. We will see what this function does in a moment.
+
+\snippet examples/declarative/slideswitch/content/Switch.qml 5
+
+Then, we place the image of the knob on top of the background.
+The interaction here is a little more complex. We want the knob to move with the finger when it is clicked. That is what the \c drag
+property of the \c MouseRegion is for. We also want to toggle the switch if the knob is released between state. We handle this case
+in the \c dorelease() function that is called in the \c onReleased property.
+
+\section2 States
+\snippet examples/declarative/slideswitch/content/Switch.qml 6
+
+We define the two states of the switch:
+\list
+\o In the \e on state the knob is on the right (\c x position is 78) and the \c on property is \c true.
+\o In the \e off state the knob is on the left (\c x position is 1) and the \c on property is \c false.
+\endlist
+
+For more information on states see \l{qmlstates}{QML States}.
+
+\section2 Functions
+
+We add two JavaScript functions to our switch:
+
+\snippet examples/declarative/slideswitch/content/Switch.qml 2
+
+This first function is called when the background image or the knob are clicked. We simply want the switch to toggle between the two
+states (\e on and \e off).
+
+
+\snippet examples/declarative/slideswitch/content/Switch.qml 3
+
+This second function is called when the knob is released and we want to make sure that the knob does not end up between states
+(neither \e on nor \e off). If it is the case call the \c toggle() function otherwise we do nothing.
+
+For more information on scripts see \l{qmlecmascript.html}{JavaScript Blocks}.
+
+\section2 Transition
+\snippet examples/declarative/slideswitch/content/Switch.qml 7
+
+At this point, when the switch toggles between the two states the knob will instantly change its \c x position between 1 and 78.
+In order for the the knob to move smoothly we add a transition that will animate the \c x property with an easing curve for a duration of 200ms.
+
+For more information on transitions see \l{state-transitions}{QML Transitions}.
+
+\section1 Usage
+The switch can be used in a QML file, like this:
+\snippet examples/declarative/slideswitch/slideswitch.qml 0
+*/
diff --git a/doc/src/declarative/examples.qdoc b/doc/src/declarative/examples.qdoc
new file mode 100644
index 0000000..3288e17
--- /dev/null
+++ b/doc/src/declarative/examples.qdoc
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlexamples.html
+\title QML Examples and Walkthroughs
+
+\section1 Running Examples and Demos
+
+You can find many simple examples in the \c examples/declarative
+sub-directory that show how to use various aspects of QML. In addition, the
+\c demos/declarative sub-directory contains more sophisticated demos of large
+applications. These demos are intended to show integrated functionality
+rather than being instructive on specifice elements.
+
+To run the examples and demos, use the included \l {qmlviewer}{qmlviewer}
+application. It has some useful options, revealed by:
+
+\code
+ bin/qmlviewer -help
+\endcode
+
+For example, from your build directory, run:
+
+\code
+ bin/qmlviewer $QTDIR/demos/declarative/flickr/flickr-desktop.qml
+\endcode
+or
+\code
+ bin/qmlviewer $QTDIR/demos/declarative/samegame/samegame.qml
+\endcode
+
+\section1 Examples
+
+These will be documented, and demonstrate how to achieve various things in QML.
+
+\table
+\row
+ \o Elastic Dial
+ \o \image dial-example.gif
+\row
+ \o \l{qmlexampletoggleswitch.html}{Toggle Switch}
+ \o \image switch-example.gif
+\row
+ \o \l{Advanced Tutorial}{SameGame}
+ \o \image declarative-adv-tutorial4.gif
+\endtable
+
+*/
diff --git a/doc/src/declarative/extending-examples.qdoc b/doc/src/declarative/extending-examples.qdoc
new file mode 100644
index 0000000..17bef4e
--- /dev/null
+++ b/doc/src/declarative/extending-examples.qdoc
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** 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 declarative/extending/adding
+\title Extending QML - Adding Types Example
+
+The Adding Types Example shows how to add a new element type, \c Person, to QML.
+The \c Person type can be used from QML like this:
+
+\snippet examples/declarative/extending/adding/example.qml 0
+
+\section1 Declare the Person class
+
+All QML elements map to C++ types. Here we declare a basic C++ Person class
+with the two properties we want accessible on the QML type - name and shoeSize.
+Although in this example we use the same name for the C++ class as the QML
+element, the C++ class can be named differently, or appear in a namespace.
+
+\snippet examples/declarative/extending/adding/person.h 0
+
+Following the class declaration, we include the QML_DECLARE_TYPE() macro. This
+is necessary to declare the type to QML. It also includes the logic necessary
+to expose the class to Qt's meta system - that is, it includes the
+Q_DECLARE_METATYPE() functionality.
+
+\section1 Define the Person class
+
+\snippet examples/declarative/extending/adding/person.cpp 0
+
+The Person class implementation is quite basic. The property accessors simply
+return members of the object instance.
+
+The implementation must also include the QML_DEFINE_TYPE() macro. This macro
+registers the Person class with QML as a type in the People library version 1.0,
+and defines the mapping between the C++ and QML class names.
+
+\section1 Running the example
+
+The main.cpp file in the example includes a simple shell application that
+loads and runs the QML snippet shown at the beginning of this page.
+*/
+
+/*!
+\example declarative/extending/properties
+\title Extending QML - Object and List Property Types Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+The Object and List Property Types example shows how to add object and list
+properties in QML. This example adds a BirthdayParty element that specifies
+a birthday party, consisting of a celebrant and a list of guests. People are
+specified using the People QML type built in the previous example.
+
+\snippet examples/declarative/extending/properties/example.qml 0
+
+\section1 Declare the BirthdayParty
+
+The BirthdayParty class is declared like this:
+
+\snippet examples/declarative/extending/properties/birthdayparty.h 0
+\snippet examples/declarative/extending/properties/birthdayparty.h 1
+\snippet examples/declarative/extending/properties/birthdayparty.h 2
+\snippet examples/declarative/extending/properties/birthdayparty.h 3
+
+The class contains a member to store the celebrant object, and also a
+QmlConcreteList<Person *> member.
+
+In QML, the type of a list properties - and the guests property is a list of
+people - are all of type QmlList<T *>*. QmlList is an abstract list interface
+that allows a developer to react to QML accessing and modifying the contents of
+the list. This is useful for implementing "virtual lists" or other advanced
+scenarios, but can't be used directly for the common case of just wanting a
+regular list of things. For this a concrete implementation, QmlConcreteList, is
+provided and that is used here.
+
+\section2 Define the BirthdayParty
+
+The implementation of BirthdayParty property accessors is straight forward.
+
+\snippet examples/declarative/extending/properties/birthdayparty.cpp 0
+
+\section1 Running the example
+
+The main.cpp file in the example includes a simple shell application that
+loads and runs the QML snippet shown at the beginning of this page.
+*/
+
+/*!
+\example declarative/extending/coercion
+\title Extending QML - Inheritance and Coercion Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Object and List Property Types Example}
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+The Inheritance and Coercion Example shows how to use base classes to assign
+elements of more than one type to a property. It specializes the Person element
+developed in the previous examples into two elements - a \c Boy and a \c Girl.
+
+\snippet examples/declarative/extending/coercion/example.qml 0
+
+\section1 Declare Boy and Girl
+
+\snippet examples/declarative/extending/coercion/person.h 0
+
+The Person class remains unaltered in this example and the Boy and Girl C++
+classes are trivial extensions of it. As an example, the inheritance used here
+is a little contrived, but in real applications it is likely that the two
+extensions would add additional properties or modify the Person classes
+behavior.
+
+\section2 Define People as a base class
+
+The implementation of the People class itself has not changed since the the
+previous example. However, as we have repurposed the People class as a common
+base for Boy and Girl, we want to prevent it from being instantiated from QML
+directly - an explicit Boy or Girl should be instantiated instead.
+
+\snippet examples/declarative/extending/coercion/person.cpp 0
+
+While we want to disallow instantiating Person from within QML, it still needs
+to be registered with the QML engine, so that it can be used as a property type
+and other types can be coerced to it. To register a type, without defining a
+named mapping into QML, we use the QML_DEFINE_NOCREATE_TYPE() macro instead of
+the QML_DEFINE_TYPE() macro used previously.
+
+\section2 Define Boy and Girl
+
+The implementation of Boy and Girl are trivial.
+
+\snippet examples/declarative/extending/coercion/person.cpp 1
+
+All that is necessary is to implement the constructor, and to register the types
+and their QML name with the QML engine.
+
+\section1 Running the example
+
+The BirthdayParty element has not changed since the previous example. The
+celebrant and guests property still use the People type.
+
+\snippet examples/declarative/extending/coercion/birthdayparty.h 0
+
+However, as all three types, Person, Boy and Girl, have been registered with the
+QML system, on assignment QML automatically (and type-safely) converts the Boy
+and Girl objects into a Person.
+
+The main.cpp file in the example includes a simple shell application that
+loads and runs the QML snippet shown at the beginning of this page.
+*/
+
+/*!
+\example declarative/extending/default
+\title Extending QML - Default Property Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Inheritance and Coercion Example}
+\o \l {Extending QML - Object and List Property Types Example}
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+The Default Property Example is a minor modification of the
+\l {Extending QML - Inheritance and Coercion Example} that simplifies the
+specification of a BirthdayParty through the use of a default property.
+
+\snippet examples/declarative/extending/default/example.qml 0
+
+\section1 Declaring the BirthdayParty class
+
+The only difference between this example and the last, is the addition of the
+\c DefaultProperty class info annotation.
+
+\snippet examples/declarative/extending/default/birthdayparty.h 0
+
+The default property specifies the property to assign to whenever an explicit
+property is not specified, in the case of the BirthdayParty element the guest
+property. It is purely a syntactic simplification, the behavior is identical
+to specifying the property by name, but it can add a more natural feel in many
+situations. The default property must be either an object or list property.
+
+\section1 Running the example
+
+The main.cpp file in the example includes a simple shell application that
+loads and runs the QML snippet shown at the beginning of this page.
+*/
+
+/*!
+\example declarative/extending/grouped
+\title Extending QML - Grouped Properties Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Default Property Example}
+\o \l {Extending QML - Inheritance and Coercion Example}
+\o \l {Extending QML - Object and List Property Types Example}
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+*/
+
+/*!
+\example declarative/extending/grouped
+\title Extending QML - Attached Properties Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Grouped Properties Example}
+\o \l {Extending QML - Default Property Example}
+\o \l {Extending QML - Inheritance and Coercion Example}
+\o \l {Extending QML - Object and List Property Types Example}
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+*/
+
+/*!
+\example declarative/extending/signal
+\title Extending QML - Signal Support Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Attached Properties Example}
+\o \l {Extending QML - Grouped Properties Example}
+\o \l {Extending QML - Default Property Example}
+\o \l {Extending QML - Inheritance and Coercion Example}
+\o \l {Extending QML - Object and List Property Types Example}
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+*/
+
+/*!
+\example declarative/extending/valuesource
+\title Extending QML - Property Value Source Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Signal Support Example}
+\o \l {Extending QML - Attached Properties Example}
+\o \l {Extending QML - Grouped Properties Example}
+\o \l {Extending QML - Default Property Example}
+\o \l {Extending QML - Inheritance and Coercion Example}
+\o \l {Extending QML - Object and List Property Types Example}
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+*/
+
+/*!
+\example declarative/extending/binding
+\title Extending QML - Binding Example
+
+This example builds on:
+\list
+\o \l {Extending QML - Property Value Source Example}
+\o \l {Extending QML - Signal Support Example}
+\o \l {Extending QML - Attached Properties Example}
+\o \l {Extending QML - Grouped Properties Example}
+\o \l {Extending QML - Default Property Example}
+\o \l {Extending QML - Inheritance and Coercion Example}
+\o \l {Extending QML - Object and List Property Types Example}
+\o \l {Extending QML - Adding Types Example}
+\endlist
+
+*/
diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc
new file mode 100644
index 0000000..3b9c7f3
--- /dev/null
+++ b/doc/src/declarative/extending.qdoc
@@ -0,0 +1,967 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qml-extending.html
+\title Extending QML
+
+The QML syntax declaratively describes how to construct an in memory object
+tree. In Qt, QML is mainly used to describe a visual scene graph, but it is
+not conceptually limited to this: the QML format is an abstract description of
+any object tree. All the QML element types included in Qt are implemented using
+the C++ extension mechanisms describe on this page. Programmers can use these
+APIs to add new types that interact with the existing Qt types, or to repurpose
+QML for their own independent use.
+
+\tableofcontents
+
+\section1 Adding Types
+\target adding-types
+
+\snippet examples/declarative/extending/adding/example.qml 0
+
+The QML snippet shown above instantiates one \c Person instance and sets
+the name and shoeSize properties on it. Everything in QML ultimately comes down
+to either instantiating an object instance, or assigning a property a value.
+QML relies heavily on Qt's meta object system and can only instantiate classes
+that derive from QObject.
+
+The QML engine has no intrinsic knowledge of any class types. Instead the
+programmer must define the C++ types, and their corresponding QML name.
+
+Custom C++ types are made available to QML using these two macros:
+
+\quotation
+\code
+#define QML_DECLARE_TYPE(T)
+#define QML_DEFINE_TYPE(URI,VMAJ,VMIN,QmlName,T)
+\endcode
+
+Register the C++ type \a T with the QML system, and make it available in QML
+under the name \a QmlName in library URI version VMAJ.VMIN.
+\a T and \a QmlName may be the same.
+
+Generally the QML_DECLARE_TYPE() macro should be included immediately following
+the type declaration (usually in its header file), and the QML_DEFINE_TYPE()
+macro in the implementation file. QML_DEFINE_TYPE() must not be present in
+a header file.
+
+Type \a T must be a concrete type that inherits QObject and has a default
+constructor.
+\endquotation
+
+Types can be registered by libraries (such as Qt does), application code,
+or by plugins (see QmlModulePlugin).
+
+Once registered, all of the \l {Qt's Property System}{properties} of a supported
+type are available for use within QML. QML has intrinsic support for properties
+of these types:
+
+\list
+\o bool
+\o unsigned int, int
+\o float, double, qreal
+\o QString
+\o QUrl
+\o QColor
+\o QDate, QTime, QDateTime
+\o QPoint, QPointF
+\o QSize, QSizeF
+\o QRect, QRectF
+\o QVariant
+\endlist
+
+QML is typesafe. Attempting to assign an invalid value to a property will
+generate an error. For example, assuming the name property of the \c Person
+element had a type of QString, this would cause an error:
+
+\code
+Person {
+ // Will NOT work
+ name: 12
+}
+\endcode
+
+\l {Extending QML - Adding Types Example} shows the complete code used to create
+the \c Person type.
+
+\section1 Object and List Property Types
+
+\snippet examples/declarative/extending/properties/example.qml 0
+
+The QML snippet shown above assigns a \c Person object to the \c BirthdayParty's
+celebrant property, and assigns three \c Person objects to the guests property.
+
+QML can set properties of types that are more complex than basic intrinsics like
+integers and strings. Properties can also be object pointers, Qt interface
+pointers, lists of object points, and lists of Qt interface pointers. As QML
+is typesafe it ensures that only valid types are assigned to these properties,
+just like it does for primitive types.
+
+Properties that are pointers to objects or Qt interfaces are declared with the
+Q_PROPERTY() macro, just like other properties. The celebrant property
+declaration looks like this:
+
+\snippet examples/declarative/extending/properties/birthdayparty.h 1
+
+As long as the property type, in this case Person, is registered with QML the
+property can be assigned.
+
+QML also supports assigning Qt interfaces. To assign to a property whose type
+is a Qt interface pointer, the interface must also be registered with QML. As
+they cannot be instantiated directly, registering a Qt interface is different
+from registering a new QML type. The following macros are used instead:
+
+\quotation
+\code
+ #define QML_DECLARE_INTERFACE(T)
+ #define QML_DEFINE_INTERFACE(T)
+\endcode
+
+Register the C++ interface \a T with the QML system.
+
+Generally the QML_DECLARE_INTERFACE() macro should be included immediately
+following the interface declaration (usually in its header file), and the
+QML_DEFINE_INTERFACE() macro in an implementation file. QML_DEFINE_INTERFACE()
+must not be present in a header file.
+
+Following registration, QML can coerce objects that implement this interface
+for assignment to appropriately typed properties.
+\endquotation
+
+The guests property is a list of \c Person objects. Properties that are lists
+of objects or Qt interfaces are also declared with the Q_PROPERTY() macro, just
+like other properties. List properties must have the type \c {QmlList<T *>*}.
+As with object properties, the type \a T must be registered with QML.
+
+The guest property declaration looks like this:
+
+\snippet examples/declarative/extending/properties/birthdayparty.h 2
+
+\l {Extending QML - Object and List Property Types Example} shows the complete
+code used to create the \c BirthdayParty type.
+
+\section1 Inheritance and Coercion
+
+\snippet examples/declarative/extending/coercion/example.qml 0
+
+The QML snippet shown above assigns a \c Boy object to the \c BirthdayParty's
+celebrant property, and assigns three other objects to the guests property.
+
+QML supports C++ inheritance heirarchies and can freely coerce between known,
+valid object types. This enables the creation of common base classes that allow
+the assignment of specialized classes to object or list properties. In the
+snippet shown, both the celebrant and the guests properties retain the Person
+type used in the previous section, but the assignment is valid as both the Boy
+and Girl objects inherit from Person.
+
+To assign to a property, the property's type must have been registered with QML.
+Both the QML_DEFINE_TYPE() and QML_DEFINE_INTERFACE() macros already shown can
+be used to register a type with QML. Additionally, if a type that acts purely
+as a base class that cannot be instantiated from QML needs to be
+registered these macros can be used:
+
+\quotation
+\code
+ #define QML_DECLARE_TYPE(T)
+ #define QML_DEFINE_NOCREATE_TYPE(T)
+\endcode
+
+Register the C++ type \a T with the QML system. QML_DEFINE_NOCREATE_TYPE()
+differs from QML_DEFINE_TYPE() in that it does not define a mapping between the
+C++ class and a QML element name, so the type is not instantiable from QML, but
+it is available for type coercion.
+
+Generally the QML_DECLARE_TYPE() macro should be included immediately following
+the type declaration (usually in its header file), and the
+QML_DEFINE_NOCREATE_TYPE() macro in the implementation file.
+QML_DEFINE_NOCREATE_TYPE() must not be present in a header file.
+
+Type \a T must inherit QObject, but there are no restrictions on whether it is
+concrete or the signature of its constructor.
+\endquotation
+
+QML will automatically coerce C++ types when assigning to either an object
+property, or to a list property. Only if coercion fails does an assignment
+error occur.
+
+\l {Extending QML - Inheritance and Coercion Example} shows the complete
+code used to create the \c Boy and \c Girl types.
+
+\section1 Default Property
+
+\snippet examples/declarative/extending/default/example.qml 0
+
+The QML snippet shown above assigns a collection of objects to the
+\c BirthdayParty's default property.
+
+The default property is a syntactic convenience that allows a type designer to
+specify a single property as the type's default. The default property is
+assigned to whenever no explicit property is specified. As a convenience, it is
+behaviorally identical to assigning the default property explicitly by name.
+
+From C++, type designers mark the default property using a Q_CLASSINFO()
+annotation:
+
+\quotation
+\code
+Q_CLASSINFO("DefaultProperty", "property")
+\endcode
+
+Mark \a property as the class's default property. \a property must be either
+an object property, or a list property.
+
+A default property is optional. A derived class inherits its base class's
+default property, but may override it in its own declaration. \a property can
+refer to a property declared in the class itself, or a property inherited from a
+base class.
+\endquotation
+
+\l {Extending QML - Default Property Example} shows the complete code used to
+specify a default property.
+
+\section1 Grouped Properties
+
+\snippet examples/declarative/extending/grouped/example.qml 1
+
+The QML snippet shown above assigns a number properties to the \c Boy object,
+including four properties using the grouped property syntax.
+
+Grouped properties collect similar properties together into a single named
+block. Grouped properties can be used to present a nicer API to developers, and
+may also simplify the implementation of common property collections across
+different types through implementation reuse.
+
+A grouped property block is implemented as a read-only object property. The
+shoe property shown is declared like this:
+
+\snippet examples/declarative/extending/grouped/person.h 1
+
+The ShoeDescription type declares the properties available to the grouped
+property block - in this case the size, color, brand and price properties.
+
+Grouped property blocks may declared and accessed be recusively.
+
+\l {Extending QML - Grouped Properties Example} shows the complete code used to
+implement the \c shoe property grouping.
+
+\section1 Attached Properties
+
+\snippet examples/declarative/extending/attached/example.qml 1
+
+The QML snippet shown above assigns the rsvp property using the attached
+property syntax.
+
+Attached properties allow unrelated types to annotate other types with some
+additional properties, generally for their own use. Attached properties are
+identified through the use of the attacher type name, in the case shown
+\c BirthdayParty, as a suffix to the property name.
+
+In the example shown, \c BirthdayParty is called the attaching type, and the
+Boy instance the attachee object instance.
+
+For the attaching type, an attached property block is implemented as a new
+QObject derived type, called the attachment object. The properties on the
+attachment object are those that become available for use as the attached
+property block.
+
+Any QML type can become an attaching type by declaring the
+\c qmlAttachedProperties() public function and declaring that the class has
+QML_HAS_ATTACHED_PROPERTIES:
+
+\quotation
+\code
+class MyType : public QObject {
+ Q_OBJECT
+public:
+
+ ...
+
+ static AttachedPropertiesType *qmlAttachedProperties(QObject *object);
+};
+
+QML_DECLARE_TYPEINFO(MyType, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(MyType)
+\endcode
+Return an attachment object, of type \a AttachedPropertiesType, for the
+attachee \a object instance. It is customary, though not strictly required, for
+the attachment object to be parented to \a object to prevent memory leaks.
+
+\a AttachedPropertiesType must be a QObject derived type. The properties on
+this type will be accessible through the attached properties syntax.
+
+This method will be called at most once for each attachee object instance. The
+QML engine will cache the returned instance pointer for subsequent attached
+property accesses. Consequently the attachment object may not be deleted until
+\a object is destroyed.
+\endquotation
+
+Conceptually, attached properties are a \e type exporting a set of additional
+properties that can be set on \e any other object instance. Attached properties
+cannot be limited to only attaching to a sub-set of object instances, although
+their effect may be so limited.
+
+For example, a common usage scenario is for a type to enhance the properties
+available to its children in order to gather instance specific data. Here we
+add a rsvp field to all the guests coming to a birthday party:
+\code
+BirthdayParty {
+ Boy { BirthdayParty.rsvp: "2009-06-01" }
+}
+\endcode
+However, as a type cannot limit the instances to which the attachment object
+must attach, the following is also allowed, even though adding a birthday party
+rsvp in this context will have no effect.
+\code
+GraduationParty {
+ Boy { BirthdayParty.rsvp: "2009-06-01" }
+}
+\endcode
+
+From C++, including the attaching type implementation, the attachment object for
+an instance can be accessed using the following method:
+
+\quotation
+\code
+template<typename T>
+QObject *qmlAttachedPropertiesObject<T>(QObject *attachee, bool create = true);
+\endcode
+Returns the attachment object attached to \a attachee by the attaching type
+\a T. If type \a T is not a valid attaching type, this method always returns 0.
+
+If \a create is true, a valid attachment object will always be returned,
+creating it if it does not already exist. If \a create is false, the attachment
+object will only be returned if it has previously been created.
+\endquotation
+
+\l {Extending QML - Attached Properties Example} shows the complete code used to
+implement the rsvp attached property.
+
+\section1 Signal Support
+
+\snippet examples/declarative/extending/signal/example.qml 0
+\snippet examples/declarative/extending/signal/example.qml 1
+
+The QML snippet shown above associates the evaluation of a JavaScript expression
+with the emission of a Qt signal.
+
+All Qt signals on a registered class become available as special "signal
+properties" within QML to which the user can assign a single JavaScript
+expression. The signal property's name is a transformed version of the Qt
+signal name: "on" is prepended, and the first letter of the signal name upper
+cased. For example, the signal used in the example above has the following
+C++ signature:
+
+\snippet examples/declarative/extending/signal/birthdayparty.h 0
+
+In classes with multiple signals with the same name, only the final signal
+is accessible as a signal property. Although QML provides an element,
+\l Connection, for accessing the other signals it is less elegant. For the best
+QML API, class developers should avoid overloading signal names.
+
+Signal parameters become accessible by name to the assigned script. An
+unnamed parameter cannot be accessed, so care should be taken to name all the
+signal parameters in the C++ class declaration. The intrinsic types
+listed in \l {Adding Types}, as well registered object types are permitted as
+signal parameter types. Using other types is not an error, but the parameter
+value will not be accessible from script.
+
+\l {Extending QML - Signal Support Example} shows the complete code used to
+implement the onPartyStarted signal property.
+
+\section1 Property Value Sources
+
+\snippet examples/declarative/extending/valuesource/example.qml 0
+\snippet examples/declarative/extending/valuesource/example.qml 1
+
+The QML snippet shown above assigns a property value to the speaker property.
+A property value source generates a value for a property that changes over time.
+
+Property value sources are most commonly used to do animation. Rather than
+constructing an animation object and manually setting the animation's "target"
+property, a property value source can be assigned directly to a property of any
+type and automatically set up this association.
+
+The example shown here is rather contrived: the speaker property of the
+BirthdayParty object is a string that is printed every time it is assigned and
+the HappyBirthday value source generates the lyrics of the song
+"Happy Birthday".
+
+\snippet examples/declarative/extending/valuesource/birthdayparty.h 0
+
+Normally, assigning an object to a string property would not be allowed. In
+the case of a property value source, rather than assigning the object instance
+itself, the QML engine sets up an association between the value source and
+the property.
+
+Property value sources are special types that derive from the
+QmlPropertyValueSource base class. This base class contains a single method,
+QmlPropertyValueSource::setTarget(), that the QML engine invokes when
+associating the property value source with a property. The relevant part of
+the HappyBirthday type declaration looks like this:
+
+\snippet examples/declarative/extending/valuesource/happybirthday.h 0
+\snippet examples/declarative/extending/valuesource/happybirthday.h 1
+\snippet examples/declarative/extending/valuesource/happybirthday.h 2
+
+In all other respects, property value sources are regular QML types. They must
+be registered with the QML engine using the same macros as other types, and can
+contain properties, signals and methods just like other types.
+
+When a property value source object is assigned to a property, QML first tries
+to assign it normally, as though it were a regular QML type. Only if this
+assignment fails does the engine call the setTarget() method. This allows
+the type to also be used in contexts other than just as a value source.
+
+\l {Extending QML - Property Value Source Example} shows the complete code used
+implement the HappyBirthday property value source.
+
+\section1 Property Binding
+
+\snippet examples/declarative/extending/binding/example.qml 0
+\snippet examples/declarative/extending/binding/example.qml 1
+
+The QML snippet shown above uses a property binding to ensure the
+HappyBirthday's name property remains up to date with the celebrant.
+
+Property binding is a core feature of QML. In addition to assigning literal
+values, property bindings allow the developer to assign an arbitrarily complex
+JavaScript expression that may include dependencies on other property values.
+Whenever the expression's result changes - through a change in one of its
+constituent values - the expression is automatically reevaluated and
+the new result assigned to the property.
+
+All properties on custom types automatically support property binding. However,
+for binding to work correctly, QML must be able to reliably determine when a
+property has changed so that it knows to reevaluate any bindings that depend on
+the property's value. QML relies on the presence of a
+\c {Qt's Property System}{NOTIFY signal} for this determination.
+
+Here is the celebrant property declaration:
+
+\snippet examples/declarative/extending/binding/birthdayparty.h 0
+
+The NOTIFY attribute is followed by a signal name. It is the responsibility of
+the class implementer to ensure that whenever the property's value changes, the
+NOTIFY signal is emitted. The signature of the NOTIFY signal is not important to QML.
+
+To prevent loops or excessive evaluation, developers should ensure that the
+signal is only emitted whenever the property's value is actually changed. If
+a property, or group of properties, is infrequently used it is permitted to use
+the same NOTIFY signal for several properties. This should be done with care to
+ensure that performance doesn't suffer.
+
+To keep QML reliable, if a property does not have a NOTIFY signal, it cannot be
+used in a binding expression. However, the property can still be assigned
+a binding as QML does not need to monitor the property for change in that
+scenario.
+
+Consider a custom type, \c TestElement, that has two properties, "a" and "b".
+Property "a" does not have a NOTIFY signal, and property "b" does have a NOTIFY
+signal.
+
+\code
+TestElement {
+ // This is OK
+ a: b
+}
+TestElement {
+ // Will NOT work
+ b: a
+}
+\endcode
+
+The presence of a NOTIFY signal does incur a small overhead. There are cases
+where a property's value is set at object construction time, and does not
+subsequently change. The most common case of this is when a type uses
+\l {Grouped Properties}, and the grouped property object is allocated once, and
+only freed when the object is deleted. In these cases, the CONSTANT attribute
+may be added to the property declaration instead of a NOTIFY signal.
+
+\snippet examples/declarative/extending/binding/person.h 0
+
+Extreme care must be taken here or applications using your type may misbehave.
+The CONSTANT attribute should only be used for properties whose value is set,
+and finalized, only in the class constructor. All other properties that want
+to be used in bindings should have a NOTIFY signal instead.
+
+\l {Extending QML - Binding Example} shows the BirthdayParty example updated to
+include NOTIFY signals for use in binding.
+
+\section1 Binding and Script Properties
+
+While generally no changes are needed to a C++ class to use property
+binding, sometimes more advanced interaction between the binding engine and
+an object is desirable. To facilitate this, there is a special exception
+in the bind engine for allowing an object to access the binding directly.
+
+If a binding is assigned to a property with a type of QmlBinding
+pointer (ie. \c {QmlBinding *}), each time the binding value changes,
+a QmlBinding instance is assigned to that property. The QmlBinding instance
+allows the object to read the binding and to evaluate the binding's current value.
+
+\section1 Extension Objects
+
+\snippet examples/declarative/extending/extended/example.qml 0
+
+The QML snippet shown above adds a new property to an existing C++ type without
+modifying its source code.
+
+When integrating existing classes and technology into QML, their APIs will often
+need to be tweaked to fit better into the declarative environment. Although
+the best results are usually obtained by modifying the original classes
+directly, if this is either not possible or is complicated by some other
+concerns, extension objects allow limited extension possibilities without
+direct modifications.
+
+Extension objects are used to add additional properties to an existing type.
+Extension objects can only add properties, not signals or methods. An extended
+type definition allows the programmer to supply an additional type - known as the
+extension type - when registering the target class whose properties are
+transparently merged with the original target class when used from within QML.
+
+An extension class is a regular QObject, with a constructor that takes a QObject
+pointer. When needed (extension classes are delay created until the first extended
+property is accessed) the extension class is created and the target object is
+passed in as the parent. When an extended property on the original is accessed,
+the appropriate property on the extension object is used instead.
+
+When an extended type is installed, one of the
+\code
+ #define QML_DEFINE_EXTENDED_TYPE(URI, VMAJ, VFROM, VTO, QmlName,T, ExtendedT)
+ #define QML_DEFINE_EXTENDED_NOCREATE_TYPE(T, ExtendedT)
+\endcode
+macros should be used instead of the regular \c QML_DEFINE_TYPE or
+\c QML_DEFINE_NOCREATE_TYPE. The arguments are identical to the corresponding
+non-extension object macro, except for the ExtendedT parameter which is the type
+of the extension object.
+
+\section1 Optimization
+
+Often to develop high performance elements it is helpful to know more about the
+status of the QML engine. For example, it might be beneficial to delay
+initializing some costly data structures until after all the properties have been
+set.
+
+The QML engine defines an interface class called QmlParserStatus, which contains a
+number of virtual methods that are invoked at various stages during component
+instantiation. To receive these notifications, an element implementation inherits
+QmlParserStatus and notifies the Qt meta system using the Q_INTERFACES() macro.
+
+For example,
+
+\code
+class Example : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+public:
+ virtual void componentComplete()
+ {
+ qDebug() << "Woohoo! Now to do my costly initialization";
+ }
+};
+\endcode
+
+*/
+
+/*!
+\page qml-extending-types.html
+\title Extending types from QML
+
+Many of the elements available for use in QML are implemented in
+\l {Extending QML}{C++}. These types are know as "core types". QML
+allows programmers to build new, fully functional elements without using C++.
+Existing core types can be extended, and new types defined entirely in the QML
+language.
+
+\tableofcontents
+
+\section1 Adding new properties
+
+New properties can be added to an existing type. These new properties are
+available for use within QML, and also appear as regular Qt properties on the
+C++ object, accessible through the regular property access mechanisms.
+
+Like all properties in QML, custom properties are typed. The type is used to
+define the property's behavior, and also determines the C++ type of the created
+Qt property. The following table shows the list of types available when
+declaring a new property, and the corresponding C++ type.
+
+\table
+\header \o QML Type Name \o C++ Type Name
+\row \o int \o int
+\row \o bool \o bool
+\row \o double \o double
+\row \o real \o double
+\row \o string \o QString
+\row \o url \o QUrl
+\row \o color \o QColor
+\row \o date \o QDate
+\row \o var \o QVariant
+\row \o variant \o QVariant
+\endtable
+
+QML supports two methods for adding a new property to a type: a new property
+definition, and a property alias.
+
+\section2 Property definitions
+
+Property definitions add a new property to an existing type. The storage of the
+property is managed by QML. The defined property may be read, written and bound
+to and from.
+
+The syntax for defining a new property is:
+\code
+ [default] property <type> <name>[: defaultValue]
+\endcode
+
+This declaration may appear anywhere within a type body, but it is customary to
+include it at the top. Attempting to declare two properties with the same name
+in the same type block is an error. However, a new property may reuse the name
+of an existing property on the type. This should be done with caution, as the
+existing property will be hidden, and become inaccessible.
+
+The <type> must be one of the QML type names shown in the above table.
+Additionally, an optional default value of the property can be provided. The
+default value is a convenient shortcut, but is behaviorally identical to doing
+it in two steps, like this:
+
+\code
+ // Use default value
+ property int myProperty: 10
+
+ // Longer, but behaviorally identical
+ property int myProperty
+ myProperty: 10
+\endcode
+
+If specified, the optional "default" attribute marks the new property as the
+types default property, overriding any existing default property. Using the
+default attribute twice in the same type block is an error.
+
+The following example shows how to declare a new "innerColor" property that
+controls the color of the inner rectangle.
+
+\code
+ Rectangle {
+ property color innerColor: "black"
+
+ color: "red"; width: 100; height: 100
+ Rectangle {
+ anchors.centerIn: parent
+ width: parent.width - 10
+ height: parent.height - 10
+ color: innerColor
+ }
+ }
+\endcode
+
+\target qml-property-aliases
+\section2 Property aliases
+
+Property aliases are a more advanced form of property declaration. Unlike a
+property definition, that allocates a new, unique storage space for the
+property, a property alias connects the newly declared property (called the
+aliasing property) to an existing property (the aliased property). Read
+operations on the aliasing property act as read operations on the aliased
+property, and write operations on the aliasing property as write operations on
+the aliased property.
+
+A property alias declaration looks a lot like a property definition:
+\code
+ [default] property alias <name>: <alias reference>
+\endcode
+
+As the aliasing property has the same type as the aliased property, an explicit
+type is omitted, and the special "alias" keyword is used. Instead of a default
+value, a property alias includes a compulsary alias reference. The alias
+reference is used to locate the aliased property. While similar to a property
+binding, the alias reference syntax is highly restricted.
+
+An alias reference takes one of the following forms
+\code
+ <id>.<property>
+ <id>
+\endcode
+
+where <id> must refer to an object id within the same component as the type
+declaring the alias, and, optionally, <property> refers to a property on that object.
+
+Here is the property definition example rewritten to use property aliases.
+\code
+Rectangle {
+ property alias innerColor: innerRect.color
+
+ color: "red"; width: 100; height: 100
+ Rectangle {
+ id: innerRect
+ anchors.centerIn: parent
+ width: parent.width - 10
+ height: parent.height - 10
+ color: "black"
+ }
+}
+\endcode
+
+Aliases are most useful when \l {Defining new Components}. Consequently
+they have several apparent limitations that only make sense in this context.
+
+Aliases are only activated once the component specifying them is completed. The
+most obvious consequence of this is that the component itself cannot generally
+use the aliased property directly. For example, this will not work:
+
+\code
+ // Does NOT work
+ property alias innerColor: innerRect.color
+ innerColor: "black"
+\endcode
+
+This behavior is required to allow type developers to redefine the behavior
+of existing property names while continuing to use the existing behavior within
+the type they are building, something that is not possible with property
+definitions. In the example used so far, this could allows the developer to fix
+the external rectangle's color as "red" and redefine the "color" property to
+refer to the inner rectangle, like this:
+
+\code
+Rectangle {
+ property alias color: innerRect.color
+
+ color: "red"; width: 100; height: 100
+ Rectangle {
+ id: innerRect
+ anchors.centerIn: parent
+ width: parent.width - 10
+ height: parent.height - 10
+ color: "black"
+ }
+}
+\endcode
+
+Users of this type would not be able to affect the color of the red rectangle,
+but would find using the "color" property, rather than the strange new
+"innerColor" property, much more familiar.
+
+A second, much less significant, consequence of the delayed activation of
+aliases is that an alias reference cannot refer to another aliasing property
+declared within the same component. This will not work:
+
+\code
+ // Does NOT work
+ id: root
+ property alias innerColor: innerRect.color
+ property alias innerColor2: root.innerColor
+\endcode
+
+From outside the component, aliasing properties appear as regular Qt properties
+and consequently can be used in alias references.
+
+\section1 Adding new signals
+
+New signals can be added to an existing type. These new signals are available
+for use within QML, and also appear as regular Qt signals on the C++ object that
+can be used in Qt signal/slot connections.
+
+The syntax for defining a new signal is:
+\code
+signal <name>[([<type> <parameter name>[, ...]])]
+\endcode
+
+This declaration may appear anywhere within a type body, but it is customary to
+include it at the top. Attempting to declare two signals or methods with the
+same name in the same type block is an error. However, a new signal may reuse
+the name of an existing signal on the type. This should be done with caution,
+as the existing signal may be hidden and become inaccessible.
+
+The options for parameter types are the same as for property types (see
+\l {Adding new properties}. If this signal has no parameters, the parameter
+list may be omitted entirely.
+
+Here are three examples of signal declarations:
+\code
+ Item {
+ signal clicked
+ signal hovered()
+ signal performAction(string action, var actionArgument)
+ }
+\endcode
+
+Adding a signal to an item automatically adds a signal handler to it.
+The signal hander is named on<Signal name>, with the first letter of the
+signal name being upper cased. The above example item would now have the
+following signal handlers:
+
+\list
+ \o onClicked
+ \o onHovered
+ \o onPerformAction
+\endlist
+
+\section1 Adding new methods
+
+New methods can be added to an existing type. These new methods are available
+for use within QML, and also appear as regular Qt slots on the C++ object that
+can be used in Qt signal/slot connections.
+
+\code
+function <name>([<parameter name>[, ...]]) { <body> }
+\endcode
+
+This declaration may appear anywhere within a type body, but it is customary to
+include it at the top. Attempting to declare two methods or signals with the
+same name in the same type block is an error. However, a new method may reuse
+the name of an existing method on the type. This should be done with caution,
+as the existing method may be hidden and become inaccessible.
+
+Methods parameters are not typed. In C++ these parameters are of type QVariant.
+The body of the method is written in JavaScript and may access the parameters by
+name.
+
+This example adds a new method that behaves like a child:
+\code
+Item {
+ function say(text) {
+ console.log("You said " + text);
+ }
+}
+\endcode
+
+\section1 Defining new Components
+\target components
+
+A component is a reusable type with a well-defined interface built entirely in
+QML. Components appear as regular QML elements, and can be used interchangably
+with core types. Components allow developers to create new types to be reused
+in other projects without the use of C++. Components can also help to reduce
+duplication inside one project by limiting the need for large numbers of
+copy-and-pasted blocks.
+
+Any snippet of QML code can become a component, just by placing it in the file
+"<Name>.qml" where <Name> is the new element name, and begins with an uppercase
+letter. These QML files automatically become available as new QML element types
+to other QML components and applications in the same directory.
+
+For example, here we show how a component named "Box" is defined and used
+multiple times by an application.
+
+\table
+\row
+\o application.qml
+\code
+Rectangle {
+ width: 100; height: 400;
+ Box { x: 0; y: 0 }
+ Box { x: 0; y: 150 }
+ Box { x: 0; y: 300 }
+}
+\endcode
+\o Box.qml
+\code
+Rectangle {
+ width: 100; height: 100;
+ color: "blue"
+}
+\endcode
+\endtable
+
+Components may be collected into \l {Modules} that gives the
+developer more freedom than just putting files in the same directory.
+
+\section2 Building reusable components
+
+A component type built to be reused by others must have a well defined
+interface. In QML, an interface consists of a defined collection of
+properties, signals and methods. Users of a component have access to all the
+properties, signals and methods defined on the root element of the component.
+
+In the component example above, the root element of the "Box" component is a
+Rect. As the Rect type has a "color" property, this property is accessible to
+users of the Box component. For example, the application.qml can be modified
+to show three different colored boxes like this:
+\code
+Rectangle {
+ width: 100; height: 400;
+ Box { x: 0; y: 0; color: "red"; }
+ Box { x: 0; y: 150; color: "yellow"; }
+ Box { x: 0; y: 300; color: "green"; }
+}
+\endcode
+
+As expected, adding additional properties to the root element of Box, makes them
+available externally. Here we add a "text" property:
+
+\table
+\row
+\o application.qml
+\code
+Rectangle {
+ width: 100; height: 400;
+ Box { x: 0; y: 0; color: "red"; text: "stop" }
+ Box { x: 0; y: 150; color: "yellow"; text: "slow" }
+ Box { x: 0; y: 300; color: "green"; text: "go" }
+}
+\endcode
+\o Box.qml
+\code
+Rectangle {
+ property alias text: myText.text
+ width: 100; height: 100;
+ color: "blue"
+ Text {
+ id: myText
+ anchors.centerIn: parent
+ }
+}
+\endcode
+\endtable
+
+Methods and signals may be added in the same way.
+
+As all external methods, signals and properties are accessible to external
+users, developers should ensure that setting these properties does not have
+any undesirable side-effects. For most resiliance, root level properties should
+only be used for literal default values. When a root level property must be
+used inside the component - such as the children property - property aliases
+can be used to redirect this property to a "safe" location for external users.
+Try to think of the root level properties as being "owned" by the components
+user, rather than the component itself.
+*/
diff --git a/doc/src/declarative/focus.qdoc b/doc/src/declarative/focus.qdoc
new file mode 100644
index 0000000..46bfc38
--- /dev/null
+++ b/doc/src/declarative/focus.qdoc
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\target qmlfocus
+\page qmlfocus.html
+\title Keyboard Focus in QML
+
+When a key is pressed or released, a key event is generated and delivered to the
+focused QML \l Item. To facilitate the construction of reusable components
+and to address some of the cases unique to fluid user interfaces, the QML items add a
+\e scope based extension to Qt's traditional keyboard focus model.
+
+\tableofcontents
+
+\section1 Key Handling Overview
+
+When the user presses or releases a key, the following occurs:
+\list 1
+\o Qt receives the key action and generates a key event.
+\o If the Qt widget containing the \l QmlView has focus, the key event is delivered to it. Otherwise, regular Qt key handling continues.
+\o The key event is delivered by the scene to the QML \l Item with \e {active focus}. If no \l Item has \e {active focus}, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues.
+\o If the QML \l Item with \e {active focus} accepts the key event, propagation stops. Otherwise the event is "bubbled up", by recursively passing it to each \l Item's parent until either the event is accepted, or the root \l Item is reached.
+
+If the \c {Rectangle} element in the following example has active focus and the \e A key is pressed,
+it will bubble up to its parent. However, pressing the \e B key will bubble up to the root
+item and thus subsequently be \l {QEvent::ignore()}{ignored}.
+
+\code
+Item {
+ Item {
+ Keys.onPressed: if (event.key == Qt.Key_A) { console.log('Key A was pressed'); event.accepted = true }
+ Rectangle {}
+ }
+}
+\endcode
+
+\o If the root \l Item is reached, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues.
+
+\endlist
+
+See also the \l {Keys}{Keys attached property} and \l {KeyNavigation}{KeyNavigation attached property}.
+
+\section1 Querying the Active Focus Item
+
+Whether or not an \l Item has \e {active focus} can be queried through the
+property \c {Item::focus}. For example, here we have a \l Text
+element whose text is determined by whether or not it has \e {active focus}.
+
+\code
+Text {
+ text: focus ? "I have active focus!" : "I do not have active focus"
+}
+\endcode
+
+\section1 Acquiring Focus and Focus Scopes
+
+An \l Item requests focus by setting the \c {Item::focus} property to true.
+
+For very simple cases simply setting the \c {Item::focus} property is sometimes
+sufficient. If we run the following example in the \c qmlviewer, we see that
+the \c {keyHandler} element has \e {active focus} and pressing the 'A', 'B'
+or 'C' keys modifies the text appropriately.
+
+\table
+\row
+\o \code
+ Rectangle {
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: myText }
+ Item {
+ id: keyHandler
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_A)
+ myText.text = 'Key A was pressed'
+ else if (event.key == Qt.Key_B)
+ myText.text = 'Key B was pressed'
+ else if (event.key == Qt.Key_C)
+ myText.text = 'Key C was pressed'
+ }
+ }
+ }
+\endcode
+\o \image declarative-qmlfocus1.png
+\endtable
+
+However, were the above example to be used as a self-contained component, this
+simple use of the \c {Item::focus} property is no longer sufficient. The left
+hand side of the following table shows what we would like to be able to write.
+Here we create two instances of our previously defined component, and set the
+second one to have focus. The intention is that when the \e A, \e B, or \e C
+keys are pressed, the second of the two components receives the event and
+reponds accordingly.
+
+\table
+\row
+\o \code
+Rectangle {
+ color: "red"; width: 240; height: 55
+ MyWidget {}
+ MyWidget { y: 30; focus: true }
+}
+\endcode
+\o \code
+Rectangle {
+ color: "red"; width: 240; height: 55
+ Rectangle {
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: myText }
+ Item {
+ id: keyHandler
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_A)
+ myText.text = 'Key A was pressed'
+ else if (event.key == Qt.Key_B)
+ myText.text = 'Key B was pressed'
+ else if (event.key == Qt.Key_C)
+ myText.text = 'Key C was pressed'
+ }
+ }
+ }
+ Rectangle {
+ y: 30; focus: true
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: myText }
+ Item {
+ id: keyHandler
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_A)
+ myText.text = 'Key A was pressed'
+ else if (event.key == Qt.Key_B)
+ myText.text = 'Key B was pressed'
+ else if (event.key == Qt.Key_C)
+ myText.text = 'Key C was pressed'
+ }
+ }
+ }
+}
+\endcode
+\endtable
+
+The right hand side of the example shows the expanded code - the equivalent QML
+without the use of the component \c {MyWidget}. From this, the problem is
+evident - there are no less than three elements that have the \c {Item::focus}
+property set to true. Ultimately only one element can have focus, and the
+system has to decide which on. In this case the first appearance of the
+\c {Item::focus} property being set to true on line 4 is selected, and the value
+of \c {Item::focus} in the other two instances is reverted back to false. This
+is exactly the opposite of what was wanted!
+
+This problem is fundamentally one of visibility. The \c {MyWidget}
+components each set their \c {keyHandler} Items as focused as that is all they can
+do - they don't know how they are going to be used, but they do know that when
+they're in use their \c {keyHandler} element is what needs focus. Likewise
+the code that uses the two \c {MyWidgets} sets the second \c {MyWidget} as
+focused. While it doesn't know exactly how the \c {MyWidget} is
+implemented, it knows that it wants the second one to be focused. This allows us
+to achieve encapsulation, allowing each widget to focus on it's appropriate behaviour
+itself.
+
+To solve this problem - allowing components to care about what they know about
+and ignore everything else - the QML items introduce a concept known as a
+\e {focus scope}. For existing Qt users, a \e {focus scope} is like an
+automatic focus proxy. A \e {focus scope} is created using the \l FocusScope
+element.
+
+In the next example, a \l FocusScope is added to the component, and the visual
+result shown.
+
+\table
+\row
+\o \code
+FocusScope {
+ width: 240; height: 25
+ Rectangle {
+ color: "lightsteelblue"; width: 240; height: 25
+ Text { id: myText }
+ Item {
+ id: keyHandler
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_A)
+ myText.text = 'Key A was pressed'
+ else if (event.key == Qt.Key_B)
+ myText.text = 'Key B was pressed'
+ else if (event.key == Qt.Key_C)
+ myText.text = 'Key C was pressed'
+ }
+ }
+ }
+}
+\endcode
+\o \image declarative-qmlfocus2.png
+\endtable
+
+Conceptually \e {focus scopes} are quite simple.
+\list
+\o Within each \e {focus scope} one element may have \c {Item::focus} set to true.
+If more than one \l Item has the \c {Item::focus} property set, the first is selected
+and the others are unset, just like when there are no \e {focus scopes}.
+\o When a \e {focus scope} receives \e {active focus}, the contained element with
+\c {Item::focus} set (if any) also gets \e {active focus}. If this element is
+also a \l FocusScope, the proxying behaviour continues. Both the
+\e {focus scope} and the sub-focused item will have \c {Item::focus} set.
+\endlist
+
+So far the example has the second component statically selected. It is trivial
+now to extend this component to make it clickable, and add it to the original
+application. We still set a one of the widgets as focused by default, but from
+then on clicking the either one gives it focus.
+
+\table
+\row
+\o \code
+Rectangle {
+ color: "red"; width: 240; height: 55
+ MyClickableWidget {}
+ MyClickableWidget { y: 30; focus: true }
+}
+\endcode
+\o \code
+FocusScope {
+ id: page; width: 240; height: 25
+ MyWidget { focus: true }
+ MouseRegion { anchors.fill: parent; onClicked: { page.focus = true } }
+}
+\endcode
+\endtable
+
+\image declarative-qmlfocus3.png
+
+When a QML item explicitly relinquishes focus (by setting its
+\c {Item::focus} property to false while it has \e {active focus}), the system
+does not automatically select another element to receive focus. That is, it
+is possible for there to be no currently \e {active focus}.
+
+\section1 Advanced uses of Focus Scopes
+
+Focus scopes allow focus to allocation to be easily partitioned. Several
+QML items use it to this effect.
+
+\l ListView, for example, is itself a focus scope. Generally this isn't
+noticable as \l ListView doesn't usually have manually added visual children.
+By being a focus scope, \l ListView can focus the current list item without
+worrying about how that will effect the rest of the application. This allows
+the current item delegate to react to key presses.
+
+This contrived example shows how this works. Pressing the \c Return key will
+print the name of the current list item.
+
+\table
+\row
+\o \code
+Rectangle {
+ color: "lightsteelblue"; width: 240; height: 320
+
+ ListView {
+ id: myView; anchors.fill: parent; focus: true
+ model: ListModel {
+ ListElement { name: "Bob" }
+ ListElement { name: "John" }
+ ListElement { name: "Michael" }
+ }
+ delegate: FocusScope {
+ width: contents.width; height: contents.height
+ Text {
+ focus: true
+ text: name
+ Keys.onReturnPressed: console.log(name)
+ }
+ }
+ }
+}
+\endcode
+\o \image declarative-qmlfocus4.png
+\endtable
+
+While the example is simple, there's a lot going on behind the scenes. Whenever
+the current item changes, the \l ListView sets the delegate's \c {Item::focus}
+property. As the \l ListView is a \e {focus scope}, this doesn't effect the
+rest of the application. However, if the \l ListView itself has
+\e {active focus} this causes the delegate itself to receive \e {active focus}.
+In this example, the root element of the delegate is also a \e {focus scope},
+which in turn gives \e {active focus} to the \c {Text} element that
+actually performs the work of handling the \e {Return} key.
+
+All of the QML view classes, such as \l PathView and \l GridView, behave
+in a similar mannor to allow key handling in their respective delegates.
+
+\section1 Focus Panels
+
+Traditional UIs are composed of many top-level windows. Windows actually
+perform two tasks - they act as the visual bounds for a widget, and they segment
+focus. Each window has a separate focused widget, that becomes (to mix
+terminologies) the \e {active focus} widget when the window is the active
+window.
+
+### Focus panels do basically the same thing.
+*/
diff --git a/doc/src/declarative/globalobject.qdoc b/doc/src/declarative/globalobject.qdoc
new file mode 100644
index 0000000..764552a
--- /dev/null
+++ b/doc/src/declarative/globalobject.qdoc
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlglobalobject.html
+\title QML Global Object
+
+Contains all the properties of the JavaScript global object, plus:
+
+\tableofcontents
+
+\section1 Qt Object
+
+The Qt object provides useful enums and functions from Qt, for use in all QML
+files.
+
+\section2 Enums
+The Qt object contains all enums in the Qt namespace. For example, you can
+access the AlignLeft member of the Qt::AlignmentFlag enum with \c Qt.AlignLeft.
+
+For a full list of enums, see the \l{Qt Namespace} documentation.
+
+\section2 Types
+The Qt object also contains helper functions for creating objects of specific
+data types. This is primarily useful when setting the properties of an item
+when the property has one of the following types:
+
+\list
+\o Color
+\o Rect
+\o Point
+\o Size
+\o Vector3D
+\endlist
+
+There are also string based constructors for these types, see \l{basicqmltypes.html}{Qml Types}.
+
+\section3 Qt.rgba(qreal red, qreal green, qreal blue, qreal alpha)
+This function returns a Color with the specified \c red, \c green, \c blue and \c alpha components. All components should be in the range 0-1 inclusive.
+
+\section3 Qt.hsla(qreal hue, qreal saturation, qreal lightness, qreal alpha)
+This function returns a Color with the specified \c hue, \c saturation, \c lightness and \c alpha components. All components should be in the range 0-1 inclusive.
+
+\section3 Qt.rect(int x, int y, int width, int height)
+This function returns a Rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
+\section3 Qt.point(int x, int y)
+This function returns a Point with the specified \c x and \c y coordinates.
+\section3 Qt.size(int width, int height)
+This function returns as Size with the specified \c width and \c height.
+\section3 Qt.vector3d(real x, real y, real z)
+This function returns a Vector3D with the specified \c x, \c y and \c z.
+\section2 Functions
+The Qt object also contains the following miscellaneous functions which expose Qt functionality for use in QML.
+
+\section3 Qt.lighter(color baseColor)
+This function returns a color 50% lighter than \c baseColor. See QColor::lighter() for further details.
+\section3 Qt.darker(color baseColor)
+This function returns a color 50% darker than \c baseColor. See QColor::darker() for further details.
+\section3 Qt.tint(color baseColor, color tintColor)
+ This function allows tinting one color with another.
+
+ The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque.
+
+ \qml
+ Rectangle { x: 0; width: 80; height: 80; color: "lightsteelblue" }
+ Rectangle { x: 100; width: 80; height: 80; color: Qt.tint("lightsteelblue", "#10FF0000") }
+ \endqml
+ \image declarative-rect_tint.png
+
+ Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
+\section3 Qt.closestAngle(number fromAngle, number toAngle)
+This function returns an equivalent angle to toAngle, such that the difference between fromAngle and toAngle is never more than 180 degrees. This is useful when animating angles using a NumberAnimation, which does not know about equivalent angles, when you always want to take the shortest path.
+
+For example, the following would rotate myItem counterclockwise from 350 degrees to 10 degrees, for a total of 340 degrees of rotation.
+\qml
+NumberAnimation { target: myItem; property: "rotation"; from: 350; to: 10 }
+\endqml
+
+while the following would rotate myItem clockwise from 350 degrees to 370 degrees (which is visually equivilant to 10 degrees), for a total of 20 degrees of rotation.
+\qml
+NumberAnimation { target: myItem; property: "rotation"; from: 350; to: Qt.closetAngle(350, 10) }
+\endqml
+
+\section3 Qt.playSound(url soundLocation)
+This function plays the audio file located at \c soundLocation. Only .wav files are supported.
+
+\section3 Qt.openUrlExternally(url target)
+This function attempts to open the specified \c target url in an external application, based on the user's desktop preferences. It will return true if it succeeds, and false otherwise.
+
+\section3 Qt.md5(data)
+This function returns a hex string of the md5 hash of \c data.
+
+\section1 Dynamic Object Creation
+The following functions on the global object allow you to dynamically create QML
+items from files or strings. See \l{Dynamic Object Management} for an overview
+of their use.
+
+\section2 createComponent(url file)
+ This function takes the URL of a QML file as its only argument. It returns
+ a component object which can be used to create and load that QML file.
+
+ Example QML script is below. Remember that QML files that might be loaded
+ over the network cannot be expected to be ready immediately.
+ \code
+ var component;
+ var sprite;
+ function finishCreation(){
+ if(component.isReady()){
+ sprite = component.createObject();
+ if(sprite == 0){
+ // Error Handling
+ }else{
+ sprite.parent = page;
+ sprite.x = 200;
+ //...
+ }
+ }else if(component.isError()){
+ // Error Handling
+ }
+ }
+
+ component = createComponent("Sprite.qml");
+ if(component.isReady()){
+ finishCreation();
+ }else{
+ component.statusChanged.connect(finishCreation);
+ }
+ \endcode
+
+ If you are certain the files will be local, you could simplify to
+
+ \code
+ component = createComponent("Sprite.qml");
+ sprite = component.createObject();
+ if(sprite == 0){
+ // Error Handling
+ console.log(component.errorsString());
+ }else{
+ sprite.parent = page;
+ sprite.x = 200;
+ //...
+ }
+ \endcode
+
+ If you want to just create an arbitrary string of QML, instead of
+ loading a QML file, consider the createQmlObject() function.
+
+\section2 createQmlObject(string qml, object parent, string filepath)
+ Creates a new object from the specified string of QML. It requires a
+ second argument, which is the id of an existing QML object to use as
+ the new object's parent. If a third argument is provided, this is used
+ for error reporting as the filepath that the QML came from.
+
+ Example (where targetItem is the id of an existing QML item):
+ \code
+ newObject = createQmlObject('import Qt 4.6; Rectangle {color: "red"; width: 20; height: 20}',
+ targetItem, "dynamicSnippet1");
+ \endcode
+
+ This function is intended for use inside QML only. It is intended to behave
+ similarly to eval, but for creating QML elements.
+
+ Returns the created object, or null if there is an error. In the case of an
+ error, details of the error are output using qWarning().
+
+ Note that this function returns immediately, and therefore may not work if
+ the QML loads new components. If you are trying to load a new component,
+ for example from a QML file, consider the createComponent() function
+ instead. 'New components' refers to external QML files that have not yet
+ been loaded, and so it is safe to use createQmlObject to load built-in
+ components.
+
+\section1 Asynchronous JavaScript and XML
+QML script supports the XMLHttpRequest object, which can be used to asynchronously obtain data from over a network.
+\section2 XMLHttpRequest()
+In QML you can construct an XMLHttpRequest object just like in a web browser! TODO: Real documentation for this object.
+\section1 Offline Storage API
+
+The \c openDatabase() and related functions
+provide the ability to access local offline storage in an SQL database.
+
+These databases are user-specific and QML-specific. They are stored in the \c Databases subdirectory
+of QmlEngine::offlineStoragePath(), currently as SQLite databases.
+
+The API conforms to the Synchronous API of the HTML5 Web Database API,
+\link http://www.w3.org/TR/2009/WD-webdatabase-20091029/ W3C Working Draft 29 October 2009\endlink.
+
+The API can be used from JavaScript functions in your QML:
+
+\quotefile declarative/sql/hello.qml
+
+When a database is first created, an INI file is also created specifying its characteristics:
+
+\table
+\header \o \bold {Key} \o \bold {Value}
+\row \o Name \o The name of the database passed to \c openDatabase()
+\row \o Version \o The version of the database passed to \c openDatabase()
+\row \o Description \o The description of the database passed to \c openDatabase()
+\row \o EstimatedSize \o The estimated size of the database passed to \c openDatabase()
+\row \o Driver \o Currently "QSQLITE"
+\endtable
+
+This data can be used by application tools.
+
+*/
diff --git a/doc/src/declarative/integrating.qdoc b/doc/src/declarative/integrating.qdoc
new file mode 100644
index 0000000..d93a6ff
--- /dev/null
+++ b/doc/src/declarative/integrating.qdoc
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qml-integration.html
+\title Integrating QML with existing Qt UI code
+
+If you have existing Qt UI code which does not use QML you can still
+add QML to your UI, without having to rewrite it.
+
+\section1 Adding QML to a \l{QWidget} based UI
+If you have an existing QWidget based UI you can simply write new custom
+widgets in QML. To integrate them into your application you can create a
+QmlView widget, and load the QML file into that. You'll then have a new widget
+containing your declarative UI, and you can interact with it through the
+QmlView interface. The one drawback of this approach is that QmlView is a lot
+heavier than a QWidget in terms of memory consumption and initialization speed,
+and so having large numbers of them may lead to performance degredation.
+
+For a smooth transition from a QWidget based UI to a QML based UI, simply
+rewrite your widgets in QML one at a time, using the above method. When
+all of your widgets are written in QML you can rewrite your main widget in
+QML, so as to load the other widgets in QML instead of using QmlViews. Then
+you just load the main QML file on startup.
+
+Keep in mind that QWidgets were designed for different sorts of UIs than QML
+was, and so it is not always a good idea to switch. QWidgets are a better
+choice if your UI is comprised of a small number of complex and static
+elements, and QML is a better choice if your UI is comprised of a large number
+of simple and dynamic elements.
+
+\section1 Adding QML to a QGraphicsView based UI
+If you have an existing Graphics View based UI you can create new items in QML,
+and use \l{QmlComponent} to create \l{QGraphicsObject}s from the QML files. These
+\l{QGraphicsObject}s can then be placed into your \l{QGraphicsScene} using \l{QGraphicsScene::addItem}
+or by reparenting them to an item already in the \l{QGraphicsScene}.
+
+Example, for local QML files:
+
+\code
+QGraphicsScene* scene = new QGraphicsScene;
+QmlEngine *engine = new QmlEngine;
+QmlComponent component(engine, QUrl::fromLocalFile(filename));
+QGraphicsObject *object =
+ qobject_cast<QGraphicsObject *>(component.create());
+scene->addItem(object);
+\endcode
+
+\section1 Using existing QGraphicsWidgets in QML
+Another way of integrating with a QGraphicsView based UI is to expose your
+existing QGraphicsWidgets to QML, and constructing your scene in QML. Note that
+this approach will not work with QGraphicsItems which are not QGraphicsWidgets,
+and that this approach allows you to integrate new items written in QML
+without using the above method.
+
+You can make custom C++ types
+available in QML using the pair of macros listed in \l{Extending QML}.
+While this is normally only useful for
+types that were designed for QML use, in conjunction with the
+\l{GraphicsObjectContainer} element QGraphicsWidget subclasses can also be
+used effectively (if they were designed, like QGraphicsWidget, to be controllable through Qt's property system).
+This way you can write your UI using QML, without having to rewrite your existing items.
+
+For details on implementing this approach see \l{Extending QML} page for details on exposing your C++ types,
+and the \l{GraphicsObjectContainer} documentation for details about using it to wrap QGraphicsWidgets.
+*/
diff --git a/doc/src/declarative/javascriptblocks.qdoc b/doc/src/declarative/javascriptblocks.qdoc
new file mode 100644
index 0000000..9c72a9c
--- /dev/null
+++ b/doc/src/declarative/javascriptblocks.qdoc
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmljavascript.html
+\title JavaScript Blocks
+
+QML encourages building UIs declaratively, using \l {Property Binding} and the
+composition of existing \l {QML Elements}. If imperative code is required to implement
+more advanced behavior, the \l Script element can be used to add JavaScript code directly
+to a QML file, or to include an external JavaScript file.
+
+The \l Script element is a QML language \e intrinsic. It can be used anywhere in a
+QML file, \e except as the root element of a file or sub-component, but cannot be
+assigned to an object property or given an id. The included JavaScript is evaluated
+in a scope chain. The \l {QML Scope} documentation covers the specifics of scoping
+in QML.
+
+A restriction on the JavaScript used in QML is that you cannot add new members to the
+global object. This happens transparently when you try to use a variable without
+declaring it, and so declaring local variables is required when using Java script in
+QML.
+
+The global object in QML has a variety of helper functions added to it, to aid UI
+implementation. See \l{QML Global Object} for further details.
+
+Note that if you are adding a function that should be called by external elements,
+you do not need the \l Script element. See \l {Extending types from QML#Adding new methods}
+{Adding new methods} for information about adding slots that can be called externally.
+
+\section1 Inline Script
+
+Small blocks of JavaScript can be included directly inside a \l {QML Document} as
+the body of the \l Script element.
+
+\code
+Rectangle {
+ Script {
+ function factorial(a) {
+ a = Integer(a);
+ if (a <= 0)
+ return 1;
+ else
+ return a * factorial(a - 1);
+ }
+ }
+}
+\endcode
+
+Good programming practice dictates that only small script snippets should be written
+inline. QML prohibits the declaration of anything other than functions in an inline
+script block. For example, the following script is illegal as an inline script block
+as it declares the non-function variable \c lastResult.
+
+\code
+// Illegal inline code block
+var lastResult = 0
+function factorial(a) {
+ a = Integer(a);
+ if (a <= 0)
+ lastResult = 1;
+ else
+ lastResult = a * factorial(a - 1);
+ return lastResult;
+}
+\endcode
+
+\section1 Including an External File
+
+To avoid cluttering the QML file, large script blocks should be in a separate file.
+The \l Script element's \c source property is used to load script from an external
+file.
+
+If the previous factorial code that was illegal as an inline script block was saved
+into a "factorial.js" file, it could be included like this.
+
+\code
+Rectangle {
+ Script {
+ source: "factorial.js"
+ }
+}
+\endcode
+
+The \c source property may reference a relative file, or an absolute path. In the
+case of a relative file, the location is resolved relative to the location of the
+\l {QML Document} that contains the \l Script element. If the script file is not
+accessible, an error will occur. If the source is on a network resource, the
+enclosing QML document will remain in the \l {QmlComponent::status()}{waiting state}
+until the script has been retrieved.
+
+\section1 Running Script at Startup
+
+It is occasionally necessary to run a block of JavaScript code at application (or
+component instance) "startup". While it is tempting to just include the startup
+script as \e {global code} in an external script file, this can have severe limitations
+as the QML environment may not have been fully established. For example, some objects
+might not have been created or some \l {Property Binding}s may not have been run.
+\l {QML Script Restrictions} covers the exact limitations of global script code.
+
+The QML \l Component element provides an \e attached \c onCompleted property that
+can be used to trigger the execution of script code at startup after the
+QML environment has been completely established.
+
+The following QML code shows how to use the \c Component::onCompleted property.
+
+\code
+Rectangle {
+ Script {
+ function startupFunction() {
+ // ... startup code
+ }
+ }
+
+ Component.onCompleted: startupFunction();
+}
+\endcode
+
+Any element in a QML file - including nested elements and nested QML component
+instances - can use this attached property. If there is more than one script to
+execute at startup, they are run sequentially in an undefined order.
+
+\section1 QML Script Restrictions
+
+QML \l Script blocks contain standard JavaScript code. QML introduces the following
+restrictions.
+
+\list
+\o Script code cannot modify the global object.
+
+In QML, the global object is constant - existing properties cannot be modified or
+deleted, and no new properties may be created.
+
+Most JavaScript programs do not explicitly modify the global object. However,
+JavaScript's automatic creation of undeclared variables is an implicit modification
+of the global object, and is prohibited in QML.
+
+Assuming that the \c a variable does not exist in the scope chain, the following code
+is illegal in QML.
+
+\code
+// Illegal modification of undeclared variable
+a = 1;
+for (var ii = 1; ii < 10; ++ii) a = a * ii;
+ console.log("Result: " + a);
+\endcode
+
+It can be trivially modified to this legal code.
+
+\code
+var a = 1;
+for (var ii = 1; ii < 10; ++ii) a = a * ii;
+ console.log("Result: " + a);
+\endcode
+
+Any attempt to modify the global object - either implicitly or explicitly - will
+cause an exception. If uncaught, this will result in an warning being printed,
+that includes the file and line number of the offending code.
+
+\o Global code is run in a reduced scope
+
+During startup, if a \l Script block includes an external file with "global"
+code, it is executed in a scope that contains only the external file itself and
+the global object. That is, it will not have access to the QML objects and
+properties it \l {QML Scope}{normally would}.
+
+Global code that only accesses script local variable is permitted. This is an
+example of valid global code.
+
+\code
+var colors = [ "red", "blue", "green", "orange", "purple" ];
+\endcode
+
+Global code that accesses QML objects will not run correctly.
+
+\code
+// Invalid global code - the "rootObject" variable is undefined
+var initialPosition = { rootObject.x, rootObject.y }
+\endcode
+
+This restriction exists as the QML environment is not yet fully established.
+To run code after the environment setup has completed, refer to
+\l {Running Script at Startup}.
+
+\endlist
+
+*/
diff --git a/doc/src/declarative/measuring-performance.qdoc b/doc/src/declarative/measuring-performance.qdoc
new file mode 100644
index 0000000..bd1b0eb
--- /dev/null
+++ b/doc/src/declarative/measuring-performance.qdoc
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page optimizing-performance.html
+\target optimizing-performance
+\title Optimizing Performance in QML
+
+The Qt Declarative module includes several tools to help measure performance.
+
+\section1 Performance Logging
+
+The declarative module uses the functionality provided by QPerformanceLog to log performance information. To see this information you can add the following to src.pro:
+
+\code
+DEFINES += Q_ENABLE_PERFORMANCE_LOG
+\endcode
+
+The performance information will be printed to screen on a QML application startup, or when running the viewer can be forced at anytime by pressing 'F3' on the keyboard.
+
+Additional logging can be enabled by adding the relevant categories to qfxperf.h and qfxperf.cpp.
+
+For example, to measure the cost of calculating the size of a text item, you would first define a TextSize category by adding the following:
+
+\code
+//in qfxperf.h
+Q_DECLARE_PERFORMANCE_METRIC(TextSize);
+
+//in qfxperf.cpp
+Q_DEFINE_PERFORMANCE_METRIC(TextSize, "Text Size Calculation");
+\endcode
+
+You could then use this category in the code:
+
+\code
+void QmlGraphicsText::updateSize()
+{
+ QmlPerfTimer<QmlPerf::TextSize> perf;
+ ...
+}
+\endcode
+
+Because there is no cost for a QmlPerfTimer when Q_ENABLE_PERFORMANCE_LOG is not defined, this line can persist in the code and be used to help detect performance bottlenecks and regressions. See the QPerformanceLog documentation for more information on this performance framework.
+
+\section1 FPS Measurements
+
+When running the viewer, pressing 'F2' on the keyboard while a QML program is running will cause information on cost-per-frame and frames-per-second (FPS) to be printed to the console.
+
+The information printed includes:
+\list
+\o \e repaint(): the total time spent painting.
+\o \e paint(): the time spent by Qt painting.
+\o \e timeBetweenFrames: the total time spent per frame. This number minus repaint() gives a good idea of how much time is spent on things besides painting. A high number here with a low number for repaint() indicates expensive calculations happening each frame.
+\endlist
+
+\section1 Improving Performance
+
+The following tips can help decrease startup time for QML-based appications.
+
+\section2 Images
+
+\list
+\o Use jpg instead of png for photo-like images. On the N810, this can save 150ms for a large (320x480) image.
+
+\o If you are configuring Qt, configure out any image plugins you don't plan to support (mng and svg are the most expensive). On the N810, this can save 75-100ms startup time. For example:
+
+\code
+configure -no-libmng -no-svg -no-libtiff
+\endcode
+
+\o In some cases running pngcrush, optipng, gifsicle or other similar tools can give some improvement.
+
+We are also investigating support for the loading of uncompressed images. This will provide opportunites to decrease startup time at the cost of increased storage space.
+\endlist
+
+\section2 Fonts
+
+\list
+\o Use qpf instead of ttf. When using multiple font sizes and weights on the N810, this can save 125ms startup time compared to a ttf 'clean' run, and 40-50ms on subsequent runs (ttfs are shared by open applications).
+\endlist
+
+*/
+
+*/
diff --git a/doc/src/declarative/modules.qdoc b/doc/src/declarative/modules.qdoc
new file mode 100644
index 0000000..368595f
--- /dev/null
+++ b/doc/src/declarative/modules.qdoc
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlmodules.html
+\title Modules
+
+A \bold module is a collection of QML types.
+
+To use types from a module it must be imported using the \c import statement. Successive
+import statements override earlier import statements, however, since imports have version
+qualifiers, changes in modules do not alter the semantics of imports.
+
+\section1 Importing Types Defined in C++
+
+Types \link adding-types defined in C++\endlink can be from types your application defines, standard QML types,
+or types defined in plugins. To use any such types, you must import
+the module defining them. For example, to use types from Qt, import it:
+
+\code
+import Qt 4.6
+\endcode
+
+This makes available all types in Qt that were available in Qt 4.6, regardless of the
+actual version of Qt executing the QML. So even if Qt 4.7 adds a type that would conflict
+with a type you defined while using 4.6, that type is not imported, so there is no conflict.
+
+Types defined by plugins are made using QmlModulePlugin. Installed plugins and QML files
+can both contribute types to the same module.
+
+
+\section1 Importing Types Defined in QML
+
+When importing types \link components defined using QML\endlink, the syntax depends
+on whether or not the types are installed on the system.
+
+
+\section2 Installed QML Files
+
+To import types defined in QML files that are installed on the system running the
+QML, a URI import is used:
+
+\code
+import com.nokia.Example 1.0
+\endcode
+
+Files imported in this way are found on the paths added by QmlEngine::addImportPath(),
+which by default only inludes \c $QTDIR/qml, so the above would make available those types
+defined in \c $QTDIR/qml/com/nokia/Example which are specified as being in version 1.0.
+Installed plugins and QML files can both contribute types to the same module.
+
+The specification of types to versions is given by a special file, \c qmldir which must
+exist in the module directory. The syntax is described below.
+
+The \c -L option to the \l {qmlviewer}{viewer} application also adds paths to the import path.
+
+
+\section2 Local QML Files
+
+To import types defined in QML files in directories relative to the file importing them,
+a quoted import directory is used:
+
+\code
+import "path"
+\endcode
+
+This allows all components defined in the directory \c path to be used in
+the component where this statement appears.
+
+In this case, and only this case, it is not necessary for the module directory to include
+a \c qmldir file, nor is it necessary to provide a version qualifier. The basis of this is
+that the files in the subdirectory are assumed to be packaged with the importer, and therefore
+they form a single versioned unit.
+
+
+\section2 Remote QML Files
+
+To import types defined in QML file at arbitrary network locations, a quoted absolute URL is used:
+
+\code
+import "http://url/.../" 1.0
+\endcode
+
+This works the same as for relative directory imports, except that the target location \e must
+include a \c qmldir file, and a version qualifier must be given.
+
+
+\section2 The \c qmldir File
+
+Directories of installed files and remote content must include a file \c qmldir which specifies the
+mapping from all type names to versioned QML files. It is a list of lines of the form:
+
+\code
+# <Comment>
+<TypeName> <InitialVersion> <File>
+\endcode
+
+<TypeName> is the type being made available; <InitialVersion> is a version
+number like \c 4.0; <File> is the (relative)
+file name of the QML file defining the type.
+
+The same type can be provided by different files in different versions, in which
+case later earlier versions (eg. 1.2) must precede earlier versions (eg. 1.0),
+since the \e first name-version match is used.
+
+Installed files do not need to import the module of which they are a part, as they can refer
+to the other QML files in the module as relative (local) files.
+
+Installed and remote files \e must be referred to by version information described above,
+local files \e may have it.
+
+The versioning system ensures that a given QML file will work regardless of the version
+of installed software, since a versioned import \e only imports types for that version,
+leaving other identifiers available, even if the actual installed version might otherwise
+use those identifiers.
+
+
+\section1 Namespaces - Named Imports
+
+When importing content it by default imports types into the global namespace.
+You may choose to import the module into another namespace, either to allow identically-named
+types to be referenced, or purely for readability.
+
+To import a module into a namespace:
+
+\code
+import Qt 4.6 as TheQtLibrary
+\endcode
+
+Types from Qt 4.6 may then be used, but only by qualifying them with the namespace:
+
+\code
+TheQtLibrary.Rectangle { ... }
+\endcode
+
+Multiple modules can be imported into the same namespace in the same way that multiple
+modules can be imported into the global namespace:
+
+\code
+import Qt 4.6 as Nokia
+import Ovi 1.0 as Nokia
+\endcode
+*/
+
+/*
+
+See original requirement QT-558.
+
+*/
diff --git a/doc/src/declarative/network.qdoc b/doc/src/declarative/network.qdoc
new file mode 100644
index 0000000..ed20e66e
--- /dev/null
+++ b/doc/src/declarative/network.qdoc
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlnetwork.html
+\title Network Transparency
+
+QML supports network transparency by using URLs (rather than file names) for all
+references from a QML document to other content:
+
+\qml
+Image {
+ source: "http://www.example.com/images/logo.png"
+}
+\endqml
+
+Since a \e relative URL is the same
+as a relative file, development of QML on regular file systems remains simple:
+
+\qml
+Image {
+ source: "images/logo.png"
+}
+\endqml
+
+Network transparency is supported throughout QML, for example:
+
+\list
+\o Scripts - the \c source property of \l Script is a URL
+\o Fonts - the \c source property of FontLoader is a URL
+\o WebViews - the \c url property of WebView (obviously!)
+\endlist
+
+Even QML types themselves can be on the network - if \l qmlviewer is used to load
+\tt http://example.com/mystuff/Hello.qml and that content refers to a type "World", this
+will load from \tt http://example.com/mystuff/World.qml just as it would for a local file.
+Any other resources that \tt Hello.qml referred to, usually by a relative URL, would
+similarly be loaded from the network.
+
+
+\section1 Relative vs. Absolute URLs
+
+Whenever an object has a property of type URL (QUrl), assigning a string to that
+property will actually assign an absolute URL - by resolving the string against
+the URL of the document where the string is used.
+
+For example, consider this content in \tt{http://example.com/mystuff/test.qml}:
+
+\qml
+Image {
+ source: "images/logo.png"
+}
+\endqml
+
+The \l Image source property will be assigned \tt{http://example.com/mystuff/images/logo.png},
+but while the QML is being developed, in say \tt C:\\User\\Fred\\Documents\\MyStuff\\test.qml, it will be assigned
+\tt C:\\User\\Fred\\Documents\\MyStuff\\images\\logo.png.
+
+If the string assigned to a URL is already an absolute URL, then "resolving" does
+not change it and the URL is assigned directly.
+
+
+\section1 Progressive Loading
+
+Because of the declarative nature of QML and the asynchronous nature of network resources,
+objects which reference network resource generally change state as the network resource loads.
+For example, an Image with a network source will initially have
+a \c width and \c height of 0, a \c status of \c Loading, and a \c progress of 0.0.
+While the content loads, the \c progress will increase until
+the content is fully loaded from the network,
+at which point the \c width and \c height become the content size, the \c status becomes \c Ready, and the \c progress reaches 1.0.
+Applications can bind to these changing states to provide visual progress indicators where appropriate, or simply
+bind to the \c width and \c height as if the content was a local file, adapting as those bound values change.
+
+Note that when objects reference local files they immediately have the \c Ready status, but applications wishing
+to remain network transparent should not rely on this. Future versions of QML may also use asynchronous local file I/O
+to improve performance.
+
+
+\section1 Accessing Network Services
+
+QML types such as XmlListModel, and JavaScript classes like XMLHttpRequest are intended
+entirely for accessing network services, which usually respond with references to
+content by URLs that can then be used directly in QML. For example, using these facilities
+to access an on-line photography service would provide the QML application with URLs to
+photographs, which can be directly set on an \l Image \c source property.
+
+See the \tt demos/declarative/flickr for a real demonstration of this.
+
+
+\section1 Configuring the Network Access Manager
+
+All network access from QML is managed by a QNetworkAccessManager set on the QmlEngine which executes the QML.
+By default, this is an unmodified Qt QNetworkAccessManager. You may set a different manager using
+QmlEngine::setNetworkAccessManager() as appropriate for the policies of your application.
+For example, the \l qmlviewer tool sets a new QNetworkAccessManager which
+trusts HTTP Expiry headers to avoid network cache checks, allows HTTP Pipelining, adds a persistent HTTP CookieJar,
+a simple disk cache, and supports proxy settings.
+
+
+\section1 QRC Resources
+
+One of the URL schemes built into Qt is the "qrc" scheme. This allows content to be compiled into
+the executable using \l{The Qt Resource System}. Using this, an executable can reference QML content
+that is compiled into the executable:
+
+\code
+ QmlView *canvas = new QmlView;
+ canvas->setUrl(QUrl("qrc:/dial.qml"));
+\endcode
+
+The content itself can then use relative URLs, and so be transparently unaware that the content is
+compiled into the executable.
+
+
+\section1 Limitations
+
+The \c import statement is only network transparent if it has an "as" clause.
+
+More specifically:
+\list
+\o \c{import "dir"} only works on local file systems
+\o \c{import libraryUri} only works on local file systems
+\o \c{import "dir" as D} works network transparently
+\o \c{import libraryUrl as U} works network transparently
+\endlist
+
+
+*/
diff --git a/doc/src/declarative/pics/3d-axis.png b/doc/src/declarative/pics/3d-axis.png
new file mode 100644
index 0000000..1a587ff
--- /dev/null
+++ b/doc/src/declarative/pics/3d-axis.png
Binary files differ
diff --git a/doc/src/declarative/pics/3d-rotation-axis.png b/doc/src/declarative/pics/3d-rotation-axis.png
new file mode 100644
index 0000000..b940215
--- /dev/null
+++ b/doc/src/declarative/pics/3d-rotation-axis.png
Binary files differ
diff --git a/doc/src/declarative/pics/BorderImage.png b/doc/src/declarative/pics/BorderImage.png
new file mode 100644
index 0000000..651dd8a
--- /dev/null
+++ b/doc/src/declarative/pics/BorderImage.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewHighlight.png b/doc/src/declarative/pics/ListViewHighlight.png
new file mode 100644
index 0000000..02bf51d
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewHighlight.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewHorizontal.png b/doc/src/declarative/pics/ListViewHorizontal.png
new file mode 100644
index 0000000..4633a0e
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewHorizontal.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewSections.png b/doc/src/declarative/pics/ListViewSections.png
new file mode 100644
index 0000000..9270126
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewSections.png
Binary files differ
diff --git a/doc/src/declarative/pics/ListViewVertical.png b/doc/src/declarative/pics/ListViewVertical.png
new file mode 100644
index 0000000..e0b23d9
--- /dev/null
+++ b/doc/src/declarative/pics/ListViewVertical.png
Binary files differ
diff --git a/doc/src/declarative/pics/anatomy-component.png b/doc/src/declarative/pics/anatomy-component.png
new file mode 100644
index 0000000..70ed983
--- /dev/null
+++ b/doc/src/declarative/pics/anatomy-component.png
Binary files differ
diff --git a/doc/src/declarative/pics/anchors.svg b/doc/src/declarative/pics/anchors.svg
new file mode 100644
index 0000000..08b00ed
--- /dev/null
+++ b/doc/src/declarative/pics/anchors.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg1910"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ inkscape:export-filename="/home/mbrasser/work/Kinetic/ngui/doc/src/pics/anchors_example2.png"
+ inkscape:export-xdpi="189.65207"
+ inkscape:export-ydpi="189.65207"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="anchors.svg">
+ <defs
+ id="defs1912" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="431.57095"
+ inkscape:cy="413.38853"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1386"
+ inkscape:window-height="971"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata1915">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:black;stroke-width:0.52033526;stroke-miterlimit:4;stroke-dasharray:1.04067054, 0.52033527;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2807"
+ width="36.245155"
+ height="32.204544"
+ x="390.23157"
+ y="574.62024" />
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:black;stroke-width:0.44547796;stroke-miterlimit:4;stroke-dasharray:0.89095592, 0.44547796;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2809"
+ width="59.048447"
+ height="14.601732"
+ x="430.82993"
+ y="574.9483" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="399.40982"
+ y="594.76312"
+ id="text3696"><tspan
+ sodipodi:role="line"
+ id="tspan3698"
+ x="399.40982"
+ y="594.76312">pic</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="445.84048"
+ y="586.5423"
+ id="text3700"><tspan
+ sodipodi:role="line"
+ id="tspan3702"
+ x="445.84048"
+ y="586.5423">label</tspan></text>
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/animatedimageitem.gif b/doc/src/declarative/pics/animatedimageitem.gif
new file mode 100644
index 0000000..85c3cb5
--- /dev/null
+++ b/doc/src/declarative/pics/animatedimageitem.gif
Binary files differ
diff --git a/doc/src/declarative/pics/axisrotation.png b/doc/src/declarative/pics/axisrotation.png
new file mode 100644
index 0000000..4cddcdf
--- /dev/null
+++ b/doc/src/declarative/pics/axisrotation.png
Binary files differ
diff --git a/doc/src/declarative/pics/blur_example.png b/doc/src/declarative/pics/blur_example.png
new file mode 100644
index 0000000..763b112
--- /dev/null
+++ b/doc/src/declarative/pics/blur_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/content.png b/doc/src/declarative/pics/content.png
new file mode 100644
index 0000000..47a98ac
--- /dev/null
+++ b/doc/src/declarative/pics/content.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-adv-tutorial1.png b/doc/src/declarative/pics/declarative-adv-tutorial1.png
new file mode 100644
index 0000000..1699ab0
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-adv-tutorial1.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-adv-tutorial2.png b/doc/src/declarative/pics/declarative-adv-tutorial2.png
new file mode 100644
index 0000000..ba27c44
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-adv-tutorial2.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-adv-tutorial3.png b/doc/src/declarative/pics/declarative-adv-tutorial3.png
new file mode 100644
index 0000000..d500434d
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-adv-tutorial3.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-adv-tutorial4.gif b/doc/src/declarative/pics/declarative-adv-tutorial4.gif
new file mode 100644
index 0000000..827458d
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-adv-tutorial4.gif
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus1.png b/doc/src/declarative/pics/declarative-qmlfocus1.png
new file mode 100644
index 0000000..fd05146
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus1.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus2.png b/doc/src/declarative/pics/declarative-qmlfocus2.png
new file mode 100644
index 0000000..a946e2c
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus2.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus3.png b/doc/src/declarative/pics/declarative-qmlfocus3.png
new file mode 100644
index 0000000..ba55f76
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus3.png
Binary files differ
diff --git a/doc/src/declarative/pics/declarative-qmlfocus4.png b/doc/src/declarative/pics/declarative-qmlfocus4.png
new file mode 100644
index 0000000..e21f2a6
--- /dev/null
+++ b/doc/src/declarative/pics/declarative-qmlfocus4.png
Binary files differ
diff --git a/doc/src/declarative/pics/dial-example.gif b/doc/src/declarative/pics/dial-example.gif
new file mode 100644
index 0000000..4e90ba9
--- /dev/null
+++ b/doc/src/declarative/pics/dial-example.gif
Binary files differ
diff --git a/doc/src/declarative/pics/edge1.png b/doc/src/declarative/pics/edge1.png
new file mode 100644
index 0000000..f4bc16d
--- /dev/null
+++ b/doc/src/declarative/pics/edge1.png
Binary files differ
diff --git a/doc/src/declarative/pics/edge2.png b/doc/src/declarative/pics/edge2.png
new file mode 100644
index 0000000..71bda8e
--- /dev/null
+++ b/doc/src/declarative/pics/edge2.png
Binary files differ
diff --git a/doc/src/declarative/pics/edge3.png b/doc/src/declarative/pics/edge3.png
new file mode 100644
index 0000000..51bb894
--- /dev/null
+++ b/doc/src/declarative/pics/edge3.png
Binary files differ
diff --git a/doc/src/declarative/pics/edge4.png b/doc/src/declarative/pics/edge4.png
new file mode 100644
index 0000000..aee3bd1
--- /dev/null
+++ b/doc/src/declarative/pics/edge4.png
Binary files differ
diff --git a/doc/src/declarative/pics/edges.png b/doc/src/declarative/pics/edges.png
new file mode 100644
index 0000000..211b101
--- /dev/null
+++ b/doc/src/declarative/pics/edges.png
Binary files differ
diff --git a/doc/src/declarative/pics/edges.svg b/doc/src/declarative/pics/edges.svg
new file mode 100644
index 0000000..25698ca
--- /dev/null
+++ b/doc/src/declarative/pics/edges.svg
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser"
+ sodipodi:docname="edges.svg">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3850"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3856"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8583315"
+ inkscape:cx="372.04724"
+ inkscape:cy="596.15198"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1279"
+ inkscape:window-height="969"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:#0ca9fa;fill-opacity:1;stroke:black;stroke-width:0.04639034;stroke-miterlimit:4;stroke-dasharray:0.09278069, 0.04639034;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect1872"
+ width="33.656742"
+ height="39.808346"
+ x="208.86543"
+ y="390.22763"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 225.51888,380.99149 C 225.51888,439.06733 225.86873,439.06733 225.86873,439.06733"
+ id="path2760" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 242.97392,380.99149 C 242.97392,439.06733 243.32377,439.06733 243.32377,439.06733"
+ id="path3647" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 208.33832,380.99149 C 208.33832,439.06733 208.68817,439.06733 208.68817,439.06733"
+ id="path3649" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,409.67956 C 256.44329,409.67956 256.09344,409.67956 256.09344,409.67956"
+ id="path3651" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,429.97112 C 256.44329,429.97112 256.09344,429.97112 256.09344,429.97112"
+ id="path3653" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,390.78742 C 256.44329,390.78742 256.09344,390.78742 256.09344,390.78742"
+ id="path3655" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.54242"
+ y="393.58627"
+ id="text3657"><tspan
+ sodipodi:role="line"
+ id="tspan3659"
+ x="258.54242"
+ y="393.58627"
+ style="font-size:10px">Top</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.78955"
+ y="412.28455"
+ id="text3661"><tspan
+ sodipodi:role="line"
+ id="tspan3663"
+ x="258.78955"
+ y="412.28455"
+ style="font-size:10px">VerticalCenter</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="260.18896"
+ y="433.27582"
+ id="text3665"><tspan
+ sodipodi:role="line"
+ id="tspan3667"
+ x="260.18896"
+ y="433.27582"
+ style="font-size:10px">Bottom</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="198.96443"
+ y="376.24954"
+ id="text3669"><tspan
+ sodipodi:role="line"
+ id="tspan3671"
+ x="198.96443"
+ y="376.24954"
+ style="font-size:10px">Left</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="230.55408"
+ y="375.39383"
+ id="text3673"><tspan
+ sodipodi:role="line"
+ id="tspan3675"
+ x="230.55408"
+ y="375.39383"
+ style="font-size:10px">Right</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="186.71951"
+ y="355.25827"
+ id="text3677"><tspan
+ sodipodi:role="line"
+ id="tspan3679"
+ x="186.71951"
+ y="355.25827"
+ style="font-size:10px">HorizontalCenter</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Mstart)"
+ d="M 224.2567,375.39382 C 227.40539,356.85154 227.75525,357.20139 227.75525,357.20139"
+ id="path3681" />
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/edges_examples.svg b/doc/src/declarative/pics/edges_examples.svg
new file mode 100644
index 0000000..31e9901
--- /dev/null
+++ b/doc/src/declarative/pics/edges_examples.svg
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg3885"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ inkscape:export-filename="/home/mbrasser/edge4.png"
+ inkscape:export-xdpi="189.65207"
+ inkscape:export-ydpi="189.65207"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="edges_examples.svg">
+ <defs
+ id="defs3887" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2"
+ inkscape:cx="162.62912"
+ inkscape:cy="591.92069"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="928"
+ inkscape:window-height="624"
+ inkscape:window-x="0"
+ inkscape:window-y="495" />
+ <metadata
+ id="metadata3890">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:#0ca9fa;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3893"
+ width="50"
+ height="50"
+ x="100"
+ y="414.36218" />
+ <rect
+ style="opacity:1;fill:#fa0c2a;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3895"
+ width="104"
+ height="50"
+ x="150"
+ y="414.36218" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="109"
+ y="443.65125"
+ id="text3897"><tspan
+ sodipodi:role="line"
+ id="tspan3899"
+ x="109"
+ y="443.65125">rect1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="186.54297"
+ y="443.65125"
+ id="text3901"><tspan
+ sodipodi:role="line"
+ id="tspan3903"
+ x="186.54297"
+ y="443.65125">rect2</tspan></text>
+ <rect
+ style="opacity:1;fill:#0ca9fa;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3905"
+ width="50"
+ height="50"
+ x="254"
+ y="414.36218" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="263"
+ y="443.65125"
+ id="text3907"><tspan
+ sodipodi:role="line"
+ id="tspan3909"
+ x="263"
+ y="443.65125">rect3</tspan></text>
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/edges_qml.png b/doc/src/declarative/pics/edges_qml.png
new file mode 100644
index 0000000..73f22f9
--- /dev/null
+++ b/doc/src/declarative/pics/edges_qml.png
Binary files differ
diff --git a/doc/src/declarative/pics/edges_qml.svg b/doc/src/declarative/pics/edges_qml.svg
new file mode 100644
index 0000000..1814ec6
--- /dev/null
+++ b/doc/src/declarative/pics/edges_qml.svg
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="edges_qml.svg"
+ inkscape:export-filename="/home/mbrasser/edges_qml.png"
+ inkscape:export-xdpi="284.45999"
+ inkscape:export-ydpi="284.45999">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3850"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3856"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8583315"
+ inkscape:cx="372.04724"
+ inkscape:cy="596.15198"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1279"
+ inkscape:window-height="969"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:#0ca9fa;fill-opacity:1;stroke:black;stroke-width:0.04639034;stroke-miterlimit:4;stroke-dasharray:0.09278069, 0.04639034;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect1872"
+ width="33.656742"
+ height="39.808346"
+ x="208.86543"
+ y="390.22763"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 225.51888,380.99149 C 225.51888,439.06733 225.86873,439.06733 225.86873,439.06733"
+ id="path2760" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 242.97392,380.99149 C 242.97392,439.06733 243.32377,439.06733 243.32377,439.06733"
+ id="path3647" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 208.33832,380.99149 C 208.33832,439.06733 208.68817,439.06733 208.68817,439.06733"
+ id="path3649" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,409.67956 C 256.44329,409.67956 256.09344,409.67956 256.09344,409.67956"
+ id="path3651" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,429.97112 C 256.44329,429.97112 256.09344,429.97112 256.09344,429.97112"
+ id="path3653" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 195.91848,390.78742 C 256.44329,390.78742 256.09344,390.78742 256.09344,390.78742"
+ id="path3655" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.54242"
+ y="393.58627"
+ id="text3657"><tspan
+ sodipodi:role="line"
+ id="tspan3659"
+ x="258.54242"
+ y="393.58627"
+ style="font-size:10px">top</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.78955"
+ y="412.28455"
+ id="text3661"><tspan
+ sodipodi:role="line"
+ id="tspan3663"
+ x="258.78955"
+ y="412.28455"
+ style="font-size:10px">verticalCenter</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="260.18896"
+ y="433.27582"
+ id="text3665"><tspan
+ sodipodi:role="line"
+ id="tspan3667"
+ x="260.18896"
+ y="433.27582"
+ style="font-size:10px">bottom</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="200.96443"
+ y="376.24954"
+ id="text3669"><tspan
+ sodipodi:role="line"
+ id="tspan3671"
+ x="200.96443"
+ y="376.24954"
+ style="font-size:10px">left</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="232.55408"
+ y="375.39383"
+ id="text3673"><tspan
+ sodipodi:role="line"
+ id="tspan3675"
+ x="232.55408"
+ y="375.39383"
+ style="font-size:10px">right</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="190.71951"
+ y="355.25827"
+ id="text3677"><tspan
+ sodipodi:role="line"
+ id="tspan3679"
+ x="190.71951"
+ y="355.25827"
+ style="font-size:10px">horizontalCenter</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-opacity:1"
+ d="M 226.2567,375.39382 C 229.40539,356.85154 229.75525,357.20139 229.75525,357.20139"
+ id="path3681" />
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/flickable.gif b/doc/src/declarative/pics/flickable.gif
new file mode 100644
index 0000000..f7a3319
--- /dev/null
+++ b/doc/src/declarative/pics/flickable.gif
Binary files differ
diff --git a/doc/src/declarative/pics/flipable.gif b/doc/src/declarative/pics/flipable.gif
new file mode 100644
index 0000000..6386f06
--- /dev/null
+++ b/doc/src/declarative/pics/flipable.gif
Binary files differ
diff --git a/doc/src/declarative/pics/gradient.png b/doc/src/declarative/pics/gradient.png
new file mode 100644
index 0000000..5eefdd2
--- /dev/null
+++ b/doc/src/declarative/pics/gradient.png
Binary files differ
diff --git a/doc/src/declarative/pics/gridLayout_example.png b/doc/src/declarative/pics/gridLayout_example.png
new file mode 100644
index 0000000..6b120e9
--- /dev/null
+++ b/doc/src/declarative/pics/gridLayout_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/gridview.png b/doc/src/declarative/pics/gridview.png
new file mode 100644
index 0000000..3726893
--- /dev/null
+++ b/doc/src/declarative/pics/gridview.png
Binary files differ
diff --git a/doc/src/declarative/pics/highlight.gif b/doc/src/declarative/pics/highlight.gif
new file mode 100644
index 0000000..fbef256
--- /dev/null
+++ b/doc/src/declarative/pics/highlight.gif
Binary files differ
diff --git a/doc/src/declarative/pics/horizontalpositioner_example.png b/doc/src/declarative/pics/horizontalpositioner_example.png
new file mode 100644
index 0000000..42f90ec
--- /dev/null
+++ b/doc/src/declarative/pics/horizontalpositioner_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/margins_qml.png b/doc/src/declarative/pics/margins_qml.png
new file mode 100644
index 0000000..d7d73a3
--- /dev/null
+++ b/doc/src/declarative/pics/margins_qml.png
Binary files differ
diff --git a/doc/src/declarative/pics/margins_qml.svg b/doc/src/declarative/pics/margins_qml.svg
new file mode 100644
index 0000000..1f0ff02
--- /dev/null
+++ b/doc/src/declarative/pics/margins_qml.svg
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="margins_qml.svg"
+ inkscape:export-filename="/home/mbrasser/edges_qml.png"
+ inkscape:export-xdpi="284.45999"
+ inkscape:export-ydpi="284.45999">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path2976"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path2979"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3850"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3856"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8583315"
+ inkscape:cx="372.04724"
+ inkscape:cy="596.15198"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1279"
+ inkscape:window-height="969"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:#0ca9fa;fill-opacity:1;stroke:black;stroke-width:0.04639034;stroke-miterlimit:4;stroke-dasharray:0.09278069, 0.04639034;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect1872"
+ width="33.656742"
+ height="39.808346"
+ x="208.86543"
+ y="390.22763"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02602077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02602088, 1.02602088;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 252.98692,377.00435 C 252.98692,443.05433 253.31077,443.05433 253.31077,443.05433"
+ id="path3647" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02601969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02602007, 1.02602007;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 198.35134,377.00433 C 198.35134,443.05431 198.67515,443.05431 198.67515,443.05431"
+ id="path3649" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02421367;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02421381, 1.02421381;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 193.94282,437.97112 C 257.43421,437.97112 257.06721,437.97112 257.06721,437.97112"
+ id="path3653" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.02421367;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.02421381, 1.02421381;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 193.94282,380.78742 C 257.43421,380.78742 257.06721,380.78742 257.06721,380.78742"
+ id="path3655" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="260.29169"
+ y="388.78741"
+ id="text1911"><tspan
+ sodipodi:role="line"
+ id="tspan1913"
+ x="260.29169"
+ y="388.78741"
+ style="font-size:10px">topMargin</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="259.65204"
+ y="437.27798"
+ id="text1915"><tspan
+ sodipodi:role="line"
+ id="tspan1917"
+ x="259.65204"
+ y="437.27798"
+ style="font-size:10px">bottomMargin</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="170.07939"
+ y="454.4209"
+ id="text1919"><tspan
+ sodipodi:role="line"
+ id="tspan1921"
+ x="170.07939"
+ y="454.4209"
+ style="font-size:10px">leftMargin</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="228.47504"
+ y="454.4209"
+ id="text1923"><tspan
+ sodipodi:role="line"
+ id="tspan1925"
+ x="228.47504"
+ y="454.4209"
+ style="font-size:10px">rightMargin</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.92020172px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 225.6938,382.51213 C 225.6938,388.91693 225.6938,388.91693 225.6938,388.91693"
+ id="path1929" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.92007709px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 225.6938,430.56703 C 225.6938,436.97192 225.6938,436.97192 225.6938,436.97192"
+ id="path3000" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-mid:none;marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 201.16631,410.1318 C 207.81355,410.1318 207.81355,410.1318 207.81355,410.1318"
+ id="path3002" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Sstart);marker-mid:none;marker-end:url(#Arrow1Send);stroke-opacity:1"
+ d="M 244.02348,410.1318 C 250.67072,410.1318 250.67072,410.1318 250.67072,410.1318"
+ id="path3889" />
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/particles.gif b/doc/src/declarative/pics/particles.gif
new file mode 100644
index 0000000..763a8a8
--- /dev/null
+++ b/doc/src/declarative/pics/particles.gif
Binary files differ
diff --git a/doc/src/declarative/pics/pathview.gif b/doc/src/declarative/pics/pathview.gif
new file mode 100644
index 0000000..4052eb2
--- /dev/null
+++ b/doc/src/declarative/pics/pathview.gif
Binary files differ
diff --git a/doc/src/declarative/pics/positioner-add.gif b/doc/src/declarative/pics/positioner-add.gif
new file mode 100644
index 0000000..86e9247
--- /dev/null
+++ b/doc/src/declarative/pics/positioner-add.gif
Binary files differ
diff --git a/doc/src/declarative/pics/positioner-move.gif b/doc/src/declarative/pics/positioner-move.gif
new file mode 100644
index 0000000..1825c22
--- /dev/null
+++ b/doc/src/declarative/pics/positioner-move.gif
Binary files differ
diff --git a/doc/src/declarative/pics/positioner-remove.gif b/doc/src/declarative/pics/positioner-remove.gif
new file mode 100644
index 0000000..7086511
--- /dev/null
+++ b/doc/src/declarative/pics/positioner-remove.gif
Binary files differ
diff --git a/doc/src/declarative/pics/propanim.gif b/doc/src/declarative/pics/propanim.gif
new file mode 100644
index 0000000..f86406e
--- /dev/null
+++ b/doc/src/declarative/pics/propanim.gif
Binary files differ
diff --git a/doc/src/declarative/pics/qml-context-object.png b/doc/src/declarative/pics/qml-context-object.png
new file mode 100644
index 0000000..1b91aff
--- /dev/null
+++ b/doc/src/declarative/pics/qml-context-object.png
Binary files differ
diff --git a/doc/src/declarative/pics/qml-context-tree.png b/doc/src/declarative/pics/qml-context-tree.png
new file mode 100644
index 0000000..6bba5f4
--- /dev/null
+++ b/doc/src/declarative/pics/qml-context-tree.png
Binary files differ
diff --git a/doc/src/declarative/pics/qml-context.png b/doc/src/declarative/pics/qml-context.png
new file mode 100644
index 0000000..bdf2ecd
--- /dev/null
+++ b/doc/src/declarative/pics/qml-context.png
Binary files differ
diff --git a/doc/src/declarative/pics/qml-scope.png b/doc/src/declarative/pics/qml-scope.png
new file mode 100644
index 0000000..be025c8
--- /dev/null
+++ b/doc/src/declarative/pics/qml-scope.png
Binary files differ
diff --git a/doc/src/declarative/pics/qmldebugger-creator.png b/doc/src/declarative/pics/qmldebugger-creator.png
new file mode 100644
index 0000000..da1e22d
--- /dev/null
+++ b/doc/src/declarative/pics/qmldebugger-creator.png
Binary files differ
diff --git a/doc/src/declarative/pics/qtlogo.png b/doc/src/declarative/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/doc/src/declarative/pics/qtlogo.png
Binary files differ
diff --git a/doc/src/declarative/pics/rect-smooth.png b/doc/src/declarative/pics/rect-smooth.png
new file mode 100644
index 0000000..abbb0a9
--- /dev/null
+++ b/doc/src/declarative/pics/rect-smooth.png
Binary files differ
diff --git a/doc/src/declarative/pics/reflection_example.png b/doc/src/declarative/pics/reflection_example.png
new file mode 100644
index 0000000..fd9bb48
--- /dev/null
+++ b/doc/src/declarative/pics/reflection_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/repeater-index.png b/doc/src/declarative/pics/repeater-index.png
new file mode 100644
index 0000000..3dbe6d0
--- /dev/null
+++ b/doc/src/declarative/pics/repeater-index.png
Binary files differ
diff --git a/doc/src/declarative/pics/repeater.png b/doc/src/declarative/pics/repeater.png
new file mode 100644
index 0000000..973df27
--- /dev/null
+++ b/doc/src/declarative/pics/repeater.png
Binary files differ
diff --git a/doc/src/declarative/pics/scalegrid.svg b/doc/src/declarative/pics/scalegrid.svg
new file mode 100644
index 0000000..e386f3d
--- /dev/null
+++ b/doc/src/declarative/pics/scalegrid.svg
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/mbrasser/work/Kinetic/ngui/doc/src/pics"
+ sodipodi:docname="scalegrid.svg"
+ inkscape:export-filename="/home/mbrasser/work/Kinetic/ngui/doc/src/pics/scalegrid.png"
+ inkscape:export-xdpi="189.65207"
+ inkscape:export-ydpi="189.65207">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="50"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="3.2163554"
+ inkscape:cx="173.89302"
+ inkscape:cy="703.69531"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:grid-bbox="false"
+ inkscape:guide-bbox="false"
+ inkscape:window-width="1409"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:red;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1876"
+ width="45.104"
+ height="45.137001"
+ x="119.16868"
+ y="301.00308"
+ rx="5"
+ ry="5" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.3965202;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304035, 0.39652018;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 157.02483,295.52571 C 157.02483,352.04784 157.02483,352.04784 157.02483,352.04784"
+ id="path2766" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.39652267;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304534, 0.39652268;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 126.2,295.64284 C 126.2,352.16567 126.2,352.16567 126.2,352.16567"
+ id="path2768" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.39652267;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304534, 0.39652268;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 169.05321,308.25967 C 112.53038,308.25967 112.53038,308.25967 112.53038,308.25967"
+ id="path2770" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.39652267;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.79304534, 0.39652268;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 169.08024,339.77238 C 112.55741,339.77238 112.55741,339.77238 112.55741,339.77238"
+ id="path2772" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
+ x="115.2857"
+ y="303.60583"
+ id="text2774"><tspan
+ sodipodi:role="line"
+ id="tspan2776"
+ x="115.2857"
+ y="303.60583">1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="137.19142"
+ y="303.60583"
+ id="text2782"><tspan
+ sodipodi:role="line"
+ id="tspan2784"
+ x="137.19142"
+ y="303.60583"
+ style="font-family:Arial Black">2</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
+ x="161.56842"
+ y="303.45935"
+ id="text2786"><tspan
+ sodipodi:role="line"
+ id="tspan2788"
+ x="161.56842"
+ y="303.45935">3</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="114.72613"
+ y="327.00702"
+ id="text2790"><tspan
+ sodipodi:role="line"
+ id="tspan2792"
+ x="114.72613"
+ y="327.00702"
+ style="font-family:Arial Black">4</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="137.12404"
+ y="326.86053"
+ id="text2794"><tspan
+ sodipodi:role="line"
+ id="tspan2796"
+ x="137.12404"
+ y="326.86053"
+ style="font-family:Arial Black">5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="161.49518"
+ y="326.86053"
+ id="text2798"><tspan
+ sodipodi:role="line"
+ id="tspan2800"
+ x="161.49518"
+ y="326.86053"
+ style="font-family:Arial Black">6</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="114.70855"
+ y="351.25809"
+ id="text2802"><tspan
+ sodipodi:role="line"
+ id="tspan2804"
+ x="114.70855"
+ y="351.25809"
+ style="font-family:Arial Black">7</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="137.08595"
+ y="351.1116"
+ id="text2806"><tspan
+ sodipodi:role="line"
+ id="tspan2808"
+ x="137.08595"
+ y="351.1116"
+ style="font-family:Arial Black">8</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="161.58307"
+ y="351.1116"
+ id="text2810"><tspan
+ sodipodi:role="line"
+ id="tspan2812"
+ x="161.58307"
+ y="351.1116"
+ style="font-family:Arial Black">9</tspan></text>
+ </g>
+</svg>
diff --git a/doc/src/declarative/pics/shadow_example.png b/doc/src/declarative/pics/shadow_example.png
new file mode 100644
index 0000000..6214620
--- /dev/null
+++ b/doc/src/declarative/pics/shadow_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/spacing_a.png b/doc/src/declarative/pics/spacing_a.png
new file mode 100644
index 0000000..c0fe895
--- /dev/null
+++ b/doc/src/declarative/pics/spacing_a.png
Binary files differ
diff --git a/doc/src/declarative/pics/spacing_b.png b/doc/src/declarative/pics/spacing_b.png
new file mode 100644
index 0000000..24cf640
--- /dev/null
+++ b/doc/src/declarative/pics/spacing_b.png
Binary files differ
diff --git a/doc/src/declarative/pics/squish-transform.png b/doc/src/declarative/pics/squish-transform.png
new file mode 100644
index 0000000..0eb848e
--- /dev/null
+++ b/doc/src/declarative/pics/squish-transform.png
Binary files differ
diff --git a/doc/src/declarative/pics/squish.png b/doc/src/declarative/pics/squish.png
new file mode 100644
index 0000000..73bf292
--- /dev/null
+++ b/doc/src/declarative/pics/squish.png
Binary files differ
diff --git a/doc/src/declarative/pics/switch-example.gif b/doc/src/declarative/pics/switch-example.gif
new file mode 100644
index 0000000..3d6582f
--- /dev/null
+++ b/doc/src/declarative/pics/switch-example.gif
Binary files differ
diff --git a/doc/src/declarative/pics/trivialListView.png b/doc/src/declarative/pics/trivialListView.png
new file mode 100644
index 0000000..dc5c6b3
--- /dev/null
+++ b/doc/src/declarative/pics/trivialListView.png
Binary files differ
diff --git a/doc/src/declarative/pics/verticalpositioner_example.png b/doc/src/declarative/pics/verticalpositioner_example.png
new file mode 100644
index 0000000..458dc7f
--- /dev/null
+++ b/doc/src/declarative/pics/verticalpositioner_example.png
Binary files differ
diff --git a/doc/src/declarative/pics/verticalpositioner_transition.gif b/doc/src/declarative/pics/verticalpositioner_transition.gif
new file mode 100644
index 0000000..ed61adb
--- /dev/null
+++ b/doc/src/declarative/pics/verticalpositioner_transition.gif
Binary files differ
diff --git a/doc/src/declarative/pics/webview.png b/doc/src/declarative/pics/webview.png
new file mode 100644
index 0000000..0d24586
--- /dev/null
+++ b/doc/src/declarative/pics/webview.png
Binary files differ
diff --git a/doc/src/declarative/propertybinding.qdoc b/doc/src/declarative/propertybinding.qdoc
new file mode 100644
index 0000000..ad4f13e
--- /dev/null
+++ b/doc/src/declarative/propertybinding.qdoc
@@ -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 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$
+**
+****************************************************************************/
+
+/*!
+\page propertybinding.html
+\title Property Binding
+
+Property binding is a declarative way of specifying the value of a property. Binding allows
+a property's value to be expressed as an JavaScript expression that defines the value relative
+to other property values or data accessible in the application. The property value is
+automatically kept up to date if the other properties or data values change.
+
+Property bindings are created implicitly in QML whenever a property is assigned an JavaScript
+expression. The following QML uses two property bindings to connect the size of the rectangle
+to that of \c otherItem.
+
+\code
+Rectangle {
+ width: otherItem.width
+ height: otherItem.height
+}
+\endcode
+
+QML extends a standards compliant JavaScript engine, so any valid JavaScript expression can be
+used as a property binding. Bindings can access object properties, make function calls and even
+use builtin JavaScript objects like \e {Date} and \e {Math}. Assigning a constant value to a
+property can even be thought of as a binding - afterall, a constant is a valid JavaScript
+expression! Here are some examples of more complex bindings:
+
+\code
+Rectangle {
+ Script {
+ function calculateMyHeight() {
+ return Math.max(otherItem.height, thirdItem.height);
+ }
+ }
+
+ anchors.centerIn: parent
+ width: Math.min(otherItem.width, 10)
+ height: calculateMyHeight()
+ color: { if (width > 10) "blue"; else "red" }
+}
+\endcode
+
+Being JavaScript expressions, bindings are evaluated in a scope chain. The \l {QML Scope}
+documentation covers the specifics of scoping in QML.
+
+\list
+\o When does a binding not get updated?
+\o Scope
+\o Assigning a constant/other binding clears existing binding
+\o Loops
+\o Using model data
+\endlist
+
+\section1 Binding Element
+
+The implicit binding syntax shown previously is easy to use and works perfectly for most uses
+of bindings. In some advanced cases, it is necessary to create bindings explicitly using the
+\l Binding element.
+
+For example, to bind a property exposed from C++ (\c system.brightness) to a value
+coming from QML (\c slider.value), you could use the Binding element as follows:
+\qml
+Binding {
+ target: system
+ property: "brightness"
+ value: slider.value
+}
+\endqml
+*/
+
diff --git a/doc/src/declarative/qmldebugging.qdoc b/doc/src/declarative/qmldebugging.qdoc
new file mode 100644
index 0000000..a6def19
--- /dev/null
+++ b/doc/src/declarative/qmldebugging.qdoc
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmldebugging.html
+\title Debugging QML
+
+\section1 Logging
+
+\c console.log can be used to print debugging information to the console. For example:
+
+\qml
+Rectangle {
+ width: 200; height: 200
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: console.log("clicked")
+ }
+}
+\endqml
+
+\section1 Debugging Transitions
+
+When a transition doesn't look quite right, it can be helpful to view it in slow
+motion to see what is happening more clearly. \l {qmlviewer} provides a
+"Slow Down Animations" menu option to facilitate this.
+
+
+\section1 The QML Inspector
+
+The \c qmldebugger tool provides an experimental inspector to aid with debugging.
+It can be run as a Qt Creator plugin or as a standalone application.
+
+\section2 Qt Creator plugin
+
+The Qt Creator plugin currently builds against Qt Creator 1.3.
+
+To build the Qt Creator plugin:
+
+\list
+\o Set an environment variable \c CREATOR_SRC_DIR that points to the Qt Creator
+ source directory
+\o Set an environment variable \c CREATOR_BUILD_DIR that points to the Qt Creator
+ build directory
+\o Run \c qmake on \c $QTDIR/tools/qmldebugger/qmldebugger.pro
+\endlist
+
+This builds the plugin into your Qt Creator installation.
+
+The plugin adds a "QML Inspect" mode into Qt Creator that provides:
+
+\list
+\o An object tree showing all objects and their children
+\o The current property values for the object selected in the object tree
+ (this table is dynamically updated for all properties that have property changed
+ notifications)
+\o An expression evaluator for querying and setting values dynamically
+\o A table of watched properties (double-click on a property in the property
+ table to add it to the watch table)
+\o A graph that shows the frame rate of your application
+\endlist
+
+
+To start the debugger, open a QML project and click the "QML Inspect" mode, then click the green
+"play" button in the toolbar of the bottom-right debugger window.
+
+\image qmldebugger-creator.png
+
+
+\section2 Standalone qmldebugger tool
+
+To run the standalone \c qmldebugger tool, set an environment variable \c QML_DEBUG_SERVER_PORT
+to an available port number and run the \c qmlviewer. For example:
+
+\code
+ QML_DEBUG_SERVER_PORT=3768 qmlviewer myqmlfile.qml
+\endcode
+
+Then in another process, start the \c qmldebugger tool, enter the port number into the corresponding spinbox
+in the top right hand corner, and press the "Connect" button.
+
+*/
diff --git a/doc/src/declarative/qmldocument.qdoc b/doc/src/declarative/qmldocument.qdoc
new file mode 100644
index 0000000..deb6e1c
--- /dev/null
+++ b/doc/src/declarative/qmldocument.qdoc
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmldocuments.html
+\title QML Documents
+
+A QML document is a block of QML source code. QML documents generally correspond to files
+stored on a disk or network resource, but can also be constructed directly from text data.
+
+Here is a simple QML document:
+
+\code
+import Qt 4.6
+
+Rectangle {
+ width: 240; height: 320;
+
+ resources: [
+ Component {
+ id: contactDelegate
+ Text {
+ text: modelData.firstName + " " + modelData.lastName
+ }
+ }
+ ]
+
+ ListView {
+ anchors.fill: parent
+ model: contactModel
+ delegate: contactDelegate
+ }
+}
+\endcode
+
+QML documents are always encoded in UTF-8 format.
+
+A QML document always begins with one or more import statements. To prevent elements
+introduced in later versions from affecting existing QML programs, the element types
+available within a document are controlled by the imported QML \l {Modules}. That is,
+QML is a \e versioned language.
+
+Syntactically a QML document is self contained; QML does \e not have a preprocessor that
+modifies the document prior to presentation to the QML runtime. \c import statements
+do not "include" code in the document, but instead instruct the QML runtime on how to
+resolve type references found in the document. Any type reference present in a QML
+document - such as \c Rectangle and \c ListView - including those made within an
+\l {JavaScript Block} or \l {Property Binding}s, are \e resolved based exclusively on the
+import statements. QML does not import any modules by default, so at least one \c import
+statement must be present or no elements will be available!
+
+A QML document defines a single, top-level \l {QmlComponent}{QML component}. A QML component
+is a template that is interpreted by the QML runtime to create an object with some predefined
+behaviour. As it is a template, a single QML component can be "run" multiple times to
+produce several objects, each of which are said to be \e instances of the component.
+
+Once created, instances are not dependent on the component that created them, so they can
+operate on independent data. Here is an example of a simple "button" component that is
+instantiated four times, each with a different value for its \c text property.
+
+\table
+\row
+\o
+\raw HTML
+<table><tr><td>
+\endraw
+\code
+import Qt 4.6
+
+BorderImage {
+ property alias text: textElement.text
+ width: 100; height: 30; source: "images/toolbutton.sci"
+
+ Text {
+ id: textElement
+ anchors.centerIn: parent
+ font.pointSize: 20
+ style: Text.Raised
+ color: "white"
+ }
+}
+\endcode
+\raw HTML
+</td> <td>
+\endraw
+\image anatomy-component.png
+\raw HTML
+</td> </tr> </table>
+\endraw
+\endtable
+
+In addition to the top-level component that all QML documents define, documents may also
+include additional \e inline components. Inline components are declared using the
+\l Component element, as can be seen in the first example above. Inline components share
+all the characteristics of regular top-level components and use the same \c import list as their
+containing QML document. Components are one of the most basic building blocks in QML, and are
+frequently used as "factories" by other elements. For example, the \l ListView element uses the
+\c delegate component as the template for instantiating list items - each list item is just a
+new instance of the component with the item specific data set appropriately.
+
+Like other \l {QML Elements}, the \l Component element is an object and must be assigned to a
+property. \l Component objects may also have an object id. In the first example on this page,
+the inline component is added to the \l Rectangle's \c resources list, and then
+\l {Property Binding} is used to assign the \l Component to the \l ListView's \c delegate
+property. While using property binding allows the \l Component object to be shared (for example,
+if the QML document contained multiple \l ListView's with the same delegate), in this case the
+\l Component could have been assigned directly to the \l ListView's \c delegate. The QML
+language even contains a syntactic optimization when assigning directly to a component property
+for this case where it will automatically insert the \l Component tag.
+
+These final two examples are behaviorally identical to the original document.
+
+\table
+\row
+\o
+\code
+import Qt 4.6
+
+Rectangle {
+ width: 240; height: 320;
+
+ ListView {
+ anchors.fill: parent
+ model: contactModel
+ delegate: Component {
+ Text {
+ text: modelData.firstName + " " + modelData.lastName
+ }
+ }
+ }
+}
+\endcode
+\o
+\code
+import Qt 4.6
+
+Rectangle {
+ width: 240; height: 320;
+
+ ListView {
+ anchors.fill: parent
+ model: contactModel
+ delegate: Text {
+ text: modelData.firstName + " " + modelData.lastName
+ }
+ }
+}
+\endcode
+\endtable
+
+\sa QmlComponent
+*/
diff --git a/doc/src/declarative/qmli18n.qdoc b/doc/src/declarative/qmli18n.qdoc
new file mode 100644
index 0000000..0c8b1d1
--- /dev/null
+++ b/doc/src/declarative/qmli18n.qdoc
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmli18n.html
+\title QML Internationalization
+
+\section1 Overview
+
+Strings in QML can be marked for translation using the qsTr(), qsTranslate(),
+QT_TR_NOOP(), and QT_TRANSLATE_NOOP() functions.
+
+For example:
+\qml
+Text { text: qsTr("Pictures") }
+\endqml
+
+These functions are standard QtScript functions; for more details see
+QScriptEngine::installTranslatorFunctions().
+
+QML relies on the core internationalization capabilities provided by Qt. These
+capabilities are described more fully in:
+\list
+\o \l {Internationalization with Qt}
+\o \l {Qt Linguist Manual}
+\endlist
+
+You can test a translation in \l {qmlviewer} using the -translation option.
+
+\section1 Example
+
+First we create a simple QML file with text to be translated. The string
+that needs to be translated is enclosed in a call to \c qsTr().
+
+hello.qml:
+\qml
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 200
+ Text { text: qsTr("Hello"); anchors.centerIn: parent }
+}
+\endqml
+
+Next we create a translation source file using lupdate:
+\code
+lupdate hello.qml -ts hello.ts
+\endcode
+
+Then we open \c hello.ts in \l {Linguist}, provide a translation
+and create the release file \c hello.qm.
+
+Finally, we can test the translation in qmlviewer:
+\code
+qmlviewer -translation hello.qm hello.qml
+\endcode
+*/
diff --git a/doc/src/declarative/qmlintro.qdoc b/doc/src/declarative/qmlintro.qdoc
new file mode 100644
index 0000000..3891515
--- /dev/null
+++ b/doc/src/declarative/qmlintro.qdoc
@@ -0,0 +1,350 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlintroduction.html
+\title Introduction to the QML language
+
+\tableofcontents
+
+QML is a declarative language designed to describe the user interface of a
+program: both what it looks like, and how it behaves. In QML, a user
+interface is specified as a tree of objects with properties.
+
+This introduction is meant for those with little or no programming
+experience. JavaScript is used as a scripting language in QML, so you may want
+to learn a bit more about it (\l{JavaScript: The Definitive Guide}) before diving
+deeper into QML. It's also helpful to have a basic understanding of other web
+technologies like HTML and CSS, but it's not required.
+
+\section1 Basic QML Syntax
+
+QML looks like this:
+
+\code
+Rectangle {
+ width: 200
+ height: 200
+ color: "white"
+ Image {
+ source: "pics/logo.png"
+ anchors.centerIn: parent
+ }
+}
+\endcode
+
+Objects are specified by their type, followed by a pair of braces. Object
+types always begin with a capital letter. In the above example, there are
+two objects, a \l Rectangle, and an \l Image. Between the braces, we can specify
+information about the object, such as its properties.
+
+Properties are specified as \c {property: value}. In the above example, we
+can see the Image has a property named \c source, which has been assigned the
+value \c "pics/logo.png". The property and its value are separated by a colon.
+
+Properties can be specified one-per-line:
+
+\code
+Rectangle {
+ width: 100
+ height: 100
+}
+\endcode
+
+or you can put multiple properties on a single line:
+
+\code
+Rectangle { width: 100; height: 100 }
+\endcode
+
+When multiple property/value pairs are specified on a single line, they
+must be separated by a semicolon.
+
+\section1 Expressions
+
+In addition to assigning values to properties, you can also assign
+expressions written in JavaScript.
+
+\code
+Rotation {
+ angle: 360 * 3
+}
+\endcode
+
+These expressions can include references to other objects and properties, in which case
+a \e binding is established: when the value of the expression changes, the property the
+expression has been assigned to is automatically updated to that value.
+
+\code
+Item {
+ Text {
+ id: text1
+ text: "Hello World"
+ }
+ Text {
+ id: text2
+ text: text1.text
+ }
+}
+\endcode
+
+In the example above, the \c text2 object will display the same text as \c text1. If \c text1 is changed,
+\c text2 is automatically changed to the same value.
+
+Note that to refer to other objects, we use their \e id values. (See below for more
+information on the \e id property.)
+
+\section1 QML Comments
+
+Commenting in QML is similar to JavaScript.
+\list
+\o Single line comments start with // and finish at the end of the line.
+\o Multiline comments start with /* and finish with *\/
+\endlist
+
+\quotefile doc/src/snippets/declarative/comments.qml
+
+Comments are ignored by the engine. The are useful for explaining what you
+are doing: for referring back to at a later date, or for others reading
+your QML files.
+
+Comments can also be used to prevent the execution of code, which is
+sometimes useful for tracking down problems.
+
+\code
+Text {
+ text: "Hello world!"
+ //opacity: 0.5
+}
+\endcode
+
+In the above example, the Text object will have normal opacity, since the
+line opacity: 0.5 has been turned into a comment.
+
+\section1 Properties
+\target intro-properties
+
+\section2 Property naming
+
+Properties begin with a lowercase letter (with the exception of \l{Attached Properties}).
+
+\section2 Property types
+
+QML supports properties of many types (see \l{Common QML Types}). The basic types include int,
+real, bool, string, color, and lists.
+
+\code
+Item {
+ x: 10.5 // a 'real' property
+ ...
+ state: "details" // a 'string' property
+ focus: true // a 'bool' property
+}
+\endcode
+
+QML properties are what is known as \e typesafe. That is, they only allow you to assign a value that
+matches the property type. For example, the \c x property of item is a real, and if you try to assign
+a string to it you will get an error.
+
+\badcode
+Item {
+ x: "hello" // illegal!
+}
+\endcode
+
+\section3 The \c id property
+
+Each object can be given a special unique property called an \e id. Assigning an id enables the object
+to be referred to by other objects and scripts.
+
+The first Rectangle element below has an \e id, "myRect". The second Rectange element defines its
+own width by referring to \tt myRect.width, which means it will have the same \tt width
+value as the first Rectangle element.
+
+\code
+Item {
+ Rectangle {
+ id: myRect
+ width: 100
+ height: 100
+ }
+ Rectangle {
+ width: myRect.width
+ height: 200
+ }
+}
+\endcode
+
+Note that an \e id must begin with a lower-case letter or an underscore, and cannot contain characters other than letters, numbers and underscores.
+
+
+\section2 List properties
+
+List properties look like this:
+
+\code
+Item {
+ children: [
+ Image {},
+ Text {}
+ ]
+}
+\endcode
+
+The list is enclosed in square brackets, with a comma separating the
+list elements. In cases where you are only assigning a single item to a
+list, you can omit the square brackets:
+
+\code
+Image {
+ children: Rectangle {}
+}
+\endcode
+
+\section2 Default properties
+
+Each object type can specify one of its list or object properties as its default property.
+If a property has been declared as the default property, the property tag can be omitted.
+
+For example this code:
+\code
+State {
+ changes: [
+ PropertyChanges {},
+ PropertyChanges {}
+ ]
+}
+\endcode
+
+can be simplified to:
+
+\code
+State {
+ PropertyChanges {}
+ PropertyChanges {}
+}
+\endcode
+
+because \c changes is the default property of the \c State type.
+
+\section2 Grouped Properties
+
+In some cases properties form a logical group and use a 'dot' or grouped notation
+to show this.
+
+Grouped properties can be written like this:
+\qml
+Text {
+ font.pixelSize: 12
+ font.bold: true
+}
+\endqml
+
+or like this:
+\qml
+Text {
+ font { pixelSize: 12; bold: true }
+}
+\endqml
+
+In the element documentation grouped properties are shown using the 'dot' notation.
+
+\section2 Attached Properties
+\target attached-properties
+
+Some objects attach properties to another object. Attached Properties
+are of the form \e {Type.property} where \e Type is the type of the
+element that attaches \e property.
+
+For example:
+\code
+Component {
+ id: myDelegate
+ Text {
+ text: "Hello"
+ color: ListView.isCurrentItem ? "red" : "blue"
+ }
+}
+ListView {
+ delegate: myDelegate
+}
+\endcode
+
+The \l ListView element attaches the \e ListView.isCurrentItem property
+to each delegate it creates.
+
+Another example of attached properties is the \l Keys element which
+attaches properties for handling key presses to
+any visual Item, for example:
+
+\code
+Item {
+ focus: true
+ Keys.onSelectPressed: console.log("Selected")
+}
+\endcode
+
+\section2 Signal Handlers
+
+Signal handlers allow actions to be taken in reponse to an event. For instance,
+the \l MouseRegion element has signal handlers to handle mouse press, release
+and click:
+
+\code
+MouseRegion {
+ onPressed: console.log("mouse button pressed")
+}
+\endcode
+
+All signal handlers begin with \e "on".
+
+Some signal handlers include an optional parameter, for example
+the MouseRegion onPressed signal handler has a \e mouse parameter:
+
+\code
+MouseRegion {
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onPressed: if (mouse.button == Qt.RightButton) console.log("Right mouse button pressed")
+}
+\endcode
+
+
+*/
diff --git a/doc/src/declarative/qmlmodels.qdoc b/doc/src/declarative/qmlmodels.qdoc
new file mode 100644
index 0000000..008ea2a
--- /dev/null
+++ b/doc/src/declarative/qmlmodels.qdoc
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlmodels.html
+\target qmlmodels
+\title Data Models
+
+Some QML Items use Data Models to provide the data to be displayed.
+These items typically require a \e delegate component that
+creates an instance for each item in the model. Models may be static, or
+have items modified, inserted, removed or moved dynamically.
+
+Data is provided to the delegate via named data roles which the
+delegate may bind to. The roles are exposed as properties of the
+\e model context property, though this property is set as a default property
+of the delegate so, unless there is a naming clash with a
+property in the delegate, the roles are usually accessed unqualified. The
+example below would have a clash between he \e color role of the model and
+the \e color property of the Rectangle. The clash is avoided by referencing
+the \e color property of the model by its full name: \e model.color.
+
+\code
+ListModel {
+ id: myModel
+ ListElement { color: "red" }
+ ListElement { color: "green" }
+}
+
+Component {
+ id: myDelegate
+ Rectangle {
+ width: 20; height: 20
+ color: model.color
+ }
+}
+\endcode
+
+A special \e index role containing the index of the item in the model
+is also available.
+
+\e Note: the index role will be set to -1 if the item is removed from
+the model. If you bind to the index role, be sure that the logic
+accounts for the possibility of index being -1, i.e. that the item
+is no longer valid. Usually the item will shortly be destroyed, but
+it is possible to delay delegate destruction in some views via a delayRemove
+attached property.
+
+Models that do not have named roles will have the data provided via
+the \e modelData role. The \e modelData role is also provided for
+Models that have only one role. In this case the \e modelData role
+contains the same data as the named role.
+
+There are a number of QML elements that operate using data models:
+
+\list
+\o ListView
+\o GridView
+\o PathView
+\o \l Repeater
+\endlist
+
+QML supports several types of data model, which may be provided by QML
+or C++ (via QmlContext::setContextProperty(), for example).
+
+\section1 QML Data Models
+
+\section2 ListModel
+
+ListModel is a simple hierarchy of elements specified in QML. The
+available roles are specified by the \l ListElement properties.
+
+\code
+ListModel {
+ id: fruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ }
+}
+\endcode
+
+The above model has two roles, \e name and \e cost. These can be bound
+to by a ListView delegate, for example:
+
+\code
+Component {
+ id: fruitDelegate
+ Row {
+ Text { text: "Fruit: " + name }
+ Text { text: "Cost: $" + cost }
+ }
+}
+ListView {
+ model: fruitModel
+ delegate: fruitDelegate
+}
+\endcode
+
+
+\section2 XmlListModel
+
+XmlListModel allows construction of a model from an XML data source. The roles
+are specified via the \l XmlRole element.
+
+The following model has three roles, \e title, \e link and \e description:
+\code
+XmlListModel {
+ id: feedModel
+ source: "http://rss.news.yahoo.com/rss/oceania"
+ query: "/rss/channel/item"
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "link"; query: "link/string()" }
+ XmlRole { name: "description"; query: "description/string()" }
+}
+\endcode
+
+
+\section2 VisualItemModel
+
+VisualItemModel allows QML items to be provided as a model. This model contains
+both the data and delegate (its child items). This model does not provide any roles.
+
+\code
+ VisualItemModel {
+ id: itemModel
+ Rectangle { height: 30; width: 80; color: "red" }
+ Rectangle { height: 30; width: 80; color: "green" }
+ Rectangle { height: 30; width: 80; color: "blue" }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: itemModel
+ }
+\endcode
+
+Note that in the above example there is no delegate required.
+The items of the model itself provide the visual elements that
+will be positioned by the view.
+
+
+\section1 C++ Data Models
+
+\section2 QAbstractItemModel
+
+QAbstractItemModel provides the roles set via the QAbstractItemModel::setRoleNames() method.
+
+
+\section2 QStringList
+
+QStringList provides the contents of the list via the \e modelData role:
+
+\table
+\o
+\code
+// main.cpp
+QStringList dataList;
+dataList.append("Fred");
+dataList.append("Ginger");
+dataList.appenf("Skipper");
+
+QmlContext *ctxt = view.rootContext();
+ctxt->setContextProperty("myModel", QVariant::fromValue(&dataList));
+\endcode
+
+\o
+\code
+// main.qml
+ListView {
+ width: 100
+ height: 100
+ anchors.fill: parent
+ model: myModel
+ delegate: Component {
+ Rect {
+ height: 25
+ Text { text: modelData }
+ }
+ }
+}
+\endcode
+\endtable
+
+Note: There is no way for the view to know that the contents of a QStringList
+have changed. If the QStringList is changed, it will be necessary to reset
+the model by calling QmlContext::setContextProperty() again.
+
+
+\section2 QList<QObject*>
+
+QList<QObject*> provides the properties of the objects in the list as roles.
+
+\code
+class DataObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString color READ color WRITE setColor)
+...
+};
+
+QList<QObject*> dataList;
+dataList.append(new DataObject("Item 1", "red"));
+dataList.append(new DataObject("Item 2", "green"));
+dataList.append(new DataObject("Item 3", "blue"));
+dataList.append(new DataObject("Item 4", "yellow"));
+
+QmlContext *ctxt = view.rootContext();
+ctxt->setContextProperty("myModel", QVariant::fromValue(&dataList));
+\endcode
+
+The properties of the object may then be accessed in the delegate:
+
+\code
+ListView {
+ width: 100
+ height: 100
+ anchors.fill: parent
+ model: myModel
+ delegate: Component {
+ Rectangle {
+ height: 25
+ width: 100
+ color: model.color
+ Text { text: name }
+ }
+ }
+}
+\endcode
+
+Note: There is no way for the view to know that the contents of a QList
+have changed. If the QList is changed, it will be necessary to reset
+the model by calling QmlContext::setContextProperty() again.
+
+
+\section1 Other Data Models
+
+
+\section2 An Integer
+
+An Integer specifies a model containing the integer number of elements.
+There are no data roles.
+
+The following example creates a ListView with five elements:
+\code
+Component {
+ id: itemDelegate
+ Text { text: "I am item number: " + index }
+}
+ListView {
+ model: 5
+ delegate: itemDelegate
+}
+\endcode
+
+
+\section2 An Object Instance
+
+An Object Instance specifies a model with a single Object element. The
+properties of the object are provided as roles.
+
+The example below creates a list with one item, showing the color of the
+\e myText text. Note the use of the fully qualified \e model.color property
+to avoid clashing with \e color property of the Text element in the delegate.
+
+\code
+Rectangle {
+ Text {
+ id: myText
+ text: "Hello"
+ color: "#dd44ee"
+ }
+
+ Component {
+ id: myDelegate
+ Text {
+ text: model.color
+ }
+ }
+ ListView {
+ anchors.fill: parent
+ anchors.topMargin: 30
+ model: myText
+ delegate: myDelegate
+ }
+}
+\endcode
+
+*/
diff --git a/doc/src/declarative/qmlreference.qdoc b/doc/src/declarative/qmlreference.qdoc
new file mode 100644
index 0000000..a413c22
--- /dev/null
+++ b/doc/src/declarative/qmlreference.qdoc
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+ \page qmlreference.html
+ \title QML Reference
+
+ \target qtdeclarativemainpage
+
+ QML is a language for building the animation rich,
+ highly fluid user interfaces that are becoming common in portable consumer
+ electronics devices such as mobile phones, media players, set-top boxes and
+ netbooks. It is also appropriate for highly custom desktop
+ user interfaces, or special elements in more traditional desktop user interfaces.
+
+ Building fluid applications is done declaratively, rather than procedurally.
+ That is, you specify \e what the UI should look like and how it should behave
+ rather than specifying step-by-step \e how to build it. Specifying a UI declaratively
+ does not just include the layout of the interface items, but also the way each
+ individual item looks and behaves and the overall flow of the application.
+
+ The QML elements provide a sophisticated set of graphical and behavioral building
+ blocks. These different elements are combined together in \l {QML Documents}{QML documents} to build components
+ ranging in complexity from simple buttons and sliders, to complete
+ internet-enabled applications like a \l {http://www.flickr.com}{Flickr} photo browser.
+
+ Getting Started:
+ \list
+ \o \l {Introduction to the QML language}
+ \o \l {tutorial}{Tutorial: 'Hello World'}
+ \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'}
+ \o \l {QML Examples and Walkthroughs}
+ \endlist
+
+ \section1 Core QML Features:
+ \list
+ \o \l {QML Documents}
+ \o \l {Property Binding}
+ \o \l {JavaScript Blocks}
+ \o \l {QML Scope}
+ \o \l {Network Transparency}
+ \o \l {qmlmodels}{Data Models}
+ \o \l {anchor-layout}{Anchor-based Layout}
+ \o \l {qmlstates}{States}
+ \o \l {qmlanimation.html}{Animation}
+ \o \l {qmlmodules.html}{Modules}
+ \o \l {qmlfocus}{Keyboard Focus}
+ \o \l {Extending types from QML}
+ \endlist
+
+ QML Reference:
+ \list
+ \o \l {elements}{QML Elements}
+ \o \l {QML Global Object}
+ \o \l {QML Internationalization}
+ \endlist
+*/
diff --git a/doc/src/declarative/qmlstates.qdoc b/doc/src/declarative/qmlstates.qdoc
new file mode 100644
index 0000000..abf3c93
--- /dev/null
+++ b/doc/src/declarative/qmlstates.qdoc
@@ -0,0 +1,86 @@
+/*!
+\page qmlstates.html
+\target qmlstates
+\title QML States
+
+\section1 Overview
+
+QML states typically describe user interface configurations, including:
+\list
+\o What UI elements are present
+\o The properties of those elements (including how they behave)
+\o What actions are available
+\endlist
+
+A state can also be thought of as a set of batched changes from a default configuration.
+
+Examples of states in modern UI:
+\list
+\o An Address Book application with a 'View Contact' state and an 'Edit Contact' State. In the first state the contact information presented is read-only (using labels), and in the second it is editable (using editors).
+\o A button with a pressed and unpressed state. When pressed the text moves slightly down and to the right, and the button has a slightly darker appearance.
+\endlist
+
+\section1 States in QML
+
+In QML:
+\list
+\o Any object can use states.
+\o There is a default state. The default state can be explicitly set.
+\o A state can affect the properties of other objects, not just the object owning the state (and not just that object's children).
+\endlist
+
+Here is an example of using states. In the default state \c myRect is positioned at 0,0. In the 'moved' state it is positioned at 50,50. Clicking within the mouse region changes the state from the default state to the 'moved' state, thus moving the rectangle.
+
+\qml
+Item {
+ id: myItem
+
+ Rectangle {
+ id: myRect
+ width: 100
+ height: 100
+ color: "red"
+ }
+
+ states: [
+ State {
+ name: "moved"
+ PropertyChanges {
+ target: myRect
+ x: 50
+ y: 50
+ }
+ }
+ ]
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: myItem.state = 'moved'
+ }
+}
+\endqml
+
+State changes can be animated using \l{state-transitions}{Transitions}.
+
+For example, adding this code to the above \c {Item {}} element animates the transition to the "moved" state:
+
+\qml
+ transitions: [
+ Transition {
+ NumberAnimation { matchProperties: "x,y"; duration: 500 }
+ }
+ ]
+\endqml
+
+See \l{state-transitions}{Transitions} for more information.
+
+
+Other things you can do in a state change:
+\list
+\o override signal handlers with PropertyChanges
+\o change an item's visual parent with ParentChange
+\o change an item's anchors with AnchorChanges
+\o run some script with StateChangeScript
+\endlist
+
+*/
diff --git a/doc/src/declarative/qmlviewer.qdoc b/doc/src/declarative/qmlviewer.qdoc
new file mode 100644
index 0000000..a5cb671
--- /dev/null
+++ b/doc/src/declarative/qmlviewer.qdoc
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+ \page qmlviewer.html
+ \title Qt Declarative UI Viewer (qmlviewer)
+ \ingroup qttools
+ \keyword qmlviewer
+
+ This page documents the \e{Declarative UI Viewer} for the Qt GUI
+ toolkit. The \c qmlviewer reads a declarative user interface definition
+ (\c .qml) file and displays the user interface it describes.
+
+ qmlviewer is a development tool. It is not intended to be
+ installed in a production environment.
+
+ \section1 Options
+
+ When run with the \c -help option, qmlviewer shows available options.
+
+ \section1 Dummy Data
+
+ One use of qmlviewer is to allow QML files to be viewed stand-alone,
+ rather than being loaded from within a Qt program. Qt applications will
+ usually bind objects and properties into the execution context before
+ running the QML. To stand-in for such bindings, you can provide dummy
+ data: create a directory called "dummydata" in the same directory as
+ the target QML file and create files there with the "qml" extension.
+ All such files will be loaded as QML objects and bound to the root
+ context as a property with the name of the file (without ".qml").
+
+ For example, if the Qt application has a "clock.time" property
+ that is a qreal from 0 to 86400 representing the number of seconds since
+ midnight, dummy data for this could be provided by \c dummydata/clock.qml:
+ \code
+ QtObject { property real time: 12345 }
+ \endcode
+ Any QML can be used in the dummy data files. You could even animate the
+ fictional data!
+
+ \section1 Screen Orientation
+
+ A special piece of dummy data which is integrated into the viewer is
+ a simple orientation property. The orientation can be set via the
+ settings menu in the application, or by pressing Ctrl+T to toggle it.
+
+ To use this from within your QML file, import QmlViewer 1.0 and create a
+ Screen object. This object has a property, orientation, which can be either
+ Screen.Landscape or Screen.Portrait and which can be bound to in your
+ application. An example is below:
+
+\code
+ import QmlViewer 1.0 as QmlViewer
+
+ Item {
+ QmlViewer.Screen { id: qmlviewerScreen }
+ state: (qmlviewerScreen.orientation == QmlViewer.Screen.Landscape) ? 'landscape' : ''
+ }
+\endcode
+
+*/
diff --git a/doc/src/declarative/qtbinding.qdoc b/doc/src/declarative/qtbinding.qdoc
new file mode 100644
index 0000000..cae0263
--- /dev/null
+++ b/doc/src/declarative/qtbinding.qdoc
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qtbinding.html
+\target qtbinding
+\title Using QML in C++ Applications
+
+\tableofcontents
+
+The QML API is split into three main classes - QmlEngine, QmlComponent and QmlContext.
+QmlEngine provides the environment in which QML is run, QmlComponent encapsulates
+\l {QML Documents}, and QmlContext allows applications to expose data to QML component instances.
+
+QML also includes a convenience API, QmlView, for applications that simply want to embed QML
+components into a new QGraphicsView. QmlView covers up many of the details discussed below.
+While QmlView is mainly intended for rapid prototyping it can have uses in production applications.
+
+If you are looking at retrofitting an existing Qt application with QML,
+read \l{Integrating QML with existing Qt UI code}.
+\section1 Basic Usage
+
+Every application requires at least one QmlEngine. A QmlEngine allows the configuration of
+global settings that apply to all the QML component instances - such as the QNetworkAccessManager
+that is used for network communications, and the path used for persistent storage.
+Multiple QmlEngine's are only needed if the application requires these settings to differ
+between QML component instances.
+
+\l {QML Documents} are loaded using the QmlComponent class. Each QmlComponent instance
+represents a single QML document. A QmlComponent can be passed a document URL, or raw text
+representing the content of the document. The document URL can be a local filesystem URL, or
+any network URL supported by QNetworkAccessManager.
+
+QML component instances can then be created by calling the QmlComponent::create() method. Here's
+an example of loading a QML document, and creating an object from it.
+
+\code
+QmlEngine *engine = new QmlEngine(parent);
+QmlComponent component(engine, QUrl("main.qml"));
+QObject *myObject = component.create();
+\endcode
+
+\section1 Exposing Data
+
+QML components are instantiated in a QmlContext. A context allows the application to expose data
+to the QML component instance. A single QmlContext can be used to instantiate all the objects
+used by an application, or several QmlContext can be created for more fine grained control over
+the data exposed to each instance. If a context is not passed to the QmlComponent::create()
+method, the QmlEngine's \l {QmlEngine::rootContext()}{root context} is used. Data exposed through
+the root context is available to all object instances.
+
+\section1 Simple Data
+
+To expose data to a QML component instance, applications set \l {QmlContext::setContextProperty()}
+{context properties} which are then accessible by name from QML \l {Property Binding}s and
+\l {JavaScript Blocks}. The following example shows how to expose a background color to a QML
+file.
+
+\table
+\row
+\o
+\code
+// main.cpp
+QmlContext *windowContext = new QmlContext(engine->rootContext());
+windowContext->setContextProperty("backgroundColor",
+ QColor(Qt::lightsteelblue));
+
+QmlComponent component(&engine, "main.qml");
+QObject *window = component.create(windowContext);
+\endcode
+\o
+\code
+// main.qml
+import Qt 4.6
+
+Rectangle {
+ color: backgroundColor
+
+ Text {
+ anchors.centerIn: parent
+ text: "Hello Light Steel Blue World!"
+ }
+}
+\endcode
+\endtable
+
+Context properties work just like normal properties in QML bindings - if the \c backgroundColor
+context property in the previous example was changed to red, the component object instances would
+all be automatically updated. Note that it is the responsibility of the creator to delete any
+QmlContext it constructs. If the \c windowContext in the example above is no longer needed when
+the \c window component instantiation is destroyed, the \c windowContext must be destroyed
+explicitly. The simplest way to ensure this is to set \c window as \c windowContext's parent.
+
+QmlContexts form a tree - each QmlContext except for the root context has a parent. Child
+QmlContexts effectively inherit the context properties present in their parents. This gives
+applications more freedom in partitioning the data exposed to different QML object instances.
+If a QmlContext sets a context property that is also set in one of its parents, the new context
+property shadows that in the parent. In The following example, the \c background context property
+in \c {Context 1} shadows the \c background context property in the root context.
+
+\image qml-context-tree.png
+
+\section2 Structured Data
+
+Context properties can also be used to expose structured and writable data to QML objects. In
+addition to all the types already supported by QVariant, QObject derived types can be assigned to
+context properties. QObject context properties allow the data exposed to be more structured, and
+allow QML to set values.
+
+The following example creates a \c CustomPalette object, and sets it as the \c palette context
+property.
+
+\code
+class CustomPalette : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QColor background READ background WRITE setBackground NOTIFY backgroundChanged)
+Q_PROPERTY(QColor text READ text WRITE setText NOTIFY text)
+public:
+ CustomPalette() : m_background(Qt::white), m_text(Qt::black) {}
+
+ QColor background() const { return m_background; }
+ void setBackground(const QColor &c) {
+ if (c != m_background) {
+ m_background = c;
+ emit backgroundChanged();
+ }
+ }
+
+ QColor text() const { return m_text; }
+ void setText(const QColor &c) {
+ if (c != m_text) {
+ m_text = c;
+ emit textChanged();
+ }
+ }
+private:
+ QColor m_background;
+ QColor m_text;
+};
+
+int main(int argc, char **argv)
+{
+ // ...
+
+ QmlContext *windowContext = new QmlContext(engine->rootContext());
+ windowContext->setContextProperty("palette", new CustomPalette);
+
+ QmlComponent component(&engine, "main.qml");
+ QObject *window = component.create(windowContext);
+}
+\endcode
+
+The QML that follows references the palette object, and its properties, to set the appropriate
+background and text colors. When the window is clicked, the palette's text color is changed, and
+the window text will update accordingly.
+
+\code
+// main.qml
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: palette.background
+
+ Text {
+ anchors.centerIn: parent
+ color: palette.text
+ text: "Hello Colorful World!"
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: {
+ palette.text = "blue";
+ }
+ }
+}
+\endcode
+
+To detect when a C++ property value - in this case the \c CustomPalette's \c text property -
+changes, the property must have a corresponding NOTIFY signal. The NOTIFY signal specifies a signal
+that is emitted whenever the property changes value. Implementers should take care to only emit the
+signal if the value \e changes to prevent loops from occuring. Accessing a property from a
+binding that does not have a NOTIFY signal will cause QML to issue a warning at runtime.
+
+\section2 Dynamic Structured Data
+
+If an application is too dynamic to structure data as compile-time QObject types, dynamically
+structured data can be constructed at runtime using the QmlPropertyMap class.
+
+
+\section1 Calling C++ methods from QML
+
+It is possible to call methods of QObject derived types by either exposing the
+methods as public slots, or by marking the methods Q_INVOKABLE.
+
+The C++ methods can also have parameters and return values. QML has support for
+the following types:
+
+\list
+\o bool
+\o unsigned int, int
+\o float, double, qreal
+\o QString
+\o QUrl
+\o QColor
+\o QDate, QTime, QDateTime
+\o QPoint, QPointF
+\o QSize, QSizeF
+\o QRect, QRectF
+\o QVariant
+\endlist
+
+This example toggles the "LED Blinker" when the MouseRegion is clicked:
+
+\table
+\row
+\o
+\code
+// main.cpp
+class LEDBlinker : public QObject
+{
+ Q_OBJECT
+public:
+ LEDBlinker();
+
+ Q_INVOKABLE bool isRunning();
+
+public slots:
+ void start();
+ void stop();
+};
+
+int main(int argc, char **argv)
+{
+ // ...
+
+ QmlContext *context = engine->rootContext();
+ context->setContextProperty("ledBlinker", new LEDBlinker);
+
+ // ...
+}
+\endcode
+\o
+\code
+// main.qml
+import Qt 4.6
+
+Rectangle {
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: {
+ if (ledBlinker.isRunning())
+ ledBlinker.stop()
+ else
+ ledBlicker.start();
+ }
+ }
+}
+\endcode
+\endtable
+
+Note that in this particular example a better way to achieve the same result
+is to have a "running" property. This leads to much nicer QML code:
+
+\table
+\row
+\o
+\code
+// main.qml
+import Qt 4.6
+
+Rectangle {
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: ledBlinker.running = !ledBlinker.running
+ }
+}
+\endcode
+\endtable
+
+
+Of course, it is also possible to call \l {Adding new methods}{functions declared in QML from C++}.
+
+
+\section1 Network Components
+
+If the URL passed to QmlComponent is a network resource, or if the QML document references a
+network resource, the QmlComponent has to fetch the network data before it is able to create
+objects. In this case, the QmlComponent will have a \l {QmlComponent::Loading}{Loading}
+\l {QmlComponent::status()}{status}. An application will have to wait until the component
+is \l {QmlComponent::Ready}{Ready} before calling \l {QmlComponent::create()}.
+
+The following example shows how to load a QML file from a network resource. After creating
+the QmlComponent, it tests whether the component is loading. If it is, it connects to the
+QmlComponent::statusChanged() signal and otherwise calls the \c {continueLoading()} method
+directly. This test is necessary, even for URLs that are known to be remote, just in case
+the component has been cached and is ready immediately.
+
+\code
+MyApplication::MyApplication()
+{
+ // ...
+ component = new QmlComponent(engine, QUrl("http://www.example.com/main.qml"));
+ if (component->isLoading())
+ QObject::connect(component, SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(continueLoading()));
+ else
+ continueLoading();
+}
+
+void MyApplication::continueLoading()
+{
+ if (component->isError()) {
+ qWarning() << component->errors();
+ } else {
+ QObject *myObject = component->create();
+ }
+}
+\endcode
+*/
+
diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc
new file mode 100644
index 0000000..6a94b6e
--- /dev/null
+++ b/doc/src/declarative/qtdeclarative.qdoc
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\module QtDeclarative
+\title QtDeclarative Module
+\ingroup modules
+
+\brief The Qt Declarative module provides a declarative framework for building
+highly dynamic, custom user interfaces.
+
+To include the definitions of the module's classes, use the
+following directive:
+
+\code
+#include <QtDeclarative>
+\endcode
+
+To link against the module, add this line to your \l qmake \c
+.pro file:
+
+\code
+QT += declarative
+\endcode
+
+For more information on the Qt Declarative module, see the
+\l{declarativeui.html}{Declarative UI} documentation.
+
+*/
diff --git a/doc/src/declarative/qtprogrammers.qdoc b/doc/src/declarative/qtprogrammers.qdoc
new file mode 100644
index 0000000..26f73cb
--- /dev/null
+++ b/doc/src/declarative/qtprogrammers.qdoc
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+
+ INCOMPLETE
+
+\page qtprogrammers.html
+\target qtprogrammers
+\title QML for Qt programmers
+
+\section1 Overview
+
+While QML does not require Qt knowledge to use, if you \e are already familar with Qt,
+much of your knowledge is directly relevant to learning and using QML. Of course,
+an application with a UI defined in QML also uses Qt for all the non-UI logic.
+
+\section1 Familiar Concepts
+
+QML provides direct access to the following concepts from Qt:
+
+\list
+ \o QAction - the \l {basicqmlaction}{action} type
+ \o QObject signals and slots - available as functions to call in JavaScript
+ \o QObject properties - available as variables in JavaScript
+ \o QWidget - QmlView is a QML-displaying widget
+ \o Qt models - used directly in data binding (QAbstractItemModel and next generation QListModelInterface)
+\endlist
+
+Qt knowledge is \e required for \l {Extending QML}, and also for \l{Integrating QML with existing Qt UI code}.
+
+\section1 QML Items compared with QWidgets
+
+QML Items are very similar to QWidgets: they define the look and feel of the user interface. (Note that while QWidgets
+haven't traditionally been used to define the look and feel of view delegates, QML Items can be used for this as well.)
+
+There are three structurally different types of QWidget:
+
+\list
+ \o Simple widgets that are not used as parents (QLabel, QCheckBox, QToolButton, etc.)
+ \o Parent widgets that are normally used as parents to other widgets (QGroupBox, QStackedWidget, QTabWidget, etc.)
+ \o Compound widgets that are internally composed of child widgets (QComboBox, QSpinBox, QFileDialog, QTabWidget, etc.)
+\endlist
+
+QML Items also serve these purposes. Each is considered separately below.
+
+\section2 Simple Widgets
+
+The most important rule to remember while implementing a new QmlGraphicsItem in C++
+is that it should not contain any look and feel policies - leave that to the
+QML usage of the item.
+
+As an example, imagine you wanted a reusable Button item. If you therefore
+decided to write a QmlGraphicsItem subclass to implement a button,
+just as QToolButton subclasses QWidget for this purpose, following the rule above, your
+\c QmlGraphicsButton would not have any appearance - just the notions of enabled, triggering, etc.
+
+But there is already an object in Qt that does this: QAction.
+
+QAction is the UI-agnostic essence of QPushButton, QCheckBox, QMenu items, QToolButton,
+and other visual widgets that are commonly bound to a QAction.
+
+So, the job of implementing a checkbox abstraction for QML is already done - it's QAction.
+The look and feel of an action - the appearance of the button, the transition between states,
+and exactly how it respond to mouse, key, or touch input, should all be left for definition
+in QML.
+
+It is illustrative to note that QmlGraphicsTextEdit is built upon QTextControl,
+QmlGraphicsWebView is built upon QWebPage, and ListView uses QListModelInterface,
+just as QTextEdit, QWebView, and QListView are built upon
+those same UI-agnostic components.
+
+The encapsulation of the look and feel that QWidgets gives is important, and for this
+the QML concept of \l {qmldocuments.html}{components} serves the same purpose. If you are building a complete
+suite of applications which should have a consistent look and feel, you should build
+a set of reusable components with the look and feel you desire.
+
+So, to implement your reusable button, you would simply build a QML component.
+
+
+\section2 Parent Widgets
+
+Parent widgets each provide a generic way to interface to one or more arbitrary other widgets.
+A QTabWidget provides an interface to multiple "pages", one of which is visible at any time,
+and a mechnism for selecting among them (the QTabBar). A QScollArea provides scrollbars around
+a widget that is otherwise too large to fit in available space.
+
+Nearly all such components can be created directly in QML. Only a few cases
+which require very particular event handling, such as Flickable, require C++ implementations.
+
+As an example, imagine you decided to make a generic tab widget item to be used
+through your application suite wherever information is in such quantity that it
+needs to be divided up into pages.
+
+A significant difference in the parenting concept with QML compare to QWidgets
+is that while child items are positioned relative to their parents,
+there is no requirement that they be wholy contained ("clipped") to
+the parent (although the clipped property of the child Item does allow
+this where it is needed).
+This difference has rather far-reaching consequences, for example:
+
+\list
+ \o A shadow or highlight around a widget could be a child of that widget.
+ \o Particle effects can flow outside the object where they originate.
+ \o Transitioning animations can "hide" items by visibly moving them beyond the screen bounds.
+\endlist
+
+
+\section2 Compound Widgets
+
+Some widgets provide functionality by composing other widgets as an "implementation detail",
+providing a higher level API to the composition. QSpinBox for example is a line edit and some
+buttons to increase/decrease the edited value. QFileDialog uses a whole host of widgets to
+give the user a way of finding and selecting a file name.
+
+When developing reusable QML Items, you may choose to do the same: build an item composed
+of other items you have already defined.
+
+The only caveat when doing this is to consider the possible animations and transitions that
+users of the compound item might wish to employ. For example, a spinbox might need to smoothly
+transition from an arbitrary Text item, or characters within a Text item, so your spinbox
+item would need to be sufficiently flexible to allow such animation.
+
+\section1 QML Items Compared With QGraphicsWidgets
+*/
diff --git a/doc/src/declarative/scope.qdoc b/doc/src/declarative/scope.qdoc
new file mode 100644
index 0000000..defb217
--- /dev/null
+++ b/doc/src/declarative/scope.qdoc
@@ -0,0 +1,380 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page qmlscope.html
+\title QML Scope
+
+\tableofcontents
+
+\l {Property Binding}s and \l {JavaScript Blocks} are executed in a scope chain automatically
+established by QML when a component instance is constructed. QML is a \e {dynamically scoped}
+language. Different object instances instantiated from the same component can exist in
+different scope chains.
+
+\image qml-scope.png
+
+\section1 JavaScript Variable object
+
+Each binding and script block has its own distinct JavaScript variable object where local
+variables are stored. That is, local variables from different bindings and script blocks never
+conflict.
+
+\section1 Element Type Names
+
+Bindings or script blocks use element type names when accessing \l {Attached Properties} or
+enumeration values. The set of available element names is defined by the import list of the
+\l {QML Documents}{QML Document} in which the the binding or script block is defined.
+
+These two examples show how to access attached properties and enumeration values with different
+types of import statements.
+\table
+\row
+\o
+\code
+import Qt 4.6
+
+Text {
+ id: root
+ scale: root.PathView.scale
+ horizontalAlignment: Text.AlignLeft
+}
+\endcode
+\o
+\code
+import Qt 4.6 as MyQt
+
+Text {
+ id: root
+ scale: root.MyQt.PathView.scale
+ horizontalAlignment: MyQt.Text.AlignLeft
+}
+\endcode
+\endtable
+
+\section1 QML Local Scope
+
+Most variables references are resolved in the local scope. The local scope is controlled by the
+QML component in which the binding or script block was defined. The following example shows
+three different bindings, and the component that dictates each local scope.
+
+\table
+\row
+\o
+\code
+// main.qml
+import Qt 4.6
+
+Rectangle { // Local scope component for binding 1
+ id: root
+ property string text
+
+ Button {
+ text: root.text // binding 1
+ }
+
+ ListView {
+ delegate: Component { // Local scope component for binding 2
+ Rectangle {
+ width: ListView.view.width // binding 2
+ }
+ }
+ }
+
+}
+\endcode
+\o
+\code
+// Button.qml
+import Qt 4.6
+
+Rectangle { // Local scope component for binding 3
+ id: root
+ property string text
+
+ Text {
+ text: root.text // binding 3
+ }
+}
+\endcode
+\endtable
+
+Inside the local scope, four "sub-scopes" exist. Each sub-scope is searched in order when
+resolving a name; names in higher sub-scopes shadow those in lower sub-scopes.
+
+\section2 IDs
+
+IDs present in the component take precendence over other names. The QML engine enforces
+uniqueness of IDs within a component, so their names cannot conflict with one another.
+
+Here is an example of using IDs within bindings:
+
+\code
+Item {
+ id: root
+ width: nested.width
+ Item {
+ id: nested
+ height: root.height
+ }
+}
+\endcode
+
+\section2 Script Methods
+
+Methods declared in script blocks are searched immediately after IDs. In the case of multiple
+script blocks in the one component, the blocks are searched in the order in which they were
+declared - the nesting of script blocks within a component is not significant for name
+resolution.
+
+In the following example, \c {Method 1} shadows \c {Method 2} for the bindings, but not for
+\c {Method 3}.
+
+\code
+Item {
+ Script {
+ function getValue() { return 10; } // Method 1
+ }
+
+ Rectangle {
+ Script {
+ function getValue() { return 11; } // Method 2
+ function getValue2() { return getValue(); } // Method 3
+ }
+
+ x: getValue() // Resolves to Method 1, set to 10
+ y: getValue2() // Resolves to Method 3, set to 11
+ }
+}
+\endcode
+
+\section2 Scope Object
+
+A scope object is associated with each binding and script block. Properties and methods of the
+scope object appear in the scope chain, immediately after \l {Script Methods}.
+
+In bindings and script blocks established explicitly in \l {QML Documents}, the scope object is
+always the element containing the binding or script block. The following example shows two
+bindings, one using grouped properties, and the corresponding scope object. These two bindings
+use the scope object to resolve variable references: \c height is a property on \l Rectangle,
+and \c parent is a property on \l Text.
+
+\code
+Item { // Scope object for Script block 1
+ Script { // Script block 1
+ function calculateValue() { ... }
+ }
+
+ Rectangle { // Scope object for Binding 1 and Script block 2
+ Script { // Script block 2
+ function calculateColor() { ... }
+ }
+ width: height * 2 // Binding 1
+ }
+
+ Text { // Scope object for Binding 2
+ font.pixelSize: parent.height * 0.7 // binding 2
+ }
+}
+\endcode
+
+One notable characteristic of the scope object is its interaction with \l {Attached Properties}.
+As attached properties exist on all objects, an attached property reference that is not
+explicitly prefixed by an id will \e always resolve to the attached property on the scope
+object.
+
+In the following example, \c {Binding 1} will resolve to the attached properties of the
+\l Rectangle element, as intended. However, due to the property search of the scope object,
+\c {Binding 2} will resolve to the attached properties of the \l Text element, which
+is probably not what was intended. This code can be corrected, by replacing \c {Binding 2}
+with this explicit element reference \c {root.ListView.view.width}.
+
+\code
+import Qt 4.6
+
+ListView {
+ delegate: Rectangle {
+ id: root
+ width: ListView.view.width // Binding 1
+ Text {
+ text: contactName
+ width: ListView.view.width // Binding 2
+ }
+ }
+}
+\endcode
+
+\e TODO
+
+\list
+\o scope object for PropertyChanges
+\endlist
+
+\section2 Root Object
+
+Properties and methods on the local scope component's root object appear in the scope chain
+immediately after the \l {Scope Object}. If the scope object and root object are the same,
+this step has no effect.
+
+This example uses the root object to easily propagate data throughout the component.
+
+\code
+Item {
+ property string description
+ property int fontSize
+
+ Text {
+ text: description
+ font.pixelSize: fontSize
+ }
+}
+\endcode
+
+\section1 QML Component chain
+
+When a QML component is instantiated it is given a parent component instance. The parent
+component instance is immutable - it is not affected, for example, by changes in the instance's
+visual parent (in the case of visual elements). Should name resolution fail within the
+\l {QML Local Scope}, this parent chain is searched.
+
+For each component instance in the chain, the following are examined:
+
+\list 1
+\o IDs
+\o Script Methods
+\o Root Object
+\endlist
+
+This list is a sub-set of that in the \l {QML Local Scope}.
+
+A sub-component's parent component instance is set to the component that created it.
+In the following example, the two \c Button instances have the
+\c main.qml instance as their parent component instance. If the \c Button type was used from
+within another QML file, it may have a difference parent component instance, and consequently
+the \c buttonClicked() method may resolve differently.
+
+\table
+\row
+\o
+\code
+// main.qml
+Item {
+ function buttonClicked(var data) {
+ print(data + " clicked");
+ }
+
+ Button { text: "Button1" }
+ Button { text: "Button2" }
+}
+\endcode
+\o
+\code
+// Button.qml
+Rectangle {
+ id: root
+ property string text
+ width: 80
+ height: 30
+ Text {
+ anchors.centerIn: parent
+ text: root.text
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: buttonClicked(text)
+ }
+}
+\endcode
+\endtable
+
+The code above discourages the re-use of the \c Button component, as it has a hard dependency
+on the environment in which it is used. Tightly coupling two types together like this should
+only be used when the components are within the same module, and the author controls the
+implementations of both.
+
+In the following example, the \l ListView sets the parent component instance of each of its
+delegates to its own component instance. In this way, the main component can easily pass data
+into the \l ListView delegates.
+
+\code
+Item {
+ property color delegateColor: "red"
+
+ ListView {
+ delegate: Component {
+ Rectangle {
+ color: delegateColor
+ }
+ }
+ }
+}
+\endcode
+
+\section1 QmlContext chain
+
+The \l QmlContext chain allows C++ applications to pass data into QML applications.
+\l QmlComponent object instances created from C++ are passed a \l QmlContext in which they
+are created. Variables defined in this context appear in the scope chain. Each QmlContext
+also defines a parent context. Variables in child QmlContext's shadow those in its parent.
+
+Consider the following QmlContext tree.
+
+\image qml-context-tree.png
+
+The value of \c background in \c {Context 1} would be used if it was instantiated in
+\c {Context 1}, where as the value of the \c background in the root context would be used if
+the component instance was instantiated in \c {Context 2}.
+
+\code
+import Qt 4.6
+
+Rectangle {
+ id: myRect
+ width: 100; height: 100
+ color: background
+}
+\endcode
+
+\section1 QML Global Object
+
+The \l {QML Global Object} contains all the properties of the JavaScript global object, plus some
+QML specific extensions.
+*/
diff --git a/doc/src/declarative/tutorial.qdoc b/doc/src/declarative/tutorial.qdoc
new file mode 100644
index 0000000..19921c0
--- /dev/null
+++ b/doc/src/declarative/tutorial.qdoc
@@ -0,0 +1,23 @@
+/*!
+\page tutorial.html
+\title Tutorial
+
+This tutorial gives an introduction to QML. It doesn't cover everything; the emphasis is on teaching the key principles,
+and features are introduced as needed.
+
+Through the different steps of this tutorial we will learn about QML basic types, we will create our own QML component
+with properties and signals, and we will create a simple animation with the help of states and transitions.
+
+Chapter one starts with a minimal "Hello world" program and the following chapters introduce new concepts.
+
+The tutorial's source code is located in the $QTDIR/examples/declarative/tutorials/helloworld directory.
+
+Tutorial chapters:
+
+\list
+\o \l {Tutorial 1 - Basic Types}
+\o \l {Tutorial 2 - QML Component}
+\o \l {Tutorial 3 - States and Transitions}
+\endlist
+
+*/
diff --git a/doc/src/declarative/tutorial1.qdoc b/doc/src/declarative/tutorial1.qdoc
new file mode 100644
index 0000000..f7e44b0
--- /dev/null
+++ b/doc/src/declarative/tutorial1.qdoc
@@ -0,0 +1,56 @@
+/*!
+\page tutorial1.html
+\title Tutorial 1 - Basic Types
+
+This first program is a very simple "Hello world" example that introduces some basic QML concepts.
+The picture below is a screenshot of this program.
+
+\image declarative-tutorial1.png
+
+Here is the QML code for the application:
+
+\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 0
+
+\section1 Walkthrough
+
+\section2 Import
+
+First, we need to import the types that we need for this example. Most QML files will import the built-in QML
+types (like \l{Rectangle}, \l{Image}, ...) that come with Qt with:
+
+\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 3
+
+\section2 Rectangle element
+
+\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 1
+
+We declare a root element of type \l{Rectangle}. It is one of the basic building blocks you can use to create an application in QML.
+We give it an \c{id} to be able to refer to it later. In this case, we call it \e page.
+We also set the \c width, \c height and \c color properties.
+The \l{Rectangle} element contains many other properties (such as \c x and \c y), but these are left at their default values.
+
+\section2 Text element
+
+\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 2
+
+We add a \l Text element as a child of our root element that will display the text 'Hello world!'.
+
+The \c y property is used to position the text vertically at 30 pixels from the top of its parent.
+
+The \c font.pointSize and \c font.bold properties are related to fonts and use the \l{Dot Properties}{dot notation}.
+
+The \c anchors.horizontalCenter property refers to the horizontal center of an element.
+In this case, we specify that our text element should be horizontally centered in the \e page element (see \l{anchor-layout}{Anchor-based Layout}).
+
+\section2 Viewing the example
+
+To view what you have created, run the qmlviewer (located in the \c bin directory) with your filename as the first argument.
+For example, to run the provided completed Tutorial 1 example from the install location, you would type:
+
+\code
+bin/qmlviewer $QTDIR/examples/declarative/tutorials/helloworld/tutorial1.qml
+\endcode
+
+[\l {Tutorial}] [Next: \l {Tutorial 2 - QML Component}]
+
+*/
diff --git a/doc/src/declarative/tutorial2.qdoc b/doc/src/declarative/tutorial2.qdoc
new file mode 100644
index 0000000..dd0d428
--- /dev/null
+++ b/doc/src/declarative/tutorial2.qdoc
@@ -0,0 +1,71 @@
+/*!
+\page tutorial2.html
+\title Tutorial 2 - QML Component
+
+This chapter adds a color picker to change the color of the text.
+
+\image declarative-tutorial2.png
+
+Our color picker is made of six cells with different colors.
+To avoid writing the same code multiple times, we first create a new \c Cell component.
+A component provides a way of defining a new type that we can re-use in other QML files.
+A QML component is like a black-box and interacts with the outside world through properties, signals and slots and is generally
+defined in its own QML file (for more details, see \l {Defining new Components}).
+The component's filename must always start with a capital letter.
+
+Here is the QML code for \c Cell.qml:
+
+\snippet examples/declarative/tutorials/helloworld/Cell.qml 0
+
+\section1 Walkthrough
+
+\section2 The Cell Component
+
+\snippet examples/declarative/tutorials/helloworld/Cell.qml 1
+
+The root element of our component is an \l Item with the \c id \e container.
+An \l Item is the most basic visual element in QML and is often used as a container for other elements.
+
+\snippet examples/declarative/tutorials/helloworld/Cell.qml 4
+
+We declare a \c color property. This property is accessible from \e outside our component, this allows us
+to instantiate the cells with different colors.
+This property is just an alias to an existing property - the color of the rectangle that compose the cell (see \l{intro-properties}{Properties}).
+
+\snippet examples/declarative/tutorials/helloworld/Cell.qml 5
+
+We want our component to also have a signal that we call \e clicked with a \e color parameter.
+We will use this signal to change the color of the text in the main QML file later.
+
+\snippet examples/declarative/tutorials/helloworld/Cell.qml 2
+
+Our cell component is basically a colored rectangle with the \c id \e rectangle.
+
+The \c anchors.fill property is a convenient way to set the size of an element.
+In this case the rectangle will have the same size as its parent (see \l{anchor-layout}{Anchor-based Layout}).
+
+\snippet examples/declarative/tutorials/helloworld/Cell.qml 3
+
+In order to change the color of the text when clicking on a cell, we create a \l MouseRegion element with
+the same size as its parent.
+
+A \l MouseRegion defines a signal called \e clicked.
+When this signal is triggered we want to emit our own \e clicked signal with the color as parameter.
+
+\section2 The main QML file
+
+In our main QML file, we use our \c Cell component to create the color picker:
+
+\snippet examples/declarative/tutorials/helloworld/tutorial2.qml 0
+
+We create the color picker by putting 6 cells with different colors in a grid.
+
+\snippet examples/declarative/tutorials/helloworld/tutorial2.qml 1
+
+When the \e clicked signal of our cell is triggered, we want to set the color of the text to the color passed as a parameter.
+We can react to any signal of our component through a property of the name \e 'onSignalName' (see \l{Signal Handlers}).
+
+[Previous: \l {Tutorial 1 - Basic Types}] [Next: \l {Tutorial 3 - States and Transitions}]
+
+*/
+
diff --git a/doc/src/declarative/tutorial3.qdoc b/doc/src/declarative/tutorial3.qdoc
new file mode 100644
index 0000000..290b535
--- /dev/null
+++ b/doc/src/declarative/tutorial3.qdoc
@@ -0,0 +1,45 @@
+/*!
+\page tutorial3.html
+\title Tutorial 3 - States and Transitions
+
+In this chapter, we make this example a little bit more dynamic by introducing states and transitions.
+
+We want our text to move to the bottom of the screen, rotate and become red when clicked.
+
+\image declarative-tutorial3_animation.gif
+
+Here is the QML code:
+
+\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 0
+
+\section1 Walkthrough
+
+\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 2
+
+First, we create a new \e down state for our text element.
+This state will be activated when the \l MouseRegion is pressed, and deactivated when it is released.
+
+The \e down state includes a set of property changes from our implicit \e {default state}
+(the items as they were initially defined in the QML).
+Specifically, we set the \c y property of the text to \c 160, the rotation to \c 180 and the \c color to red.
+
+\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 3
+
+Because we don't want the text to appear at the bottom instantly but rather move smoothly,
+we add a transition between our two states.
+
+\c from and \c to define the states between which the transition will run.
+In this case, we want a transition from the default state to our \e down state.
+
+Because we want the same transition to be run in reverse when changing back from the \e down state to the default state,
+we set \c reversible to \c true.
+This is equivalent to writing the two transitions separately.
+
+The \l ParallelAnimation element makes sure that the two types of animations (number and color) start at the same time.
+We could also run them one after the other by using \l SequentialAnimation instead.
+
+For more details on states and transitions, see \l {QML States}.
+
+[Previous: \l {Tutorial 2 - QML Component}] [\l {Tutorial}]
+
+*/
diff --git a/doc/src/deployment/deployment.qdoc b/doc/src/deployment/deployment.qdoc
index bc6ae98..16718f3 100644
--- a/doc/src/deployment/deployment.qdoc
+++ b/doc/src/deployment/deployment.qdoc
@@ -109,8 +109,6 @@
\row
\o \l {Phonon Module}{Phonon}
\o \l {Qt3Support}
- \o \l {}
- \o \l {}
\endtable
Since Qt is not a system library, it has to be redistributed along
@@ -963,14 +961,14 @@
\title Deploying an Application on Mac OS X
- Starting with version 4.5, Qt now includes a \l {macdeploy}{deployment tool}
- that automates the prodecures described in this document.
+ Beginning with Qt 4.5, a \l {macdeploy}{deployment tool} is
+ included that automates the prodecures described here.
- This documentation will describe how to create a bundle, and how
- to make sure that the application will find the resources it needs
- at run-time. We will demonstrate the procedures in terms of
- deploying the \l {tools/plugandpaint}{Plug & Paint} application
- that is provided in Qt's examples directory.
+ This document describes how to create a bundle and how to make
+ sure that the application will find the resources it needs at
+ run-time. We demonstrate the procedures in terms of deploying the
+ \l {tools/plugandpaint}{Plug & Paint} application that is provided
+ in Qt's examples directory.
\tableofcontents
@@ -1380,63 +1378,38 @@
\section2 Mac OS X Version Dependencies
- Qt 4.2 has been designed to be built and deployed on Mac OS X 10.3
- up until the current version as of this writing, Mac OS X 10.4 and
- all their minor releases. Qt achieves this by using "weak
- linking." This means that Qt tests if a function added in newer
- versions of Mac OS X is available on the computer it is running on
- before it uses it. This results in getting access to newer
- features when running on newer versions of OS X while still
- remaining compatible on older versions.
+ From Qt 4.6, Mac OS X 10.3 (Panther) is no longer supported. Qt
+ 4.6 applications can be built and deployed on Mac OS X 10.4
+ (Tiger) and higher. This is achieved using \e{weak linking}. In
+ \e{weak linking}, Qt tests whether a function added in a newer
+ version of Mac OS X is available on the computer it is running
+ on. This allows Qt to use newer features, when it runs on a newer
+ version of OS X, while remaining compatible on the older versions.
For more information about cross development issues on Mac OS X,
see \l
{http://developer.apple.com/documentation/DeveloperTools/Conceptual/cross_development/index.html}{Apple's Developer Website}.
- Since the linker is set to be compatible with all OS X version, you have to
- change the \c MACOSX_DEPLOYMENT_TARGET environment variable to get weak
- linking to work for your application. You can add:
+ Since the linker is set to be compatible with all OS X versions,
+ you must change the \c MACOSX_DEPLOYMENT_TARGET environment
+ variable to get \e{weak linking} to work for your application. You
+ can add:
\snippet doc/src/snippets/code/doc_src_deployment.qdoc 51
- to your .pro file and qmake will take care of this for you.
-
- However, there is a bit of a wrinkle to keep in mind when your are
- deploying. Mac OS X 10.4 ("Tiger") ships GCC 4.0 as its default
- compiler. This is also the GCC compiler we use for building the
- binary Qt package. If you use GCC 4.0 to build your application,
- it will link against a dynamic libstdc++ that is only available on
- Mac OS X 10.4 and Mac OS X 10.3.9. The application will refuse to
- run on older versions of the operating system.
+ to your .pro file, and qmake will take care of this for you.
For more information about C++ runtime environment, see \l
{http://developer.apple.com/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/index.html}{Apple's Developer Website}
- If you want to deploy to versions of Mac OS X earlier than 10.3.9,
- you must build with GCC 3.3 which is the default on Mac OS X
- 10.3. GCC 3.3 is also available on the Mac OS X 10.4 "Xcode Tools"
- CD and as a download for earlier versions of Mac OS X from Apple
- (\l {https://connect.apple.com/}{connect.apple.com}). You can use
- Apple's \c gcc_select(1) command line tool to switch the default
- complier on your system.
-
\section3 Deploying Phonon Applications on Mac OS X
\list
- \o If you build your Phonon application on Tiger, it will work on
- Tiger, Leopard and Panther.
- \o If you build your application on Leopard, it will \bold not work
- on Panther unless you rename the libraries with the following command
- after you have built your application:
- \snippet doc/src/snippets/code/doc_src_deployment.qdoc 51a
+ \o If you build your Qt 4.6 Phonon application on OS X 10.4
+ (Tiger), it will run on OS X 10.4 and higher.
- This command must be invoked in the directory where
- \c{libphonon_qt7.dylib} is located, usually in
- \c{yourapp.app/Contents/plugins/phonon_backend/}.
- \o The \l {macdeploy}{deployment tool} will perform this step for you.
-
- \o If you are using Leopard, but would like to build your application
+ \o If you are using Leopard but would like to build your application
against Tiger, you can use:
\snippet doc/src/snippets/code/doc_src_deployment.qdoc 51b
@@ -1444,12 +1417,13 @@
\section2 Architecture Dependencies
- The Qt for Mac OS X libraries, tools, and examples can be built "universal"
- (i.e. they run natively on both Intel and PowerPC machines). This
- is accomplished by passing \c -universal on the \c configure line
- of the source package, and requires that you use GCC 4.0.x. On
- PowerPC hardware you will need to pass the universal SDK as a
- command line argument to the Qt configure command. For example:
+ The Qt for Mac OS X libraries, tools, and examples can be built
+ "universal" (i.e. they run natively on both Intel and PowerPC
+ machines). This is accomplished by passing \c -universal on the
+ \c configure line of the source package, and requires that you use
+ GCC 4.0.x. On PowerPC hardware you will need to pass the universal
+ SDK as a command line argument to the Qt configure command. For
+ example:
\snippet doc/src/snippets/code/doc_src_deployment.qdoc 52
@@ -1573,33 +1547,35 @@
By default \c .pkg file generated by \c qmake adds support for all
S60 3rd edition FP1, S60 3rd edition FP2 and S60 5th edition devices.
- As a last step we will embed the \c qt_installer.sis file to the Wiggly
- deployment file:
-
- \snippet doc/src/snippets/code/doc_src_deployment.qdoc 58
-
- When \c qt_installer.sis is embedded to the application deployment file, the
- end-user does not need to download and install all dependencies separately.
- The drawback of \c .sis embedding is that the application \c .sis file size becomes
- big. To address these problems Forum Nokia is planning to release a smart installer
- which will take care of downloading and installing the necessary dependencies
- over-the-air. The expected availability of smart installer is 1Q 2010.
-
Now we are ready to compile the application and create the application
deployment file. Run \c qmake to create Symbian specific makefiles, resources (\.rss)
and deployment packaging files (\c .pkg). And do build to create the
application binaries and resources.
- \snippet doc/src/snippets/code/doc_src_deployment.qdoc 59
+ \snippet doc/src/snippets/code/doc_src_deployment.qdoc 58
If everything compiled and linked without any errors, we are now ready to create
- an application installation file:
+ an application installation package (\c wiggly_installer.sis).
+
+ If you haven't done so already, download the latest release of the Smart Installer
+ from \l{http://get.qt.nokia.com/nokiasmartinstaller/}, and install it on top of the Qt package
+
+ Then use this command to create the installer sis package:
+
+ \snippet doc/src/snippets/code/doc_src_deployment.qdoc 59
+
+ If all binaries and dependencies were found, you should now have a self signed
+ \c wiggly_installer.sis ready to be installed on a device. The smart installer
+ contained in the in the installer package will download the necessary dependencies
+ such as Qt libraries to the device.
- \snippet doc/src/snippets/code/doc_src_deployment.qdoc 60
+ \note If you want to have your application properly Symbian Signed for distribution,
+ you will have to properly sign both the application and the application installer packages.
+ Please see
+ \l{http://developer.symbian.org/wiki/index.php/Category:Symbian_Signed}
+ {Symbian Signed wiki} for more information about Symbian Signed.
- If all binaries and dependencies were found, we should now have a self-signed
- \c wiggly_release-gcce.sis ready to be installed on a device. For more information
- about creating a \c .sis file and installing it to device see also
+ For more information about creating a \c .sis file and installing it to device see also
\l {The Symbian platform - Introduction to Qt#Installing your own applications}{here}.
*/
diff --git a/doc/src/development/qmake-manual.qdoc b/doc/src/development/qmake-manual.qdoc
index 8fc4058..6215268 100644
--- a/doc/src/development/qmake-manual.qdoc
+++ b/doc/src/development/qmake-manual.qdoc
@@ -858,7 +858,7 @@
libraries are linked in the "Frameworks & Libraries" phase in the
XCode build system.
- Furthermore, The selected "Active Build Configuration" is stored
+ Furthermore, the selected "Active Build Configuration" is stored
in a .pbxuser file, which is generated by xcode on first load, not
created by qmake.
@@ -979,7 +979,7 @@
If \c UID2 is not specified, it defaults to the same value as \c UID3.
If \c UID3 is not specified, qmake will automatically generate a \c UID3
suitable for development and debugging. This value should be manually
- specified for applications that are to be released. In order to optain
+ specified for applications that are to be released. In order to obtain
an official UID, please contact Nokia. Both \c SID and \c VID default to empty values.
For more information about unique identifiers and their meaning for
@@ -1431,6 +1431,18 @@ is the application private directory on the drive it is installed to.
\snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 141
+ On the Symbian platform, you can use \c{DEPLOYMENT.installer_header}
+ variable to generate smart installer wrapper for your application.
+ If you specify just UID of the installer package as the value, then
+ installer package name and version will be autogenerated:
+
+ \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 146
+
+ If autogenerated values are not suitable, you can also specify the sis
+ header yourself using this variable:
+
+ \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 147
+
\target DEPLOYMENT_PLUGIN
\section1 DEPLOYMENT_PLUGIN
@@ -3492,7 +3504,7 @@ For example:
\target Properties
\section1 Properties
- \c qmake has a system of persistant information, this allows you to
+ \c qmake has a system of persistent information, this allows you to
\c set a variable in qmake once, and each time qmake is invoked this
value can be queried. Use the following to set a property in qmake:
@@ -3670,7 +3682,7 @@ For example:
the newly introduced libraries in the \c LIBS variable, and find their
dependent .prl files, continuing until all libraries have been resolved.
At this point, the Makefile is created as usual, and the libraries are
- linked explicitlyy against the application.
+ linked explicitly against the application.
The internals of the .prl file are left closed so they can easily
change later. They are not designed to be changed by hand, should only
diff --git a/doc/src/development/qtestlib.qdoc b/doc/src/development/qtestlib.qdoc
index 0835ff1..4b9c657 100644
--- a/doc/src/development/qtestlib.qdoc
+++ b/doc/src/development/qtestlib.qdoc
@@ -237,14 +237,14 @@
The code insde the QBENCHMARK macro will be measured, and possibly also repeated
several times in order to get an accurate measurement. This depends on the selected
- measurement back-end. Several back-ends are available an can be selected on the
+ measurement back-end. Several back-ends are available. They can be selected on the
command line:
\target testlib-benchmarking-measurement
\table
\header \o Name
- \o Commmand-line Arguemnt
+ \o Commmand-line Argument
\o Availability
\row \o Walltime
\o (default)
diff --git a/doc/src/examples/googlesuggest.qdoc b/doc/src/examples/googlesuggest.qdoc
index cd6c6b1..f2bdb4f 100644
--- a/doc/src/examples/googlesuggest.qdoc
+++ b/doc/src/examples/googlesuggest.qdoc
@@ -111,7 +111,7 @@
event processing.
Key event handling is implemented so that Enter and Return execute the
- selected link, while the Escape key hides the popup. Sine we want to be
+ selected link, while the Escape key hides the popup. Since we want to be
able to navigate the list of suggestions using the different navigation
keys on the keyboard we let Qt continue regular event processing for those
by returning false from the eventFilter reimplementation.
diff --git a/doc/src/examples/hellogl_es.qdoc b/doc/src/examples/hellogl_es.qdoc
index fca1150..67a83e0 100644
--- a/doc/src/examples/hellogl_es.qdoc
+++ b/doc/src/examples/hellogl_es.qdoc
@@ -64,29 +64,6 @@
the OpenGL ES window within the native window manager. In
QGLWidget::initializeGL() we initialize OpenGL ES.
- \section1 Using OpenGL ES rendering commands
-
- To update the scene, we reimplment QGLWidget::paintGL(). We use OpenGL ES
- rendering commands just like we do with standard OpenGL. Since the OpenGL
- ES common light profile only supports fixed point functions, we need to
- abstract it somehow. Hence, we define an abstraction layer in
- \c{cl_helper.h}.
-
- \snippet examples/opengl/hellogl_es/cl_helper.h 0
-
- Instead of \c glFogxv() or \c glFogfv() we use \c q_glFogv() and to
- convert the coordinates of a vertice we use the macro \c f2vt(). That way,
- if QT_OPENGL_ES_CL is defined we use the fixed point functions and every
- float is converted to fixed point.
-
- If QT_OPENGL_ES_CL is not defined we use the floating point functions.
-
- \snippet examples/opengl/hellogl_es/cl_helper.h 1
-
- This way we support OpenGL ES Common and Common Light with the same code
- and abstract the fact that we use either the floating point functions or
- otherwise the fixed point functions.
-
\section1 Porting OpenGL to OpenGL ES
Since OpenGL ES is missing the immediate mode and does not support quads,
diff --git a/doc/src/getting-started/installation.qdoc b/doc/src/getting-started/installation.qdoc
index 3088892..e54774b 100644
--- a/doc/src/getting-started/installation.qdoc
+++ b/doc/src/getting-started/installation.qdoc
@@ -677,7 +677,7 @@ If you are using pre-built binaries, follow the instructions given in the
\snippet doc/src/snippets/code/doc_src_installation.qdoc 30
- This will create a self-signed \c fluidlauncher_armv5_urel.sis and
+ This will create a self-signed \c fluidlauncher.sis and
install it to your device.
To run the demos on the emulator simply navigate to the directory of the demo
@@ -1023,9 +1023,11 @@ If you are using pre-built binaries, follow the instructions given in the
See \l{http://pepper.troll.no/s60prereleases/patches/}{here} for instructions how to check your
compiler version and how to patch it, if needed.
\endlist
- \o \l{http://downloads.activestate.com/ActivePerl/Windows/5.6/ActivePerl-5.6.1.638-MSWin32-x86.msi}{ActivePerl v5.6.1 build 638}
+ \o \l{http://downloads.activestate.com/ActivePerl/releases}{ActivePerl 5.6.1 build 638 or higher}
\list
- \o \bold{Note:} According to Symbian, version 5.6.1 build 638 is mandatory. Using later versions may result in unexplained errors.
+ \o \bold{Note:} According to Symbian, version 5.6.1 build 638 is mandatory for building Symbian applications,
+ but that version is no longer available from ActiveState. However, Qt for Symbian has been successfully
+ compiled using both 5.8.x and 5.10.x versions.
\endlist
\o \l{http://www.forum.nokia.com/main/resources/tools_and_sdks/S60SDK/}{S60 Platform SDK 3rd Edition FP1 or higher}
\list
@@ -1038,8 +1040,9 @@ If you are using pre-built binaries, follow the instructions given in the
\list
\o \bold{Note:} This is not required if you are using pre-built binary package.
\endlist
- \o Building Qt libraries requires \l{http://www.arm.com/products/DevTools/RVCT.html}{RVCT} 2.2 [build 686] or later,
- which is not available free of charge.
+ \o Building Qt libraries requires \l{http://www.arm.com/products/DevTools/RVCT.html}{RVCT} version 2.2 (build 686 or later),
+ which is not available free of charge. Usage of later versions of RVCT, including the 3.x and 4.x series, is not supported
+ in this release.
\endlist
Running Qt on real device requires the Open C to be installed on the device.
diff --git a/doc/src/images/declarative-anchors_example.png b/doc/src/images/declarative-anchors_example.png
new file mode 100644
index 0000000..293cd4b
--- /dev/null
+++ b/doc/src/images/declarative-anchors_example.png
Binary files differ
diff --git a/doc/src/images/declarative-anchors_example2.png b/doc/src/images/declarative-anchors_example2.png
new file mode 100644
index 0000000..6d3be7d
--- /dev/null
+++ b/doc/src/images/declarative-anchors_example2.png
Binary files differ
diff --git a/doc/src/images/declarative-image_fillMode.gif b/doc/src/images/declarative-image_fillMode.gif
new file mode 100644
index 0000000..eb0a9af
--- /dev/null
+++ b/doc/src/images/declarative-image_fillMode.gif
Binary files differ
diff --git a/doc/src/images/declarative-image_tile.png b/doc/src/images/declarative-image_tile.png
new file mode 100644
index 0000000..b946a6d
--- /dev/null
+++ b/doc/src/images/declarative-image_tile.png
Binary files differ
diff --git a/doc/src/images/declarative-item_opacity1.png b/doc/src/images/declarative-item_opacity1.png
new file mode 100644
index 0000000..cde973b
--- /dev/null
+++ b/doc/src/images/declarative-item_opacity1.png
Binary files differ
diff --git a/doc/src/images/declarative-item_opacity2.png b/doc/src/images/declarative-item_opacity2.png
new file mode 100644
index 0000000..8627360
--- /dev/null
+++ b/doc/src/images/declarative-item_opacity2.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking1.png b/doc/src/images/declarative-item_stacking1.png
new file mode 100644
index 0000000..18f4148
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking1.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking2.png b/doc/src/images/declarative-item_stacking2.png
new file mode 100644
index 0000000..7a71bcd
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking2.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking3.png b/doc/src/images/declarative-item_stacking3.png
new file mode 100644
index 0000000..cde973b
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking3.png
Binary files differ
diff --git a/doc/src/images/declarative-item_stacking4.png b/doc/src/images/declarative-item_stacking4.png
new file mode 100644
index 0000000..3fdf627
--- /dev/null
+++ b/doc/src/images/declarative-item_stacking4.png
Binary files differ
diff --git a/doc/src/images/declarative-nopercent.png b/doc/src/images/declarative-nopercent.png
new file mode 100644
index 0000000..28b00a9
--- /dev/null
+++ b/doc/src/images/declarative-nopercent.png
Binary files differ
diff --git a/doc/src/images/declarative-pathattribute.png b/doc/src/images/declarative-pathattribute.png
new file mode 100644
index 0000000..57cd049
--- /dev/null
+++ b/doc/src/images/declarative-pathattribute.png
Binary files differ
diff --git a/doc/src/images/declarative-pathcubic.png b/doc/src/images/declarative-pathcubic.png
new file mode 100644
index 0000000..ffbca5d
--- /dev/null
+++ b/doc/src/images/declarative-pathcubic.png
Binary files differ
diff --git a/doc/src/images/declarative-pathquad.png b/doc/src/images/declarative-pathquad.png
new file mode 100644
index 0000000..65f1999
--- /dev/null
+++ b/doc/src/images/declarative-pathquad.png
Binary files differ
diff --git a/doc/src/images/declarative-percent.png b/doc/src/images/declarative-percent.png
new file mode 100644
index 0000000..c277055
--- /dev/null
+++ b/doc/src/images/declarative-percent.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo1.png b/doc/src/images/declarative-qtlogo1.png
new file mode 100644
index 0000000..940d159
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo1.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo2.png b/doc/src/images/declarative-qtlogo2.png
new file mode 100644
index 0000000..b1d128a
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo2.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo3.png b/doc/src/images/declarative-qtlogo3.png
new file mode 100644
index 0000000..d516524
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo3.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo4.png b/doc/src/images/declarative-qtlogo4.png
new file mode 100644
index 0000000..7c8aa64
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo4.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo5.png b/doc/src/images/declarative-qtlogo5.png
new file mode 100644
index 0000000..b7b3513
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo5.png
Binary files differ
diff --git a/doc/src/images/declarative-qtlogo6.png b/doc/src/images/declarative-qtlogo6.png
new file mode 100644
index 0000000..07a078f
--- /dev/null
+++ b/doc/src/images/declarative-qtlogo6.png
Binary files differ
diff --git a/doc/src/images/declarative-rect.png b/doc/src/images/declarative-rect.png
new file mode 100644
index 0000000..173759a
--- /dev/null
+++ b/doc/src/images/declarative-rect.png
Binary files differ
diff --git a/doc/src/images/declarative-rect_gradient.png b/doc/src/images/declarative-rect_gradient.png
new file mode 100644
index 0000000..f79d579
--- /dev/null
+++ b/doc/src/images/declarative-rect_gradient.png
Binary files differ
diff --git a/doc/src/images/declarative-rect_tint.png b/doc/src/images/declarative-rect_tint.png
new file mode 100644
index 0000000..3a44013
--- /dev/null
+++ b/doc/src/images/declarative-rect_tint.png
Binary files differ
diff --git a/doc/src/images/declarative-removebutton-close.png b/doc/src/images/declarative-removebutton-close.png
new file mode 100644
index 0000000..d73f8e1
--- /dev/null
+++ b/doc/src/images/declarative-removebutton-close.png
Binary files differ
diff --git a/doc/src/images/declarative-removebutton-open.png b/doc/src/images/declarative-removebutton-open.png
new file mode 100644
index 0000000..b54d797
--- /dev/null
+++ b/doc/src/images/declarative-removebutton-open.png
Binary files differ
diff --git a/doc/src/images/declarative-removebutton.gif b/doc/src/images/declarative-removebutton.gif
new file mode 100644
index 0000000..ca4d7e6
--- /dev/null
+++ b/doc/src/images/declarative-removebutton.gif
Binary files differ
diff --git a/doc/src/images/declarative-removebutton.png b/doc/src/images/declarative-removebutton.png
new file mode 100644
index 0000000..f783e6a
--- /dev/null
+++ b/doc/src/images/declarative-removebutton.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-1.png b/doc/src/images/declarative-reuse-1.png
new file mode 100644
index 0000000..c704457
--- /dev/null
+++ b/doc/src/images/declarative-reuse-1.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-2.png b/doc/src/images/declarative-reuse-2.png
new file mode 100644
index 0000000..0b6006b
--- /dev/null
+++ b/doc/src/images/declarative-reuse-2.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-3.png b/doc/src/images/declarative-reuse-3.png
new file mode 100644
index 0000000..695a725
--- /dev/null
+++ b/doc/src/images/declarative-reuse-3.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-bluerect.png b/doc/src/images/declarative-reuse-bluerect.png
new file mode 100644
index 0000000..97dbb5f
--- /dev/null
+++ b/doc/src/images/declarative-reuse-bluerect.png
Binary files differ
diff --git a/doc/src/images/declarative-reuse-focus.png b/doc/src/images/declarative-reuse-focus.png
new file mode 100644
index 0000000..f91d374
--- /dev/null
+++ b/doc/src/images/declarative-reuse-focus.png
Binary files differ
diff --git a/doc/src/images/declarative-rotation.png b/doc/src/images/declarative-rotation.png
new file mode 100644
index 0000000..994011b
--- /dev/null
+++ b/doc/src/images/declarative-rotation.png
Binary files differ
diff --git a/doc/src/images/declarative-roundrect.png b/doc/src/images/declarative-roundrect.png
new file mode 100644
index 0000000..607da81
--- /dev/null
+++ b/doc/src/images/declarative-roundrect.png
Binary files differ
diff --git a/doc/src/images/declarative-scale.png b/doc/src/images/declarative-scale.png
new file mode 100644
index 0000000..bab729e
--- /dev/null
+++ b/doc/src/images/declarative-scale.png
Binary files differ
diff --git a/doc/src/images/declarative-scalegrid.png b/doc/src/images/declarative-scalegrid.png
new file mode 100644
index 0000000..32d87125
--- /dev/null
+++ b/doc/src/images/declarative-scalegrid.png
Binary files differ
diff --git a/doc/src/images/declarative-text.png b/doc/src/images/declarative-text.png
new file mode 100644
index 0000000..c1a4112
--- /dev/null
+++ b/doc/src/images/declarative-text.png
Binary files differ
diff --git a/doc/src/images/declarative-textedit.gif b/doc/src/images/declarative-textedit.gif
new file mode 100644
index 0000000..7186eb9
--- /dev/null
+++ b/doc/src/images/declarative-textedit.gif
Binary files differ
diff --git a/doc/src/images/declarative-textformat.png b/doc/src/images/declarative-textformat.png
new file mode 100644
index 0000000..ade1b45
--- /dev/null
+++ b/doc/src/images/declarative-textformat.png
Binary files differ
diff --git a/doc/src/images/declarative-textstyle.png b/doc/src/images/declarative-textstyle.png
new file mode 100644
index 0000000..858c1bc
--- /dev/null
+++ b/doc/src/images/declarative-textstyle.png
Binary files differ
diff --git a/doc/src/images/declarative-transformorigin.png b/doc/src/images/declarative-transformorigin.png
new file mode 100644
index 0000000..4af320f
--- /dev/null
+++ b/doc/src/images/declarative-transformorigin.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list-closed.png b/doc/src/images/declarative-tutorial-list-closed.png
new file mode 100644
index 0000000..4a0fee9
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list-closed.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list-open.png b/doc/src/images/declarative-tutorial-list-open.png
new file mode 100644
index 0000000..16a9c94
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list-open.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial-list.png b/doc/src/images/declarative-tutorial-list.png
new file mode 100644
index 0000000..723fe2f
--- /dev/null
+++ b/doc/src/images/declarative-tutorial-list.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial1.png b/doc/src/images/declarative-tutorial1.png
new file mode 100644
index 0000000..c9d3844
--- /dev/null
+++ b/doc/src/images/declarative-tutorial1.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial2.png b/doc/src/images/declarative-tutorial2.png
new file mode 100644
index 0000000..835484a
--- /dev/null
+++ b/doc/src/images/declarative-tutorial2.png
Binary files differ
diff --git a/doc/src/images/declarative-tutorial3.gif b/doc/src/images/declarative-tutorial3.gif
new file mode 100644
index 0000000..e2eae81
--- /dev/null
+++ b/doc/src/images/declarative-tutorial3.gif
Binary files differ
diff --git a/doc/src/images/declarative-tutorial3_animation.gif b/doc/src/images/declarative-tutorial3_animation.gif
new file mode 100644
index 0000000..80b78de
--- /dev/null
+++ b/doc/src/images/declarative-tutorial3_animation.gif
Binary files differ
diff --git a/doc/src/images/qpainter-text.png b/doc/src/images/qpainter-text.png
index af7821c..e95c965 100644
--- a/doc/src/images/qpainter-text.png
+++ b/doc/src/images/qpainter-text.png
Binary files differ
diff --git a/doc/src/index.qdoc b/doc/src/index.qdoc
index 0a603ce..d1f5f0f 100644
--- a/doc/src/index.qdoc
+++ b/doc/src/index.qdoc
@@ -103,6 +103,7 @@
<li><a href="paintsystem.html">Painting and Printing</a></li>
<li><a href="graphicsview.html">Canvas UI with Graphics View</a></li>
<li><a href="webintegration.html">Integrating Web Content</a></li>
+ <li><a href="declarativeui.html">Declarative UI (QML)</a></li>
</ul>
</td>
<td valign="top">
diff --git a/doc/src/modules.qdoc b/doc/src/modules.qdoc
index 48e1358..78af7eb 100644
--- a/doc/src/modules.qdoc
+++ b/doc/src/modules.qdoc
@@ -65,6 +65,7 @@
\row \o \l{QtWebKit} \o Classes for displaying and editing Web content
\row \o \l{QtXml} \o Classes for handling XML
\row \o \l{QtXmlPatterns} \o An XQuery & XPath engine for XML and custom data models
+ \row \o \l{QtDeclarative} \o An engine for declaratively building fluid user interfaces.
\row \o \l{Phonon Module}{Phonon} \o Multimedia framework classes
\row \o \l{Qt3Support} \o Qt 3 compatibility classes
\header \o {2,1} \bold{Modules for working with Qt's tools}
diff --git a/doc/src/platforms/platform-notes.qdoc b/doc/src/platforms/platform-notes.qdoc
index b64d67b..9c9b743 100644
--- a/doc/src/platforms/platform-notes.qdoc
+++ b/doc/src/platforms/platform-notes.qdoc
@@ -285,6 +285,9 @@
\section1 General Information
+ Qt 4.6 applications can only be deployed on Mac OS X 10.4 (Tiger)
+ and higher.
+
Qt 4.4 and Qt 4.5 development is only supported on Mac OS X 10.4 and up.
Applications built against these version of Qt can be deployed on Mac OS X
10.3, but cannot be developed on that version of the operating system due
diff --git a/doc/src/platforms/symbian-introduction.qdoc b/doc/src/platforms/symbian-introduction.qdoc
index 427f45a..591d6f1 100644
--- a/doc/src/platforms/symbian-introduction.qdoc
+++ b/doc/src/platforms/symbian-introduction.qdoc
@@ -127,6 +127,13 @@
\row \o \c run \o Run the application on the emulator.
\row \o \c runonphone \o Run the application on a device.
\row \o \c sis \o Create signed \c .sis file for project.
+ \row \o \c installer_sis \o Create signed \l{Smart Installer}{smart installer}
+ \c .sis file for project.
+ Smart installer will attempt to download
+ missing dependencies in addition to
+ just installing the application.
+ \row \o \c stub_sis \o Create a stub sis to allow upgradability of projects
+ that are deployed in ROM
\endtable
The following lines perform a debug build for the emulator
@@ -137,6 +144,14 @@
To work on your project in Carbide, simply import the \c .pro file
by right clicking on the project explorer and executing "Import...".
+ \section2 Smart Installer
+
+ The Smart Installer makes sure that deployed applications have all the Qt dependencies
+ they need to run on a device.
+
+ Download the latest release of the Smart Installer from \l{http://get.qt.nokia.com/nokiasmartinstaller/},
+ and install it on top of the Qt package.
+
\section1 Installing your own applications
To install your own applications on hardware, you need a signed \c .sis file.
diff --git a/doc/src/porting/porting4.qdoc b/doc/src/porting/porting4.qdoc
index 25dc792..1b6eeb7 100644
--- a/doc/src/porting/porting4.qdoc
+++ b/doc/src/porting/porting4.qdoc
@@ -3201,8 +3201,8 @@
The \c QShared class has been obsoleted by the more powerful
QSharedData and QSharedDataPointer as a means of creating custom
- implicitly shared classes. It has been renamed Q3Shared moved to
- the Qt3Support library.
+ implicitly shared classes. It has been renamed Q3Shared and moved
+ to the Qt3Support library.
An easy way of porting to Qt 4 is to include this class into your
project and to use it instead of \c QShared:
@@ -3226,7 +3226,7 @@
\section1 QSimpleRichText
QSimpleRichText has been obsoleted by QTextDocument. It has
- bene renamed Q3SimpleRichText and moved to the Qt3Support
+ been renamed Q3SimpleRichText and moved to the Qt3Support
library.
Previously, you would do the following with Q3SimpleRichText:
diff --git a/doc/src/porting/qt4-network.qdoc b/doc/src/porting/qt4-network.qdoc
index 91c1c4e..60e6dbb 100644
--- a/doc/src/porting/qt4-network.qdoc
+++ b/doc/src/porting/qt4-network.qdoc
@@ -199,7 +199,7 @@
level QNetworkProtocol and QUrlOperator abstraction has been
eliminated. These classes attempted the impossible (unify FTP and
HTTP under one roof), and unsurprisingly failed at that. Qt 4
- still provides QFtp, and it also proveds the QNetworkAccessManager.
+ still provides QFtp, and it also provides the QNetworkAccessManager.
The QSocket class in Qt 3 has been renamed QTcpSocket. The new
class is reentrant and supports blocking. It's also easier to
diff --git a/doc/src/qt4-intro.qdoc b/doc/src/qt4-intro.qdoc
index daceba5..5344bcc 100644
--- a/doc/src/qt4-intro.qdoc
+++ b/doc/src/qt4-intro.qdoc
@@ -457,6 +457,30 @@
*/
/*!
+ \page qt4-7-intro.html
+ \title What's New in Qt 4.7
+
+ Qt 4.7 provides many improvements and enhancements over the
+ previous releases in the Qt 4 series. This document covers the
+ most important features in this release, separated by category.
+
+ A list of other Qt 4 features can be found on the \bold{\l{What's
+ New in Qt 4}} page.
+
+ \bold{Highlights}
+
+ \tableofcontents
+
+ \section1 New Classes, Functions, Macros, etc.
+
+ Links to new classes, functions, macros, and other items
+ introduced in Qt 4.7.
+
+ \sincelist 4.7
+
+*/
+
+/*!
\page qt4-6-intro.html
\title What's New in Qt 4.6
diff --git a/doc/src/scripting/scripting.qdoc b/doc/src/scripting/scripting.qdoc
index edee52a..2c22989 100644
--- a/doc/src/scripting/scripting.qdoc
+++ b/doc/src/scripting/scripting.qdoc
@@ -1007,7 +1007,7 @@
Because of the presence of the built-in \c arguments object,
implementing functions that take a variable number of arguments
is simple. In fact, as we have seen, in the technical sense \e{all}
- Qt Script functions can be seen as variable-argument functions).
+ Qt Script functions can be seen as variable-argument functions.
As an example, consider a concat() function that takes an arbitrary
number of arguments, converts the arguments to their string
representation and concatenates the results; for example,
diff --git a/doc/src/snippets/code/doc_src_deployment.qdoc b/doc/src/snippets/code/doc_src_deployment.qdoc
index 7eb8808..3b0cda1 100644
--- a/doc/src/snippets/code/doc_src_deployment.qdoc
+++ b/doc/src/snippets/code/doc_src_deployment.qdoc
@@ -475,18 +475,10 @@ default_deployment.pkg_prerules += supported_platforms
//! [57]
//! [58]
-embedded_deployments = \
- "; Embed Qt dependencies" \
- "@\"$$[QT_INSTALL_PREFIX]/qt_installer.sis\",(0x2001E62D)"
-
-default_deployment.pkg_prerules += embedded_deployments
-//! [58]
-
-//! [59]
qmake
make release-gcce
-//! [59]
+//! [58]
-//! [60]
-make sis
-//! [60] \ No newline at end of file
+//! [59]
+make installer_sis
+//! [59] \ No newline at end of file
diff --git a/doc/src/snippets/code/doc_src_porting4.qdoc b/doc/src/snippets/code/doc_src_porting4.qdoc
index 4d24ba3..2f76591 100644
--- a/doc/src/snippets/code/doc_src_porting4.qdoc
+++ b/doc/src/snippets/code/doc_src_porting4.qdoc
@@ -452,7 +452,7 @@ QSimpleRichText richText(text, font);
// Set the width of the paragraph to w
richText.setWidth(w);
-// Or set a resonable default size
+// Or set a reasonable default size
richText.adjustSize();
// Query for its used size
diff --git a/doc/src/snippets/code/doc_src_qmake-manual.qdoc b/doc/src/snippets/code/doc_src_qmake-manual.qdoc
index b1cbc72..a48b53f 100644
--- a/doc/src/snippets/code/doc_src_qmake-manual.qdoc
+++ b/doc/src/snippets/code/doc_src_qmake-manual.qdoc
@@ -963,9 +963,9 @@ RSS_RULES += myrssrules
//! [145]
//! [146]
-BLD_INF_RULES.prj_exports += \
- "$${LITERAL_HASH}include <platform_paths.hrh>" \
- "rom/my.iby APP_LAYER_PUBLIC_EXPORT_PATH(my.iby)" \
- "inc/myheader.h mycomp/myheader.h" \
- ":zip my_api.zip my_api"
+DEPLOYMENT.installer_header = 0x12345678
//! [146]
+
+//! [147]
+DEPLOYMENT.installer_header = "$${LITERAL_HASH}{\"My Application Installer\"},(0x12345678),1,0,0"
+//! [147]
diff --git a/doc/src/snippets/declarative/GroupBox.qml b/doc/src/snippets/declarative/GroupBox.qml
new file mode 100644
index 0000000..6c5431e
--- /dev/null
+++ b/doc/src/snippets/declarative/GroupBox.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+
+ContentWrapper {
+ id: container; width: parent.width; height: contents.height
+ children: [
+ Rectangle {
+ width: parent.width; height: contents.height
+ color: "white"; pen.width: 2; pen.color: "#adaeb0"; radius: 10
+ Column {
+ id: layout; width: parent.width; margin: 5; spacing: 2
+ Content { }
+ }
+ }
+ ]
+}
diff --git a/doc/src/snippets/declarative/border-image.qml b/doc/src/snippets/declarative/border-image.qml
new file mode 100644
index 0000000..c4215cd
--- /dev/null
+++ b/doc/src/snippets/declarative/border-image.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ color: "white"
+ width: 520; height: 280
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 50
+//! [0]
+ BorderImage {
+ width: 180; height: 180
+ border.left: 30; border.top: 30
+ border.right: 30; border.bottom: 30
+ horizontalTileMode: BorderImage.Stretch
+ verticalTileMode: BorderImage.Stretch
+ source: "content/colors.png"
+ }
+
+ BorderImage {
+ width: 180; height: 180
+ border.left: 30; border.top: 30
+ border.right: 30; border.bottom: 30
+ horizontalTileMode: BorderImage.Round
+ verticalTileMode: BorderImage.Round
+ source: "content/colors.png"
+ }
+//! [0]
+ }
+}
diff --git a/doc/src/snippets/declarative/comments.qml b/doc/src/snippets/declarative/comments.qml
new file mode 100644
index 0000000..806be29
--- /dev/null
+++ b/doc/src/snippets/declarative/comments.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+Text {
+ text: "Hello world!" //a basic greeting
+ /*
+ We want this text to stand out from the rest so
+ we give it a large size and different font.
+ */
+ font.family: "Helvetica"
+ font.pointSize: 24
+}
diff --git a/doc/src/snippets/declarative/content.qml b/doc/src/snippets/declarative/content.qml
new file mode 100644
index 0000000..fb03ced
--- /dev/null
+++ b/doc/src/snippets/declarative/content.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 100; color: "lightgray"
+ GroupBox {
+ Text { text: "First Item" }
+ Text { text: "Second Item" }
+ }
+}
diff --git a/doc/src/snippets/declarative/drag.qml b/doc/src/snippets/declarative/drag.qml
new file mode 100644
index 0000000..8735d0c
--- /dev/null
+++ b/doc/src/snippets/declarative/drag.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+//! [0]
+Rectangle {
+ id: blurtest; width: 600; height: 200; color: "white"
+ Image {
+ id: pic; source: "qtlogo-64.png"; anchors.verticalCenter: parent.verticalCenter
+ opacity: (600.0-pic.x) / 600;
+ MouseRegion {
+ anchors.fill: parent
+ drag.target: pic
+ drag.axis: "XAxis"
+ drag.minimumX: 0
+ drag.maximumX: blurtest.width-pic.width
+ }
+ }
+}
+//! [0]
diff --git a/doc/src/snippets/declarative/gradient.qml b/doc/src/snippets/declarative/gradient.qml
new file mode 100644
index 0000000..281360e
--- /dev/null
+++ b/doc/src/snippets/declarative/gradient.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+Rectangle {
+ width: 100; height: 100
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "red" }
+ GradientStop { position: 0.33; color: "yellow" }
+ GradientStop { position: 1.0; color: "green" }
+ }
+}
diff --git a/doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml b/doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
new file mode 100644
index 0000000..3cf9ba7
--- /dev/null
+++ b/doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+ListModel {
+ id: contactModel
+ ListElement {
+ name: "Bill Smith"
+ number: "555 3264"
+ portrait: "pics/portrait.png"
+ }
+ ListElement {
+ name: "Jim Williams"
+ number: "555 5673"
+ portrait: "pics/portrait.png"
+ }
+ ListElement {
+ name: "John Brown"
+ number: "555 8426"
+ portrait: "pics/portrait.png"
+ }
+ ListElement {
+ name: "Sam Wise"
+ number: "555 0473"
+ portrait: "pics/portrait.png"
+ }
+}
diff --git a/doc/src/snippets/declarative/gridview/gridview.qml b/doc/src/snippets/declarative/gridview/gridview.qml
new file mode 100644
index 0000000..1a2021c
--- /dev/null
+++ b/doc/src/snippets/declarative/gridview/gridview.qml
@@ -0,0 +1,47 @@
+import Qt 4.6
+
+//! [3]
+Rectangle {
+ width: 240; height: 180; color: "white"
+ // ContactModel model is defined in dummydata/ContactModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+//! [0]
+ Component {
+ id: delegate
+ Item {
+ id: wrapper
+ width: 80; height: 78
+ Column {
+ Image { source: portrait; anchors.horizontalCenter: parent.horizontalCenter }
+ Text { text: name; anchors.horizontalCenter: parent.horizontalCenter }
+ }
+ }
+ }
+//! [0]
+ // Define a highlight component. Just one of these will be instantiated
+ // by each ListView and placed behind the current item.
+//! [1]
+ Component {
+ id: highlight
+ Rectangle {
+ color: "lightsteelblue"
+ radius: 5
+ }
+ }
+//! [1]
+ // The actual grid
+//! [2]
+ GridView {
+ width: parent.width; height: parent.height
+ model: ContactModel; delegate: delegate
+ cellWidth: 80; cellHeight: 80
+ highlight: highlight
+ focus: true
+ }
+//! [2]
+}
+//! [3]
diff --git a/doc/src/snippets/declarative/gridview/pics/portrait.png b/doc/src/snippets/declarative/gridview/pics/portrait.png
new file mode 100644
index 0000000..fb5052a
--- /dev/null
+++ b/doc/src/snippets/declarative/gridview/pics/portrait.png
Binary files differ
diff --git a/doc/src/snippets/declarative/listview/dummydata/ContactModel.qml b/doc/src/snippets/declarative/listview/dummydata/ContactModel.qml
new file mode 100644
index 0000000..6832308
--- /dev/null
+++ b/doc/src/snippets/declarative/listview/dummydata/ContactModel.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+
+ListModel {
+ id: contactModel
+ ListElement {
+ name: "Bill Smith"
+ number: "555 3264"
+ }
+ ListElement {
+ name: "John Brown"
+ number: "555 8426"
+ }
+ ListElement {
+ name: "Sam Wise"
+ number: "555 0473"
+ }
+}
diff --git a/doc/src/snippets/declarative/listview/highlight.qml b/doc/src/snippets/declarative/listview/highlight.qml
new file mode 100644
index 0000000..b016f9a
--- /dev/null
+++ b/doc/src/snippets/declarative/listview/highlight.qml
@@ -0,0 +1,63 @@
+import Qt 4.6
+
+Rectangle {
+ width: 180; height: 200; color: "white"
+
+ // ContactModel model is defined in dummydata/ContactModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+//! [0]
+ Component {
+ id: delegate
+ Item {
+ id: wrapper
+ width: 180; height: 40
+ Column {
+ x: 5; y: 5
+ Text { text: '<b>Name:</b> ' + name }
+ Text { text: '<b>Number:</b> ' + number }
+ }
+ // Use the ListView.isCurrentItem attached property to
+ // indent the item if it is the current item.
+ states: [
+ State {
+ name: "Current"
+ when: wrapper.ListView.isCurrentItem
+ PropertyChanges { target: wrapper; x: 10 }
+ }
+ ]
+ transitions: [
+ Transition { NumberAnimation { matchProperties: "x"; duration: 200 } }
+ ]
+ }
+ }
+//! [0]
+ // Specify a highlight with custom movement. Note that autoHighlight
+ // is set to false in the ListView so that we can control how the
+ // highlight moves to the current item.
+//! [1]
+ Component {
+ id: highlight
+ Rectangle {
+ width: 180; height: 40
+ color: "lightsteelblue"; radius: 5
+ y: SpringFollow {
+ source: list.currentItem.y
+ spring: 3
+ damping: 0.2
+ }
+ }
+ }
+ ListView {
+ id: list
+ width: parent.height; height: parent.height
+ model: ContactModel; delegate: delegate
+ highlight: highlight
+ highlightFollowsCurrentItem: false
+ focus: true
+ }
+//! [1]
+}
diff --git a/doc/src/snippets/declarative/listview/listview.qml b/doc/src/snippets/declarative/listview/listview.qml
new file mode 100644
index 0000000..be0f3ad
--- /dev/null
+++ b/doc/src/snippets/declarative/listview/listview.qml
@@ -0,0 +1,49 @@
+import Qt 4.6
+
+//! [3]
+Rectangle {
+ width: 180; height: 200; color: "white"
+
+ // ContactModel model is defined in dummydata/ContactModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+//! [0]
+ Component {
+ id: delegate
+ Item {
+ id: wrapper
+ width: 180; height: 40
+ Column {
+ x: 5; y: 5
+ Text { text: '<b>Name:</b> ' + name }
+ Text { text: '<b>Number:</b> ' + number }
+ }
+ }
+ }
+//! [0]
+ // Define a highlight component. Just one of these will be instantiated
+ // by each ListView and placed behind the current item.
+//! [1]
+ Component {
+ id: highlight
+ Rectangle {
+ color: "lightsteelblue"
+ radius: 5
+ }
+ }
+//! [1]
+ // The actual list
+//! [2]
+ ListView {
+ width: parent.width; height: parent.height
+ model: ContactModel
+ delegate: delegate
+ highlight: highlight
+ focus: true
+ }
+//! [2]
+}
+//! [3]
diff --git a/doc/src/snippets/declarative/mouseregion.qml b/doc/src/snippets/declarative/mouseregion.qml
new file mode 100644
index 0000000..67857f5
--- /dev/null
+++ b/doc/src/snippets/declarative/mouseregion.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+Rectangle { width: 200; height: 100
+HorizontalLayout {
+//! [0]
+Rectangle { width: 100; height: 100; color: "green"
+ MouseRegion { anchors.fill: parent; onClicked: { parent.color = 'red' } }
+}
+//! [0]
+//! [1]
+Rectangle {
+ width: 100; height: 100; color: "green"
+ MouseRegion {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onClicked: {
+ if (mouse.button == Qt.RightButton)
+ parent.color = 'blue';
+ else
+ parent.color = 'red';
+ }
+ }
+}
+//! [1]
+}
+}
diff --git a/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml
new file mode 100644
index 0000000..1334cf4
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+
+ListModel {
+ id: menuModel
+ ListElement {
+ name: "Bill Jones"
+ icon: "pics/qtlogo-64.png"
+ }
+ ListElement {
+ name: "Jane Doe"
+ icon: "pics/qtlogo-64.png"
+ }
+ ListElement {
+ name: "John Smith"
+ icon: "pics/qtlogo-64.png"
+ }
+}
diff --git a/doc/src/snippets/declarative/pathview/pathattributes.qml b/doc/src/snippets/declarative/pathview/pathattributes.qml
new file mode 100644
index 0000000..19a192c
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/pathattributes.qml
@@ -0,0 +1,36 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240; height: 200; color: 'white'
+//! [0]
+//! [1]
+ Component {
+ id: delegate
+ Item {
+ id: wrapper
+ width: 80; height: 80
+ scale: PathView.scale
+ opacity: PathView.opacity
+ Column {
+ Image { anchors.horizontalCenter: name.horizontalCenter; width: 64; height: 64; source: icon }
+ Text { id: name; text: name; font.pointSize: 16}
+ }
+ }
+ }
+//! [1]
+//! [2]
+ PathView {
+ anchors.fill: parent; model: MenuModel; delegate: delegate
+ path: Path {
+ startX: 120; startY: 100
+ PathAttribute { name: "scale"; value: 1.0 }
+ PathAttribute { name: "opacity"; value: 1.0 }
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathAttribute { name: "scale"; value: 0.3 }
+ PathAttribute { name: "opacity"; value: 0.5 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+//! [2]
+//! [0]
+}
diff --git a/doc/src/snippets/declarative/pathview/pathview.qml b/doc/src/snippets/declarative/pathview/pathview.qml
new file mode 100644
index 0000000..5605139
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/pathview.qml
@@ -0,0 +1,30 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240; height: 200; color: 'white'
+//! [0]
+//! [1]
+ Component {
+ id: delegate
+ Item {
+ id: wrapper
+ width: 80; height: 80
+ Column {
+ Image { anchors.horizontalCenter: name.horizontalCenter; width: 64; height: 64; source: icon }
+ Text { id: name; text: name; font.pointSize: 16}
+ }
+ }
+ }
+//! [1]
+//! [2]
+ PathView {
+ anchors.fill: parent; model: MenuModel; delegate: delegate
+ path: Path {
+ startX: 120; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+//! [2]
+//! [0]
+}
diff --git a/doc/src/snippets/declarative/pathview/pics/qtlogo-64.png b/doc/src/snippets/declarative/pathview/pics/qtlogo-64.png
new file mode 100644
index 0000000..4f68e16
--- /dev/null
+++ b/doc/src/snippets/declarative/pathview/pics/qtlogo-64.png
Binary files differ
diff --git a/doc/src/snippets/declarative/pics/qt.png b/doc/src/snippets/declarative/pics/qt.png
new file mode 100644
index 0000000..cbed1a9
--- /dev/null
+++ b/doc/src/snippets/declarative/pics/qt.png
Binary files differ
diff --git a/doc/src/snippets/declarative/repeater-index.qml b/doc/src/snippets/declarative/repeater-index.qml
new file mode 100644
index 0000000..9063967
--- /dev/null
+++ b/doc/src/snippets/declarative/repeater-index.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+
+Rectangle {
+ width: 50; height: childrenRect.height; color: "white"
+
+//! [0]
+ Column {
+ Repeater {
+ model: 10
+ Text { text: "I'm item " + index }
+ }
+ }
+//! [0]
+}
+
diff --git a/doc/src/snippets/declarative/repeater.qml b/doc/src/snippets/declarative/repeater.qml
new file mode 100644
index 0000000..f8ac856
--- /dev/null
+++ b/doc/src/snippets/declarative/repeater.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+Rectangle {
+ width: 220; height: 20; color: "white"
+
+//! [0]
+ Row {
+ Rectangle { width: 10; height: 20; color: "red" }
+ Repeater {
+ model: 10
+ Rectangle { width: 20; height: 20; radius: 10; color: "green" }
+ }
+ Rectangle { width: 10; height: 20; color: "blue" }
+ }
+//! [0]
+}
diff --git a/doc/src/snippets/declarative/rotation.qml b/doc/src/snippets/declarative/rotation.qml
new file mode 100644
index 0000000..4a67dcb
--- /dev/null
+++ b/doc/src/snippets/declarative/rotation.qml
@@ -0,0 +1,33 @@
+import Qt 4.6
+
+Rectangle {
+ width: 360; height: 80
+ color: "white"
+//! [0]
+ Row {
+ x: 10; y: 10
+ spacing: 10
+ Image { source: "pics/qt.png" }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation { origin.x: 30; origin.y: 30; axis { x: 0; y: 1; z: 0 } angle: 18 }
+ smooth: true
+ }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation { origin.x: 30; origin.y: 30; axis { x: 0; y: 1; z: 0 } angle: 36 }
+ smooth: true
+ }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation { origin.x: 30; origin.y: 30; axis { x: 0; y: 1; z: 0 } angle: 54 }
+ smooth: true
+ }
+ Image {
+ source: "pics/qt.png"
+ transform: Rotation { origin.x: 30; origin.y: 30; axis { x: 0; y: 1; z: 0 } angle: 72 }
+ smooth: true
+ }
+ }
+//! [0]
+}
diff --git a/doc/src/widgets-and-layouts/styles.qdoc b/doc/src/widgets-and-layouts/styles.qdoc
index b7f7322..9a28715 100644
--- a/doc/src/widgets-and-layouts/styles.qdoc
+++ b/doc/src/widgets-and-layouts/styles.qdoc
@@ -125,7 +125,7 @@
necessary for drawing. Thanks to QStyleOption, it is possible to make
QStyle draw widgets without linking in any code for the widget. This
makes it possible to use \l{QStyle}'s draw functions on any paint
- device. Ie you can draw a combobox on any widget, not just on a
+ device, i.e., you can draw a combobox on any widget, not just on a
QComboBox.
The widget is passed as the last argument in case the style needs
diff --git a/doc/src/widgets-and-layouts/stylesheet.qdoc b/doc/src/widgets-and-layouts/stylesheet.qdoc
index ebe67df..5f42f28 100644
--- a/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -3822,7 +3822,7 @@
The tear indicator and the scroll buttons can be further customized as follows:
\snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 148
- Sine Qt 4.6 the close button can be customized as follow:
+ Since Qt 4.6 the close button can be customized as follow:
\snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 159
\section2 Customizing QTableView
diff --git a/examples/dbus/dbus-chat/chat_adaptor.h b/examples/dbus/dbus-chat/chat_adaptor.h
index 831c4f5..47b7f8f 100644
--- a/examples/dbus/dbus-chat/chat_adaptor.h
+++ b/examples/dbus/dbus-chat/chat_adaptor.h
@@ -54,12 +54,15 @@
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
+
+QT_BEGIN_NAMESPACE
class QByteArray;
template<class T> class QList;
template<class Key, class Value> class QMap;
class QString;
class QStringList;
class QVariant;
+QT_END_NAMESPACE
/*
* Adaptor class for interface com.trolltech.chat
diff --git a/examples/dbus/remotecontrolledcar/car/car_adaptor.h b/examples/dbus/remotecontrolledcar/car/car_adaptor.h
index d109883..d16972e 100644
--- a/examples/dbus/remotecontrolledcar/car/car_adaptor.h
+++ b/examples/dbus/remotecontrolledcar/car/car_adaptor.h
@@ -54,12 +54,15 @@
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
+
+QT_BEGIN_NAMESPACE
class QByteArray;
template<class T> class QList;
template<class Key, class Value> class QMap;
class QString;
class QStringList;
class QVariant;
+QT_END_NAMESPACE
/*
* Adaptor class for interface com.trolltech.Examples.CarInterface
diff --git a/examples/declarative/anchors/anchor-changes.qml b/examples/declarative/anchors/anchor-changes.qml
new file mode 100644
index 0000000..2ebe1c0
--- /dev/null
+++ b/examples/declarative/anchors/anchor-changes.qml
@@ -0,0 +1,46 @@
+import Qt 4.6
+
+Item {
+ id: window
+ width: 200; height: 450
+
+ Rectangle {
+ id: titleBar; color: "Gray"
+ anchors.top: parent.top; height: 50
+ width: parent.width
+ }
+
+ Rectangle {
+ id: statusBar; color: "Gray"
+ height: 50; anchors.bottom: parent.bottom
+ width: parent.width
+ }
+
+ Rectangle {
+ id: content
+ anchors.top: titleBar.bottom; anchors.bottom: statusBar.top
+ width: parent.width
+
+ Text { text: "Top"; anchors.top: parent.top }
+ Text { text: "Bottom"; anchors.bottom: parent.bottom }
+ }
+
+ MouseRegion {
+ anchors.fill: content
+ onPressed: window.state = "FullScreen"
+ onReleased: window.state = ""
+ }
+
+ states : State {
+ name: "FullScreen"
+ //! [0]
+ AnchorChanges {
+ target: content; top: window.top; bottom: window.bottom
+ }
+ //! [0]
+ }
+
+ transitions : Transition {
+ NumberAnimation { matchProperties: "y,height" }
+ }
+}
diff --git a/examples/declarative/animations/color-animation.qml b/examples/declarative/animations/color-animation.qml
new file mode 100644
index 0000000..7171a69
--- /dev/null
+++ b/examples/declarative/animations/color-animation.qml
@@ -0,0 +1,70 @@
+import Qt 4.6
+
+Item {
+ id: window
+ width: 640; height: 480
+
+ // Let's draw the sky...
+ Rectangle {
+ anchors { left: parent.left; top: parent.top; right: parent.right; bottom: parent.verticalCenter }
+ gradient: Gradient {
+ GradientStop {
+ position: 0.0
+ color: SequentialAnimation {
+ repeat: true
+ ColorAnimation { from: "DeepSkyBlue"; to: "#0E1533"; duration: 5000 }
+ ColorAnimation { from: "#0E1533"; to: "DeepSkyBlue"; duration: 5000 }
+ }
+ }
+ GradientStop {
+ position: 1.0
+ color: SequentialAnimation {
+ repeat: true
+ ColorAnimation { from: "SkyBlue"; to: "#437284"; duration: 5000 }
+ ColorAnimation { from: "#437284"; to: "SkyBlue"; duration: 5000 }
+ }
+ }
+ }
+ }
+
+ // the sun, moon, and stars
+ Item {
+ width: parent.width; height: 2 * parent.height
+ transformOrigin: Item.Center
+ rotation: NumberAnimation { from: 0; to: 360; duration: 10000; repeat: true }
+ Image {
+ source: "images/sun.png"; y: 10; anchors.horizontalCenter: parent.horizontalCenter
+ transformOrigin: Item.Center; rotation: -3 * parent.rotation
+ }
+ Image {
+ source: "images/moon.png"; y: parent.height - 74; anchors.horizontalCenter: parent.horizontalCenter
+ transformOrigin: Item.Center; rotation: -parent.rotation
+ }
+ Particles {
+ x: 0; y: parent.height/2; width: parent.width; height: parent.height/2
+ source: "images/star.png"; angleDeviation: 360; velocity: 0
+ velocityDeviation: 0; count: parent.width / 10; fadeInDuration: 2800
+ opacity: SequentialAnimation {
+ repeat: true
+ NumberAnimation { from: 0; to: 1; duration: 5000 }
+ NumberAnimation { from: 1; to: 0; duration: 5000 }
+ }
+ }
+ }
+
+ // ...and the ground.
+ Rectangle {
+ anchors { left: parent.left; top: parent.verticalCenter; right: parent.right; bottom: parent.bottom }
+ gradient: Gradient {
+ GradientStop {
+ position: 0.0
+ color: SequentialAnimation {
+ repeat: true
+ ColorAnimation { from: "ForestGreen"; to: "#001600"; duration: 5000 }
+ ColorAnimation { from: "#001600"; to: "ForestGreen"; duration: 5000 }
+ }
+ }
+ GradientStop { position: 1.0; color: "DarkGreen" }
+ }
+ }
+}
diff --git a/examples/declarative/animations/easing.qml b/examples/declarative/animations/easing.qml
new file mode 100644
index 0000000..a9ba05f
--- /dev/null
+++ b/examples/declarative/animations/easing.qml
@@ -0,0 +1,99 @@
+import Qt 4.6
+
+Rectangle {
+ id: window
+ width: 600; height: 460; color: "#232323"
+
+ ListModel {
+ id: easingTypes
+ ListElement { type: "easeLinear"; ballColor: "DarkRed" }
+ ListElement { type: "easeInQuad"; ballColor: "IndianRed" }
+ ListElement { type: "easeOutQuad"; ballColor: "Salmon" }
+ ListElement { type: "easeInOutQuad"; ballColor: "Tomato" }
+ ListElement { type: "easeOutInQuad"; ballColor: "DarkOrange" }
+ ListElement { type: "easeInCubic"; ballColor: "Gold" }
+ ListElement { type: "easeOutCubic"; ballColor: "Yellow" }
+ ListElement { type: "easeInOutCubic"; ballColor: "PeachPuff" }
+ ListElement { type: "easeOutInCubic"; ballColor: "Thistle" }
+ ListElement { type: "easeInQuart"; ballColor: "Orchid" }
+ ListElement { type: "easeOutQuart"; ballColor: "Purple" }
+ ListElement { type: "easeInOutQuart"; ballColor: "SlateBlue" }
+ ListElement { type: "easeOutInQuart"; ballColor: "Chartreuse" }
+ ListElement { type: "easeInQuint"; ballColor: "LimeGreen" }
+ ListElement { type: "easeOutQuint"; ballColor: "SeaGreen" }
+ ListElement { type: "easeInOutQuint"; ballColor: "DarkGreen" }
+ ListElement { type: "easeOutInQuint"; ballColor: "Olive" }
+ ListElement { type: "easeInSine"; ballColor: "DarkSeaGreen" }
+ ListElement { type: "easeOutSine"; ballColor: "Teal" }
+ ListElement { type: "easeInOutSine"; ballColor: "Turquoise" }
+ ListElement { type: "easeOutInSine"; ballColor: "SteelBlue" }
+ ListElement { type: "easeInExpo"; ballColor: "SkyBlue" }
+ ListElement { type: "easeOutExpo"; ballColor: "RoyalBlue" }
+ ListElement { type: "easeInOutExpo"; ballColor: "MediumBlue" }
+ ListElement { type: "easeOutInExpo"; ballColor: "MidnightBlue" }
+ ListElement { type: "easeInCirc"; ballColor: "CornSilk" }
+ ListElement { type: "easeOutCirc"; ballColor: "Bisque" }
+ ListElement { type: "easeInOutCirc"; ballColor: "RosyBrown" }
+ ListElement { type: "easeOutInCirc"; ballColor: "SandyBrown" }
+ ListElement { type: "easeInElastic"; ballColor: "DarkGoldenRod" }
+ ListElement { type: "easeOutElastic"; ballColor: "Chocolate" }
+ ListElement { type: "easeInOutElastic"; ballColor: "SaddleBrown" }
+ ListElement { type: "easeOutInElastic"; ballColor: "Brown" }
+ ListElement { type: "easeInBack"; ballColor: "Maroon" }
+ ListElement { type: "easeOutBack"; ballColor: "LavenderBlush" }
+ ListElement { type: "easeInOutBack"; ballColor: "MistyRose" }
+ ListElement { type: "easeOutInBack"; ballColor: "Gainsboro" }
+ ListElement { type: "easeOutBounce"; ballColor: "Silver" }
+ ListElement { type: "easeInBounce"; ballColor: "DimGray" }
+ ListElement { type: "easeInOutBounce"; ballColor: "SlateGray" }
+ ListElement { type: "easeOutInBounce"; ballColor: "DarkSlateGray" }
+ }
+
+ Component {
+ id: delegate
+
+ Item {
+ height: 42; width: window.width
+ Text { text: type; anchors.centerIn: parent; color: "White" }
+ Rectangle {
+ id: slot1; color: "#121212"; x: 30; height: 32; width: 32
+ border.color: "#343434"; border.width: 1; radius: 8; anchors.verticalCenter: parent.verticalCenter
+ }
+ Rectangle {
+ id: slot2; color: "#121212"; x: window.width - 62; height: 32; width: 32
+ border.color: "#343434"; border.width: 1; radius: 8; anchors.verticalCenter: parent.verticalCenter
+ }
+ Rectangle {
+ id: rect; x: 30; color: "#454545"
+ border.color: "White"; border.width: 2
+ height: 32; width: 32; radius: 8; anchors.verticalCenter: parent.verticalCenter
+
+ MouseRegion {
+ onClicked: if (rect.state == '') rect.state = "right"; else rect.state = ''
+ anchors.fill: parent
+ }
+
+ states : State {
+ name: "right"
+ PropertyChanges { target: rect; x: window.width - 62; color: ballColor }
+ }
+
+ transitions: Transition {
+ ParallelAnimation {
+ NumberAnimation { matchProperties: "x"; easing: type; duration: 1000 }
+ ColorAnimation { matchProperties: "color"; easing: type; duration: 1000 }
+ }
+ }
+ }
+ }
+ }
+
+ Flickable {
+ anchors.fill: parent; viewportHeight: layout.height
+ Column {
+ id: layout
+ anchors.left: parent.left; anchors.right: parent.right
+ Repeater { model: easingTypes; delegate: delegate }
+ }
+ }
+}
diff --git a/examples/declarative/animations/images/face-smile.png b/examples/declarative/animations/images/face-smile.png
new file mode 100644
index 0000000..3d66d72
--- /dev/null
+++ b/examples/declarative/animations/images/face-smile.png
Binary files differ
diff --git a/examples/declarative/animations/images/moon.png b/examples/declarative/animations/images/moon.png
new file mode 100644
index 0000000..9407b2b
--- /dev/null
+++ b/examples/declarative/animations/images/moon.png
Binary files differ
diff --git a/examples/declarative/animations/images/shadow.png b/examples/declarative/animations/images/shadow.png
new file mode 100644
index 0000000..8270565
--- /dev/null
+++ b/examples/declarative/animations/images/shadow.png
Binary files differ
diff --git a/examples/declarative/animations/images/star.png b/examples/declarative/animations/images/star.png
new file mode 100644
index 0000000..27ef924
--- /dev/null
+++ b/examples/declarative/animations/images/star.png
Binary files differ
diff --git a/examples/declarative/animations/images/sun.png b/examples/declarative/animations/images/sun.png
new file mode 100644
index 0000000..7713ca5
--- /dev/null
+++ b/examples/declarative/animations/images/sun.png
Binary files differ
diff --git a/examples/declarative/animations/property-animation.qml b/examples/declarative/animations/property-animation.qml
new file mode 100644
index 0000000..9f76ee5
--- /dev/null
+++ b/examples/declarative/animations/property-animation.qml
@@ -0,0 +1,64 @@
+import Qt 4.6
+
+Item {
+ id: window
+ width: 320; height: 480
+
+ // Let's draw the sky...
+ Rectangle {
+ anchors { left: parent.left; top: parent.top; right: parent.right; bottom: parent.verticalCenter }
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "DeepSkyBlue" }
+ GradientStop { position: 1.0; color: "LightSkyBlue" }
+ }
+ }
+
+ // ...and the ground.
+ Rectangle {
+ anchors { left: parent.left; top: parent.verticalCenter; right: parent.right; bottom: parent.bottom }
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "ForestGreen" }
+ GradientStop { position: 1.0; color: "DarkGreen" }
+ }
+ }
+
+ // The shadow for the smiley face
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: "images/shadow.png"; y: smiley.minHeight + 58
+ transformOrigin: Item.Center
+
+ // The scale property depends on the y position of the smiley face.
+ scale: smiley.y * 0.5 / (smiley.minHeight - smiley.maxHeight)
+ }
+
+ Image {
+ id: smiley
+ property int maxHeight: window.height / 3
+ property int minHeight: 2 * window.height / 3
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: "images/face-smile.png"; y: minHeight
+
+ // Animate the y property. Setting repeat to true makes the
+ // animation repeat indefinitely, otherwise it would only run once.
+ y: SequentialAnimation {
+ repeat: true
+
+ // Move from minHeight to maxHeight in 300ms, using the easeOutExpo easing function
+ NumberAnimation {
+ from: smiley.minHeight; to: smiley.maxHeight
+ easing: "easeOutExpo"; duration: 300
+ }
+
+ // Then move back to minHeight in 1 second, using the easeOutBounce easing function
+ NumberAnimation {
+ from: smiley.maxHeight; to: smiley.minHeight
+ easing: "easeOutBounce"; duration: 1000
+ }
+
+ // Then pause for 500ms
+ PauseAnimation { duration: 500 }
+ }
+ }
+}
diff --git a/examples/declarative/aspectratio/face_fit.qml b/examples/declarative/aspectratio/face_fit.qml
new file mode 100644
index 0000000..482d1b7
--- /dev/null
+++ b/examples/declarative/aspectratio/face_fit.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+// Here, we implement a hybrid of the "scale to fit" and "scale and crop"
+// behaviours which will crop up to 25% from *one* dimension if necessary
+// to fully scale the other. This is a realistic algorithm, for example
+// when the edges of the image contain less vital information than the
+// center - such as a face.
+//
+Rectangle {
+ // default size: whole image, unscaled
+ width: face.width
+ height: face.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: face
+ smooth: true
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: Math.max(Math.min(parent.width/width*1.333,parent.height/height),
+ Math.min(parent.width/width,parent.height/height*1.333))
+ }
+}
diff --git a/examples/declarative/aspectratio/face_fit_animated.qml b/examples/declarative/aspectratio/face_fit_animated.qml
new file mode 100644
index 0000000..80a762b
--- /dev/null
+++ b/examples/declarative/aspectratio/face_fit_animated.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+// Here, we extend the "face_fit" example with animation to show how truly
+// diverse and usage-specific behaviours are made possible by NOT putting a
+// hard-coded aspect ratio feature into the Image primitive.
+//
+Rectangle {
+ // default size: whole image, unscaled
+ width: face.width
+ height: face.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: face
+ smooth: true
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: SpringFollow {
+ source: Math.max(Math.min(face.parent.width/face.width*1.333,face.parent.height/face.height),
+ Math.min(face.parent.width/face.width,face.parent.height/face.height*1.333))
+ spring: 1
+ damping: 0.05
+ }
+ }
+}
diff --git a/examples/declarative/aspectratio/pics/face.png b/examples/declarative/aspectratio/pics/face.png
new file mode 100644
index 0000000..3d66d72
--- /dev/null
+++ b/examples/declarative/aspectratio/pics/face.png
Binary files differ
diff --git a/examples/declarative/aspectratio/scale_and_crop.qml b/examples/declarative/aspectratio/scale_and_crop.qml
new file mode 100644
index 0000000..283e24b
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_and_crop.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+// Here, we implement "Scale and Crop" behaviour.
+//
+Rectangle {
+ // default size: whole image, unscaled
+ width: face.width
+ height: face.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: face
+ smooth: true
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: Math.max(parent.width/width,parent.height/height)
+ }
+}
diff --git a/examples/declarative/aspectratio/scale_and_crop_simple.qml b/examples/declarative/aspectratio/scale_and_crop_simple.qml
new file mode 100644
index 0000000..e720ce7
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_and_crop_simple.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+// Here, we implement "Scale to Fit" behaviour, using the
+// fillMode property.
+//
+Rectangle {
+ // default size: whole image, unscaled
+ width: face.width
+ height: face.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: face
+ smooth: true
+ source: "pics/face.png"
+ fillMode: Image.PreserveAspectCrop
+ anchors.fill: parent
+ }
+}
diff --git a/examples/declarative/aspectratio/scale_and_sidecrop.qml b/examples/declarative/aspectratio/scale_and_sidecrop.qml
new file mode 100644
index 0000000..c3ef859
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_and_sidecrop.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+// Here, we implement a variant of "Scale and Crop" behaviour, where we
+// crop the sides if necessary to fully fit vertically, but not the reverse.
+//
+Rectangle {
+ // default size: whole image, unscaled
+ width: face.width
+ height: face.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: face
+ smooth: true
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: parent.height/height
+ }
+}
diff --git a/examples/declarative/aspectratio/scale_to_fit.qml b/examples/declarative/aspectratio/scale_to_fit.qml
new file mode 100644
index 0000000..961ac04
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_to_fit.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+// Here, we implement "Scale to Fit" behaviour "manually", rather
+// than using the preserveAspect property.
+//
+Rectangle {
+ // default size: whole image, unscaled
+ width: face.width
+ height: face.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: face
+ smooth: true
+ source: "pics/face.png"
+ x: (parent.width-width*scale)/2
+ y: (parent.height-height*scale)/2
+ scale: Math.min(parent.width/width,parent.height/height)
+ }
+}
diff --git a/examples/declarative/aspectratio/scale_to_fit_simple.qml b/examples/declarative/aspectratio/scale_to_fit_simple.qml
new file mode 100644
index 0000000..7389581
--- /dev/null
+++ b/examples/declarative/aspectratio/scale_to_fit_simple.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+// Here, we implement "Scale to Fit" behaviour, using the
+// fillMode property.
+//
+Rectangle {
+ // default size: whole image, unscaled
+ width: face.width
+ height: face.height
+ color: "gray"
+ clip: true
+
+ Image {
+ id: face
+ smooth: true
+ source: "pics/face.png"
+ fillMode: Image.PreserveAspectFit
+ anchors.fill: parent
+ }
+}
diff --git a/examples/declarative/behaviours/MyRect.qml b/examples/declarative/behaviours/MyRect.qml
new file mode 100644
index 0000000..a272e1f
--- /dev/null
+++ b/examples/declarative/behaviours/MyRect.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+Rectangle {
+ radius: 15
+ border.color: "black"
+ width: 100
+ height: 100
+ id: page
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { bluerect.parent = page; bluerect.x=0 }
+ }
+}
diff --git a/examples/declarative/behaviours/SideRect.qml b/examples/declarative/behaviours/SideRect.qml
new file mode 100644
index 0000000..c7c7ebf
--- /dev/null
+++ b/examples/declarative/behaviours/SideRect.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+
+Rectangle {
+ id: myRect
+
+ property string text
+
+ color: "black"
+ width: 75; height: 50
+ radius: 5
+ border.width: 10; border.color: "white";
+ MouseRegion {
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: { focusRect.x = myRect.x; focusRect.y = myRect.y; focusRect.text = myRect.text }
+ }
+}
diff --git a/examples/declarative/behaviours/behavior.qml b/examples/declarative/behaviours/behavior.qml
new file mode 100644
index 0000000..2732c0a
--- /dev/null
+++ b/examples/declarative/behaviours/behavior.qml
@@ -0,0 +1,72 @@
+import Qt 4.6
+
+Rectangle {
+ color: "black"
+ width: 400; height: 400
+
+ Rectangle {
+ color: "transparent"
+ anchors.centerIn: parent
+ width: 200; height: 200
+ radius: 30
+ border.width: 10; border.color: "white";
+
+ SideRect {
+ id: leftRect
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.left
+ text: "Left"
+ }
+
+ SideRect {
+ id: rightRect
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.right
+ text: "Right"
+ }
+
+ SideRect {
+ id: topRect
+ anchors.verticalCenter: parent.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "Top"
+ }
+
+ SideRect {
+ id: bottomRect
+ anchors.verticalCenter: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "Bottom"
+ }
+
+
+ Rectangle {
+ id: focusRect
+
+ property string text
+
+ color: "red"
+ width: 75; height: 50
+ radius: 5
+ border.width: 10; border.color: "white";
+ x: 100-37; y: 100-25
+ x: Behavior { NumberAnimation { duration: 300 } }
+ y: Behavior { NumberAnimation { duration: 300 } }
+ Text {
+ id: focusText
+ text: focusRect.text;
+ text: Behavior {
+ SequentialAnimation {
+ NumberAnimation { target: focusText; property: "opacity"; to: 0; duration: 150 }
+ PropertyAction {}
+ NumberAnimation { target: focusText; property: "opacity"; to: 1; duration: 150 }
+ }
+ }
+ anchors.centerIn: parent;
+ color: "white";
+ font.pixelSize: 16
+ font.bold: true
+ }
+ }
+ }
+}
diff --git a/examples/declarative/behaviours/test.qml b/examples/declarative/behaviours/test.qml
new file mode 100644
index 0000000..1869c45
--- /dev/null
+++ b/examples/declarative/behaviours/test.qml
@@ -0,0 +1,100 @@
+import Qt 4.6
+
+Rectangle {
+ color: "lightsteelblue"
+ width: 800
+ height: 600
+ id: page
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { bluerect.parent = page; console.log(mouseX); bluerect.x = mouseX; }
+ }
+ MyRect {
+ color: "green"
+ x: 200
+ y: 200
+ }
+ MyRect {
+ color: "red"
+ x: 400
+ y: 200
+ }
+ MyRect {
+ color: "yellow"
+ x: 400
+ y: 400
+ }
+ MyRect {
+ color: "orange"
+ x: 400
+ y: 500
+ }
+ MyRect {
+ color: "pink"
+ x: 400
+ y: 0
+ }
+ MyRect {
+ color: "lightsteelblue"
+ x: 100
+ y: 500
+ }
+ MyRect {
+ color: "black"
+ x: 0
+ y: 200
+ }
+ MyRect {
+ color: "white"
+ x: 400
+ y: 0
+ }
+ Rectangle {
+ color: "blue"
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ id: bluerect
+ x: Behavior {
+ ParallelAnimation {
+ SequentialAnimation {
+ NumberAnimation {
+ target: bluerect
+ property: "y"
+ from: 0
+ to: 10
+ easing: "easeOutBounce(amplitude:30)"
+ duration: 250
+ }
+ NumberAnimation {
+ target: bluerect
+ property: "y"
+ from: 10
+ to: 0
+ easing: "easeOutBounce(amplitude:30)"
+ duration: 250
+ }
+ }
+ NumberAnimation { duration: 500 }
+ }
+ }
+ parent: Behavior {
+ SequentialAnimation {
+ NumberAnimation {
+ target: bluerect
+ property: "opacity"
+ to: 0
+ duration: 150
+ }
+ PropertyAction {}
+ NumberAnimation {
+ target: bluerect
+ property: "opacity"
+ to: 1
+ duration: 150
+ }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/border-image/animated.qml b/examples/declarative/border-image/animated.qml
new file mode 100644
index 0000000..29c02b3
--- /dev/null
+++ b/examples/declarative/border-image/animated.qml
@@ -0,0 +1,55 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ id: page
+ color: "white"
+ width: 1030; height: 540
+
+ MyBorderImage {
+ x: 20; y: 20; minWidth: 120; maxWidth: 240
+ minHeight: 120; maxHeight: 240
+ source: "content/colors.png"; margin: 30
+ }
+ MyBorderImage {
+ x: 270; y: 20; minWidth: 120; maxWidth: 240
+ minHeight: 120; maxHeight: 240
+ source: "content/colors.png"; margin: 30
+ horizontalMode: BorderImage.Repeat; verticalMode: BorderImage.Repeat
+ }
+ MyBorderImage {
+ x: 520; y: 20; minWidth: 120; maxWidth: 240
+ minHeight: 120; maxHeight: 240
+ source: "content/colors.png"; margin: 30
+ horizontalMode: BorderImage.Stretch; verticalMode: BorderImage.Repeat
+ }
+ MyBorderImage {
+ x: 770; y: 20; minWidth: 120; maxWidth: 240
+ minHeight: 120; maxHeight: 240
+ source: "content/colors.png"; margin: 30
+ horizontalMode: BorderImage.Round; verticalMode: BorderImage.Round
+ }
+ MyBorderImage {
+ x: 20; y: 280; minWidth: 60; maxWidth: 200
+ minHeight: 40; maxHeight: 200
+ source: "content/bw.png"; margin: 10
+ }
+ MyBorderImage {
+ x: 270; y: 280; minWidth: 60; maxWidth: 200
+ minHeight: 40; maxHeight: 200
+ source: "content/bw.png"; margin: 10
+ horizontalMode: BorderImage.Repeat; verticalMode: BorderImage.Repeat
+ }
+ MyBorderImage {
+ x: 520; y: 280; minWidth: 60; maxWidth: 200
+ minHeight: 40; maxHeight: 200
+ source: "content/bw.png"; margin: 10
+ horizontalMode: BorderImage.Stretch; verticalMode: BorderImage.Repeat
+ }
+ MyBorderImage {
+ x: 770; y: 280; minWidth: 60; maxWidth: 200
+ minHeight: 40; maxHeight: 200
+ source: "content/bw.png"; margin: 10
+ horizontalMode: BorderImage.Round; verticalMode: BorderImage.Round
+ }
+}
diff --git a/examples/declarative/border-image/borders.qml b/examples/declarative/border-image/borders.qml
new file mode 100644
index 0000000..9879416
--- /dev/null
+++ b/examples/declarative/border-image/borders.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ color: "white"
+ width: 520; height: 280
+
+ BorderImage {
+ x: 20; y: 20; width: 230; height: 240
+ smooth: true
+ source: "content/colors-stretch.sci"
+ }
+ BorderImage {
+ x: 270; y: 20; width: 230; height: 240
+ smooth: true
+ source: "content/colors-round.sci"
+ }
+}
diff --git a/examples/declarative/border-image/content/MyBorderImage.qml b/examples/declarative/border-image/content/MyBorderImage.qml
new file mode 100644
index 0000000..a57acc7
--- /dev/null
+++ b/examples/declarative/border-image/content/MyBorderImage.qml
@@ -0,0 +1,37 @@
+import Qt 4.6
+
+Item {
+ property alias horizontalMode: image.horizontalTileMode
+ property alias verticalMode: image.verticalTileMode
+ property alias source: image.source
+
+ property int minWidth
+ property int minHeight
+ property int maxWidth
+ property int maxHeight
+ property int margin
+
+ id: container
+ width: 240; height: 240
+
+ BorderImage {
+ id: image; x: container.width / 2 - width / 2; y: container.height / 2 - height / 2
+
+ width: SequentialAnimation {
+ repeat: true
+ NumberAnimation { from: container.minWidth; to: container.maxWidth; duration: 2000; easing: "easeInOutQuad"}
+ NumberAnimation { from: container.maxWidth; to: container.minWidth; duration: 2000; easing: "easeInOutQuad" }
+ }
+
+ height: SequentialAnimation {
+ repeat: true
+ NumberAnimation { from: container.minHeight; to: container.maxHeight; duration: 2000; easing: "easeInOutQuad"}
+ NumberAnimation { from: container.maxHeight; to: container.minHeight; duration: 2000; easing: "easeInOutQuad" }
+ }
+
+ border.top: container.margin
+ border.left: container.margin
+ border.bottom: container.margin
+ border.right: container.margin
+ }
+}
diff --git a/examples/declarative/border-image/content/bw.png b/examples/declarative/border-image/content/bw.png
new file mode 100644
index 0000000..486eaae
--- /dev/null
+++ b/examples/declarative/border-image/content/bw.png
Binary files differ
diff --git a/examples/declarative/border-image/content/colors-round.sci b/examples/declarative/border-image/content/colors-round.sci
new file mode 100644
index 0000000..506f6f5
--- /dev/null
+++ b/examples/declarative/border-image/content/colors-round.sci
@@ -0,0 +1,7 @@
+border.left:30
+border.top:30
+border.right:30
+border.bottom:30
+horizontalTileRule:Round
+verticalTileRule:Round
+source:colors.png
diff --git a/examples/declarative/border-image/content/colors-stretch.sci b/examples/declarative/border-image/content/colors-stretch.sci
new file mode 100644
index 0000000..e4989a7
--- /dev/null
+++ b/examples/declarative/border-image/content/colors-stretch.sci
@@ -0,0 +1,5 @@
+border.left:30
+border.top:30
+border.right:30
+border.bottom:30
+source:colors.png
diff --git a/examples/declarative/border-image/content/colors.png b/examples/declarative/border-image/content/colors.png
new file mode 100644
index 0000000..dfb62f3
--- /dev/null
+++ b/examples/declarative/border-image/content/colors.png
Binary files differ
diff --git a/examples/declarative/clocks/clocks.qml b/examples/declarative/clocks/clocks.qml
new file mode 100644
index 0000000..624748a
--- /dev/null
+++ b/examples/declarative/clocks/clocks.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ width: childrenRect.width
+ height: childrenRect.height
+ color: "#646464"
+
+ Grid {
+ columns: 3
+ Clock { city: "New York"; shift: -4 }
+ Clock { city: "Mumbai"; shift: 5.5 }
+ Clock { city: "Tokyo"; shift: 9 }
+ }
+}
diff --git a/examples/declarative/clocks/content/Clock.qml b/examples/declarative/clocks/content/Clock.qml
new file mode 100644
index 0000000..0c6836f
--- /dev/null
+++ b/examples/declarative/clocks/content/Clock.qml
@@ -0,0 +1,80 @@
+import Qt 4.6
+
+Item {
+ id: clock
+ width: 200; height: 230
+
+ property alias city: cityLabel.text
+ property var hours
+ property var minutes
+ property var seconds
+ property var shift : 0
+ property bool night: false
+
+ function timeChanged() {
+ var date = new Date;
+ hours = shift ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours()
+ if ( hours < 7 || hours > 19 ) night = true; else night = false
+ minutes = shift ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes()
+ seconds = date.getUTCSeconds();
+ }
+
+ Timer {
+ interval: 100; running: true; repeat: true; triggeredOnStart: true
+ onTriggered: clock.timeChanged()
+ }
+
+ Image { id: background; source: "clock.png"; visible: clock.night == false }
+ Image { source: "clock-night.png"; visible: clock.night == true }
+
+ Image {
+ x: 92.5; y: 27
+ source: "hour.png"
+ smooth: true
+ transform: Rotation {
+ id: hourRotation
+ origin.x: 7.5; origin.y: 73; angle: 0
+ angle: SpringFollow {
+ spring: 2; damping: 0.2; modulus: 360
+ source: (clock.hours * 30) + (clock.minutes * 0.5)
+ }
+ }
+ }
+
+ Image {
+ x: 93.5; y: 17
+ source: "minute.png"
+ smooth: true
+ transform: Rotation {
+ id: minuteRotation
+ origin.x: 6.5; origin.y: 83; angle: 0
+ angle: SpringFollow {
+ spring: 2; damping: 0.2; modulus: 360
+ source: clock.minutes * 6
+ }
+ }
+ }
+
+ Image {
+ x: 97.5; y: 20
+ source: "second.png"
+ smooth: true
+ transform: Rotation {
+ id: secondRotation
+ origin.x: 2.5; origin.y: 80; angle: 0
+ angle: SpringFollow {
+ spring: 5; damping: 0.25; modulus: 360
+ source: clock.seconds * 6
+ }
+ }
+ }
+
+ Image {
+ anchors.centerIn: background; source: "center.png"
+ }
+
+ Text {
+ id: cityLabel; font.bold: true; font.pixelSize: 14; y:200; color: "white"
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+}
diff --git a/examples/declarative/clocks/content/background.png b/examples/declarative/clocks/content/background.png
new file mode 100644
index 0000000..a885950
--- /dev/null
+++ b/examples/declarative/clocks/content/background.png
Binary files differ
diff --git a/examples/declarative/clocks/content/center.png b/examples/declarative/clocks/content/center.png
new file mode 100755
index 0000000..7fbd802
--- /dev/null
+++ b/examples/declarative/clocks/content/center.png
Binary files differ
diff --git a/examples/declarative/clocks/content/clock-night.png b/examples/declarative/clocks/content/clock-night.png
new file mode 100755
index 0000000..cc7151a
--- /dev/null
+++ b/examples/declarative/clocks/content/clock-night.png
Binary files differ
diff --git a/examples/declarative/clocks/content/clock.png b/examples/declarative/clocks/content/clock.png
new file mode 100755
index 0000000..462edac
--- /dev/null
+++ b/examples/declarative/clocks/content/clock.png
Binary files differ
diff --git a/examples/declarative/clocks/content/hour.png b/examples/declarative/clocks/content/hour.png
new file mode 100755
index 0000000..f8061a1
--- /dev/null
+++ b/examples/declarative/clocks/content/hour.png
Binary files differ
diff --git a/examples/declarative/clocks/content/minute.png b/examples/declarative/clocks/content/minute.png
new file mode 100755
index 0000000..1297ec7
--- /dev/null
+++ b/examples/declarative/clocks/content/minute.png
Binary files differ
diff --git a/examples/declarative/clocks/content/second.png b/examples/declarative/clocks/content/second.png
new file mode 100755
index 0000000..4aa9fb5
--- /dev/null
+++ b/examples/declarative/clocks/content/second.png
Binary files differ
diff --git a/examples/declarative/connections/connections.qml b/examples/declarative/connections/connections.qml
new file mode 100644
index 0000000..07f71bb
--- /dev/null
+++ b/examples/declarative/connections/connections.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ id: window; color: "#646464"
+ width: 640; height: 480
+
+ function turnLeft() {
+ image.rotation -= 90
+ }
+ function turnRight() {
+ image.rotation += 90
+ }
+
+ Image {
+ id: image; source: "content/bg1.jpg"; anchors.centerIn: parent; transformOrigin: Item.Center
+ rotation: Behavior { NumberAnimation { easing: "easeOutCubic"; duration: 300 } }
+ }
+
+ Button {
+ id: leftButton; image: "content/rotate-left.png"
+ anchors { left: parent.left; bottom: parent.bottom; leftMargin: 10; bottomMargin: 10 }
+ }
+ Button {
+ id: rightButton; image: "content/rotate-right.png"
+ anchors { right: parent.right; bottom: parent.bottom; rightMargin: 10; bottomMargin: 10 }
+ }
+
+ Connection { sender: leftButton; signal: "clicked()"; script: window.turnLeft() }
+ Connection { sender: rightButton; signal: "clicked()"; script: window.turnRight() }
+}
diff --git a/examples/declarative/connections/content/Button.qml b/examples/declarative/connections/content/Button.qml
new file mode 100644
index 0000000..1d46acc
--- /dev/null
+++ b/examples/declarative/connections/content/Button.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+Item {
+ id: button
+ width: 48; height: 48
+
+ property alias image: icon.source
+ signal clicked
+
+ Image { id: icon }
+ MouseRegion { anchors.fill: icon; onClicked: button.clicked() }
+}
diff --git a/examples/declarative/connections/content/bg1.jpg b/examples/declarative/connections/content/bg1.jpg
new file mode 100644
index 0000000..dfc7cee
--- /dev/null
+++ b/examples/declarative/connections/content/bg1.jpg
Binary files differ
diff --git a/examples/declarative/connections/content/rotate-left.png b/examples/declarative/connections/content/rotate-left.png
new file mode 100644
index 0000000..c30387e
--- /dev/null
+++ b/examples/declarative/connections/content/rotate-left.png
Binary files differ
diff --git a/examples/declarative/connections/content/rotate-right.png b/examples/declarative/connections/content/rotate-right.png
new file mode 100644
index 0000000..1b05674
--- /dev/null
+++ b/examples/declarative/connections/content/rotate-right.png
Binary files differ
diff --git a/examples/declarative/dial/content/Dial.qml b/examples/declarative/dial/content/Dial.qml
new file mode 100644
index 0000000..6fd0f39
--- /dev/null
+++ b/examples/declarative/dial/content/Dial.qml
@@ -0,0 +1,37 @@
+import Qt 4.6
+
+Item {
+ id: root
+ property real value : 0
+
+ width: 210; height: 210
+
+ Image { source: "background.png" }
+
+ Image {
+ x: 93
+ y: 35
+ source: "needle_shadow.png"
+ transform: Rotation {
+ origin.x: 11; origin.y: 67
+ angle: needleRotation.angle
+ }
+ }
+ Image {
+ id: needle
+ x: 95; y: 33
+ smooth: true
+ source: "needle.png"
+ transform: Rotation {
+ id: needleRotation
+ origin.x: 7; origin.y: 65
+ angle: -130
+ angle: SpringFollow {
+ spring: 1.4
+ damping: .15
+ source: Math.min(Math.max(-130, root.value*2.6 - 130), 133)
+ }
+ }
+ }
+ Image { x: 21; y: 18; source: "overlay.png" }
+}
diff --git a/examples/declarative/dial/content/background.png b/examples/declarative/dial/content/background.png
new file mode 100644
index 0000000..75d555d
--- /dev/null
+++ b/examples/declarative/dial/content/background.png
Binary files differ
diff --git a/examples/declarative/dial/content/needle.png b/examples/declarative/dial/content/needle.png
new file mode 100644
index 0000000..2d19f75
--- /dev/null
+++ b/examples/declarative/dial/content/needle.png
Binary files differ
diff --git a/examples/declarative/dial/content/needle_shadow.png b/examples/declarative/dial/content/needle_shadow.png
new file mode 100644
index 0000000..8d8a928
--- /dev/null
+++ b/examples/declarative/dial/content/needle_shadow.png
Binary files differ
diff --git a/examples/declarative/dial/content/overlay.png b/examples/declarative/dial/content/overlay.png
new file mode 100644
index 0000000..3860a7b
--- /dev/null
+++ b/examples/declarative/dial/content/overlay.png
Binary files differ
diff --git a/examples/declarative/dial/dial.qml b/examples/declarative/dial/dial.qml
new file mode 100644
index 0000000..c7b7659
--- /dev/null
+++ b/examples/declarative/dial/dial.qml
@@ -0,0 +1,35 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ color: "#545454"
+ width: 300; height: 300
+
+ // Dial with a slider to adjust it
+ Dial { id: dial; anchors.centerIn: parent; value: slider.x *100 / (container.width - 34) }
+
+ Rectangle {
+ id: container
+ anchors.bottom: parent.bottom; anchors.bottomMargin: 10
+ anchors.left: parent.left; anchors.leftMargin: 20
+ anchors.right: parent.right; anchors.rightMargin: 20; height: 16
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "gray" }
+ GradientStop { position: 1.0; color: "white" }
+ }
+ radius: 8; opacity: 0.7; smooth: true
+ Rectangle {
+ id: slider
+ x: 1; y: 1; width: 30; height: 14
+ radius: 6; smooth: true
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#424242" }
+ GradientStop { position: 1.0; color: "black" }
+ }
+ MouseRegion {
+ anchors.fill: parent
+ drag.target: parent; drag.axis: "XAxis"; drag.minimumX: 2; drag.maximumX: container.width - 32
+ }
+ }
+ }
+}
diff --git a/examples/declarative/dynamic/dynamic.qml b/examples/declarative/dynamic/dynamic.qml
new file mode 100644
index 0000000..2831b0c
--- /dev/null
+++ b/examples/declarative/dynamic/dynamic.qml
@@ -0,0 +1,117 @@
+import Qt 4.6
+import "qml"
+
+Item {
+ id: window
+ //This is a desktop-sized example
+ width: 1024; height: 512
+ property int activeSuns: 0
+
+ // sky
+ Rectangle { id: sky
+ anchors { left: parent.left; top: parent.top; right: toolbox.right; bottom: parent.verticalCenter }
+ gradient: Gradient {
+ GradientStop { id: stopA; position: 0.0; color: "#0E1533" }
+ GradientStop { id: stopB; position: 1.0; color: "#437284" }
+ }
+ }
+
+ // stars (when there's no sun)
+ Particles { id: stars
+ x: 0; y: 0; width: parent.width; height: parent.height/2
+ source: "images/star.png"; angleDeviation: 360; velocity: 0
+ velocityDeviation: 0; count: parent.width / 10; fadeInDuration: 2800
+ opacity: 1
+ }
+
+ // ground, which has a z such that the sun can set behind it
+ Rectangle { id: ground
+ z: 2
+ anchors { left: parent.left; top: parent.verticalCenter; right: toolbox.right; bottom: parent.bottom }
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "ForestGreen" }
+ GradientStop { position: 1.0; color: "DarkGreen" }
+ }
+ }
+
+ //Day state, for when you place a sun
+ states: State { name: "Day"; when: window.activeSuns > 0
+ PropertyChanges { target: stopA; color: "DeepSkyBlue"}
+ PropertyChanges { target: stopB; color: "SkyBlue"}
+ PropertyChanges { target: stars; opacity: 0 }
+ }
+
+ transitions: Transition {
+ PropertyAnimation { duration: 3000 }
+ ColorAnimation { duration: 3000 }
+ }
+
+ SystemPalette { id: activePalette }
+
+ // toolbox
+ Rectangle {
+ id: toolbox
+ z: 3 //Above ground
+ color: activePalette.window;
+ width: 480
+ anchors { right: parent.right; top:parent.top; bottom: parent.bottom }
+ Rectangle { //Not a child of any positioner
+ color: "white"; border.color: "black";
+ width: toolRow.width + 4
+ height: toolRow.height + 4
+ x: toolboxPositioner.x + toolRow.x - 2
+ y: toolboxPositioner.y + toolRow.y - 2
+ }
+ Column{
+ id: toolboxPositioner
+ anchors.centerIn: parent
+ spacing: 8
+ Text{ text: "Drag an item into the scene." }
+ Row{ id: toolRow
+ spacing: 8;
+ PaletteItem{
+ anchors.verticalCenter: parent.verticalCenter
+ file: "Sun.qml";
+ image: "../images/sun.png"
+ }
+ PaletteItem{
+ file: "GenericItem.qml"
+ image: "../images/moon.png"
+ }
+ PaletteItem{
+ anchors.verticalCenter: parent.verticalCenter
+ file: "PerspectiveItem.qml"
+ image: "../images/tree_s.png"
+ }
+ PaletteItem{
+ anchors.verticalCenter: parent.verticalCenter
+ file: "PerspectiveItem.qml"
+ image: "../images/rabbit_brown.png"
+ }
+ PaletteItem{
+ anchors.verticalCenter: parent.verticalCenter
+ file: "PerspectiveItem.qml"
+ image: "../images/rabbit_bw.png"
+ }
+ }
+ Text{ text: "Active Suns: " + activeSuns }
+ Rectangle { width: 440; height: 1; color: "black" }
+ Text{ text: "Arbitrary QML: " }
+ TextEdit {
+ id: qmlText
+ width: 460
+ height: 220
+ readOnly: false
+ focusOnPress: true
+ font.pixelSize: 16
+
+ text: "import Qt 4.6\nImage { id: smile;\n x: 500*Math.random();\n y: 200*Math.random(); \n source: 'images/face-smile.png';\n opacity: NumberAnimation{ \n to: 0; duration: 1500;\n }\n Component.onCompleted: smile.destroy(1500);\n}"
+ }
+ Button {
+ text: "Create"
+ onClicked: createQmlObject(qmlText.text, window, 'CustomObject');
+ }
+ }
+ }
+
+}
diff --git a/examples/declarative/dynamic/images/NOTE b/examples/declarative/dynamic/images/NOTE
new file mode 100644
index 0000000..fcd87f9
--- /dev/null
+++ b/examples/declarative/dynamic/images/NOTE
@@ -0,0 +1 @@
+Images (except star.png) are from the KDE project.
diff --git a/examples/declarative/dynamic/images/face-smile.png b/examples/declarative/dynamic/images/face-smile.png
new file mode 100644
index 0000000..3d66d72
--- /dev/null
+++ b/examples/declarative/dynamic/images/face-smile.png
Binary files differ
diff --git a/examples/declarative/dynamic/images/moon.png b/examples/declarative/dynamic/images/moon.png
new file mode 100644
index 0000000..1c0d606
--- /dev/null
+++ b/examples/declarative/dynamic/images/moon.png
Binary files differ
diff --git a/examples/declarative/dynamic/images/rabbit_brown.png b/examples/declarative/dynamic/images/rabbit_brown.png
new file mode 100644
index 0000000..ebfdeed
--- /dev/null
+++ b/examples/declarative/dynamic/images/rabbit_brown.png
Binary files differ
diff --git a/examples/declarative/dynamic/images/rabbit_bw.png b/examples/declarative/dynamic/images/rabbit_bw.png
new file mode 100644
index 0000000..7bff9b9
--- /dev/null
+++ b/examples/declarative/dynamic/images/rabbit_bw.png
Binary files differ
diff --git a/examples/declarative/dynamic/images/star.png b/examples/declarative/dynamic/images/star.png
new file mode 100644
index 0000000..27ef924
--- /dev/null
+++ b/examples/declarative/dynamic/images/star.png
Binary files differ
diff --git a/examples/declarative/dynamic/images/sun.png b/examples/declarative/dynamic/images/sun.png
new file mode 100644
index 0000000..7713ca5
--- /dev/null
+++ b/examples/declarative/dynamic/images/sun.png
Binary files differ
diff --git a/examples/declarative/dynamic/images/tree_s.png b/examples/declarative/dynamic/images/tree_s.png
new file mode 100644
index 0000000..6eac35a
--- /dev/null
+++ b/examples/declarative/dynamic/images/tree_s.png
Binary files differ
diff --git a/examples/declarative/dynamic/qml/Button.qml b/examples/declarative/dynamic/qml/Button.qml
new file mode 100644
index 0000000..cf2ffa7
--- /dev/null
+++ b/examples/declarative/dynamic/qml/Button.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+
+ property var text
+ signal clicked
+
+ SystemPalette { id: activePalette }
+ height: text.height + 10
+ width: text.width + 20
+ border.width: 1
+ radius: 4; smooth: true
+ gradient: Gradient {
+ GradientStop { position: 0.0;
+ color: if(!mr.pressed){activePalette.light;}else{activePalette.button;}
+ }
+ GradientStop { position: 1.0;
+ color: if(!mr.pressed){activePalette.button;}else{activePalette.dark;}
+ }
+ }
+ MouseRegion { id:mr; anchors.fill: parent; onClicked: container.clicked() }
+ Text { id: text; anchors.centerIn:parent; font.pointSize: 10; text: parent.text; color: activePalette.buttonText }
+}
diff --git a/examples/declarative/dynamic/qml/GenericItem.qml b/examples/declarative/dynamic/qml/GenericItem.qml
new file mode 100644
index 0000000..10e3dba
--- /dev/null
+++ b/examples/declarative/dynamic/qml/GenericItem.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+Item{
+ property bool created: false
+ property string image
+ width: imageItem.width
+ height: imageItem.height
+ z: 2
+ Image{
+ id: imageItem
+ source: image;
+ }
+}
diff --git a/examples/declarative/dynamic/qml/PaletteItem.qml b/examples/declarative/dynamic/qml/PaletteItem.qml
new file mode 100644
index 0000000..bb6036d
--- /dev/null
+++ b/examples/declarative/dynamic/qml/PaletteItem.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+GenericItem {
+ id: itemButton
+ property string file
+ Script { source: "itemCreation.js" }
+ MouseRegion {
+ anchors.fill: parent;
+ onPressed: startDrag(mouse);
+ onPositionChanged: moveDrag(mouse);
+ onReleased: endDrag(mouse);
+ }
+}
diff --git a/examples/declarative/dynamic/qml/PerspectiveItem.qml b/examples/declarative/dynamic/qml/PerspectiveItem.qml
new file mode 100644
index 0000000..728c3a5
--- /dev/null
+++ b/examples/declarative/dynamic/qml/PerspectiveItem.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+
+Image {
+ id: tree
+ property bool created: false
+ property double scaleFactor: Math.max((y+height-250)*0.01, 0.3)
+ property double scaledBottom: y + (height+height*scaleFactor)/2
+ property bool onLand: scaledBottom > window.height/2
+ opacity: onLand ? 1 : 0.25
+ onCreatedChanged: if (created && !onLand) { tree.destroy() } else { z = scaledBottom }
+ scale: scaleFactor
+ transformOrigin: "Center"
+ source: image; smooth: true
+ onYChanged: z = scaledBottom
+}
diff --git a/examples/declarative/dynamic/qml/Sun.qml b/examples/declarative/dynamic/qml/Sun.qml
new file mode 100644
index 0000000..796a370
--- /dev/null
+++ b/examples/declarative/dynamic/qml/Sun.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+Image {
+ id: sun
+ property bool created: false
+ property string image: "../images/sun.png"
+ onCreatedChanged: if(created){window.activeSuns++;}else{window.activeSuns--;}
+
+ source: image;
+ z: 1
+
+ //x and y get set when instantiated
+ //head offscreen
+ y: NumberAnimation {
+ to: parent.height;
+ duration: 10000;
+ running: created
+ }
+
+ states: State {
+ name: "OffScreen"; when: created && y > window.height / 2;//Below the ground
+ StateChangeScript { script: { sun.created = false; sun.destroy() } }
+ }
+}
diff --git a/examples/declarative/dynamic/qml/itemCreation.js b/examples/declarative/dynamic/qml/itemCreation.js
new file mode 100644
index 0000000..ccc03aa
--- /dev/null
+++ b/examples/declarative/dynamic/qml/itemCreation.js
@@ -0,0 +1,82 @@
+var itemComponent = null;
+var draggedItem = null;
+var startingMouse;
+var startingZ;
+//Until QT-2385 is resolved we need to convert to scene coordinates manually
+var xOffset;
+var yOffset;
+function setSceneOffset()
+{
+ xOffset = 0;
+ yOffset = 0;
+ var p = itemButton;
+ while(p != window){
+ xOffset += p.x;
+ yOffset += p.y;
+ p = p.parent;
+ }
+}
+
+function startDrag(mouse)
+{
+ setSceneOffset();
+ startingMouse = { x: mouse.x, y: mouse.y }
+ loadComponent();
+}
+
+//Creation is split into two functions due to an asyncronous wait while
+//possible external files are loaded.
+
+function loadComponent() {
+ if (itemComponent != null) //Already loaded the component
+ createItem();
+
+ itemComponent = createComponent(itemButton.file);
+ //print(itemButton.file)
+ if(itemComponent.isLoading){
+ component.statusChanged.connect(finishCreation);
+ }else{//Depending on the content, it can be ready or error immediately
+ createItem();
+ }
+}
+
+function createItem() {
+ if (itemComponent.isReady && draggedItem == null) {
+ draggedItem = itemComponent.createObject();
+ draggedItem.parent = window;
+ draggedItem.image = itemButton.image;
+ draggedItem.x = xOffset;
+ draggedItem.y = yOffset;
+ startingZ = draggedItem.z;
+ draggedItem.z = 4;//On top
+ } else if (itemComponent.isError) {
+ draggedItem = null;
+ print("error creating component");
+ print(component.errorsString());
+ }
+}
+
+function moveDrag(mouse)
+{
+ if(draggedItem == null)
+ return;
+
+ draggedItem.x = mouse.x + xOffset - startingMouse.x;
+ draggedItem.y = mouse.y + yOffset - startingMouse.y;
+}
+
+function endDrag(mouse)
+{
+ if(draggedItem == null)
+ return;
+
+ if(draggedItem.x + draggedItem.width > toolbox.x){ //Don't drop it in the toolbox
+ draggedItem.destroy();
+ draggedItem = null;
+ }else{
+ draggedItem.z = startingZ;
+ draggedItem.created = true;
+ draggedItem = null;
+ }
+}
+
diff --git a/examples/declarative/effects/effects.qml b/examples/declarative/effects/effects.qml
new file mode 100644
index 0000000..51658ff
--- /dev/null
+++ b/examples/declarative/effects/effects.qml
@@ -0,0 +1,60 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 400
+ height: 200
+
+ Image {
+ id: blur
+ x: 5
+ source: "pic.png"
+
+ effect: Blur {
+ blurRadius: NumberAnimation {
+ id: blurEffect
+ running: false
+ from: 0; to: 10
+ duration: 1000
+ repeat: true
+ }
+ }
+
+ MouseRegion { anchors.fill: parent; onClicked: blurEffect.running = !blurEffect.running }
+ }
+
+ Text { text: "Blur"; anchors.top: blur.bottom; anchors.horizontalCenter: blur.horizontalCenter }
+
+ Image {
+ id: dropShadow
+ source: "pic.png"
+ x: 135
+
+ effect: DropShadow {
+ blurRadius: 3
+ offset.x: 3
+ offset.y: NumberAnimation { id: dropShadowEffect; from: 0; to: 10; duration: 1000; running: false; repeat: true; }
+ }
+
+ MouseRegion { anchors.fill: parent; onClicked: dropShadowEffect.running = !dropShadowEffect.running }
+ }
+
+ Image {
+ id: colorize
+ source: "pic.png"
+ x: 265
+
+ effect: Colorize { color: "blue" }
+ }
+
+ Text { text: "Colorize"; anchors.top: colorize.bottom; anchors.horizontalCenter: colorize.horizontalCenter }
+
+ Text { text: "Drop Shadow"; anchors.top: dropShadow.bottom; anchors.horizontalCenter: dropShadow.horizontalCenter }
+
+ Text {
+ y: 155; anchors.horizontalCenter: parent.horizontalCenter
+ text: "Clicking Blur or Drop Shadow will \ntoggle animation."
+ color: "black"
+ }
+
+}
diff --git a/examples/declarative/effects/pic.png b/examples/declarative/effects/pic.png
new file mode 100644
index 0000000..051e738
--- /dev/null
+++ b/examples/declarative/effects/pic.png
Binary files differ
diff --git a/examples/declarative/extending/adding/adding.pro b/examples/declarative/extending/adding/adding.pro
new file mode 100644
index 0000000..c02a35f
--- /dev/null
+++ b/examples/declarative/extending/adding/adding.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = adding
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp
+HEADERS += person.h
+RESOURCES += adding.qrc
diff --git a/examples/declarative/extending/adding/adding.qrc b/examples/declarative/extending/adding/adding.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/adding/adding.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/adding/example.qml b/examples/declarative/extending/adding/example.qml
new file mode 100644
index 0000000..c608f94
--- /dev/null
+++ b/examples/declarative/extending/adding/example.qml
@@ -0,0 +1,8 @@
+import People 1.0
+
+// ![0]
+Person {
+ name: "Bob Jones"
+ shoeSize: 12
+}
+// ![0]
diff --git a/examples/declarative/extending/adding/main.cpp b/examples/declarative/extending/adding/main.cpp
new file mode 100644
index 0000000..82e4946
--- /dev/null
+++ b/examples/declarative/extending/adding/main.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ Person *person = qobject_cast<Person *>(component.create());
+ if (person) {
+ qWarning() << "The person's name is" << person->name();
+ qWarning() << "They wear a" << person->shoeSize() << "sized shoe";
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return 0;
+}
diff --git a/examples/declarative/extending/adding/person.cpp b/examples/declarative/extending/adding/person.cpp
new file mode 100644
index 0000000..832bcdc
--- /dev/null
+++ b/examples/declarative/extending/adding/person.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+// ![0]
+Person::Person(QObject *parent)
+: QObject(parent), m_shoeSize(0)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+int Person::shoeSize() const
+{
+ return m_shoeSize;
+}
+
+void Person::setShoeSize(int s)
+{
+ m_shoeSize = s;
+}
+
+QML_DEFINE_TYPE(People, 1,0, Person, Person);
+// ![0]
diff --git a/examples/declarative/extending/adding/person.h b/examples/declarative/extending/adding/person.h
new file mode 100644
index 0000000..1a01586
--- /dev/null
+++ b/examples/declarative/extending/adding/person.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+// ![0]
+#include <qml.h>
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ int shoeSize() const;
+ void setShoeSize(int);
+private:
+ QString m_name;
+ int m_shoeSize;
+};
+QML_DECLARE_TYPE(Person);
+// ![0]
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/attached/attached.pro b/examples/declarative/extending/attached/attached.pro
new file mode 100644
index 0000000..b0f3fea
--- /dev/null
+++ b/examples/declarative/extending/attached/attached.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = attached
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp
+HEADERS += person.h \
+ birthdayparty.h
+RESOURCES += attached.qrc
diff --git a/examples/declarative/extending/attached/attached.qrc b/examples/declarative/extending/attached/attached.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/attached/attached.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/attached/birthdayparty.cpp b/examples/declarative/extending/attached/birthdayparty.cpp
new file mode 100644
index 0000000..c1f0fe8
--- /dev/null
+++ b/examples/declarative/extending/attached/birthdayparty.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayPartyAttached::BirthdayPartyAttached(QObject *object)
+: QObject(object)
+{
+}
+
+QDate BirthdayPartyAttached::rsvp() const
+{
+ return m_rsvp;
+}
+
+void BirthdayPartyAttached::setRsvp(const QDate &d)
+{
+ m_rsvp = d;
+}
+
+QML_DEFINE_NOCREATE_TYPE(BirthdayPartyAttached);
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ m_celebrant = c;
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+
+BirthdayPartyAttached *BirthdayParty::qmlAttachedProperties(QObject *object)
+{
+ return new BirthdayPartyAttached(object);
+}
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/attached/birthdayparty.h b/examples/declarative/extending/attached/birthdayparty.h
new file mode 100644
index 0000000..ffebe5f
--- /dev/null
+++ b/examples/declarative/extending/attached/birthdayparty.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <QDate>
+#include <qml.h>
+#include "person.h"
+
+class BirthdayPartyAttached : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp)
+public:
+ BirthdayPartyAttached(QObject *object);
+
+ QDate rsvp() const;
+ void setRsvp(const QDate &);
+
+private:
+ QDate m_rsvp;
+};
+QML_DECLARE_TYPE(BirthdayPartyAttached)
+
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant)
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+Q_CLASSINFO("DefaultProperty", "guests")
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+ static BirthdayPartyAttached *qmlAttachedProperties(QObject *);
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+
+QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(BirthdayParty)
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/attached/example.qml b/examples/declarative/extending/attached/example.qml
new file mode 100644
index 0000000..952eb93
--- /dev/null
+++ b/examples/declarative/extending/attached/example.qml
@@ -0,0 +1,29 @@
+import People 1.0
+
+BirthdayParty {
+ celebrant: Boy {
+ name: "Bob Jones"
+ shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
+ }
+
+ // ![1]
+ Boy {
+ name: "Joan Hodges"
+ BirthdayParty.rsvp: "2009-07-06"
+ shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
+ }
+ // ![1]
+ Boy {
+ name: "Jack Smith"
+ shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 }
+ }
+ Girl {
+ name: "Anne Brown"
+ BirthdayParty.rsvp: "2009-07-01"
+ shoe.size: 7
+ shoe.color: "red"
+ shoe.brand: "Marc Jacobs"
+ shoe.price: 699.99
+ }
+}
+
diff --git a/examples/declarative/extending/attached/main.cpp b/examples/declarative/extending/attached/main.cpp
new file mode 100644
index 0000000..d99bfd3
--- /dev/null
+++ b/examples/declarative/extending/attached/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+
+ if (qobject_cast<Boy *>(party->celebrant()))
+ qWarning() << "He is inviting:";
+ else
+ qWarning() << "She is inviting:";
+
+ for (int ii = 0; ii < party->guests()->count(); ++ii) {
+ Person *guest = party->guests()->at(ii);
+
+ QDate rsvpDate;
+ QObject *attached =
+ qmlAttachedPropertiesObject<BirthdayParty>(guest, false);
+ if (attached)
+ rsvpDate = attached->property("rsvp").toDate();
+
+ if (rsvpDate.isNull())
+ qWarning() << " " << guest->name() << "RSVP date: Hasn't RSVP'd";
+ else
+ qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString());
+ }
+
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return 0;
+}
diff --git a/examples/declarative/extending/attached/person.cpp b/examples/declarative/extending/attached/person.cpp
new file mode 100644
index 0000000..8105ee7
--- /dev/null
+++ b/examples/declarative/extending/attached/person.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+ShoeDescription::ShoeDescription(QObject *parent)
+: QObject(parent), m_size(0), m_price(0)
+{
+}
+
+int ShoeDescription::size() const
+{
+ return m_size;
+}
+
+void ShoeDescription::setSize(int s)
+{
+ m_size = s;
+}
+
+QColor ShoeDescription::color() const
+{
+ return m_color;
+}
+
+void ShoeDescription::setColor(const QColor &c)
+{
+ m_color = c;
+}
+
+QString ShoeDescription::brand() const
+{
+ return m_brand;
+}
+
+void ShoeDescription::setBrand(const QString &b)
+{
+ m_brand = b;
+}
+
+qreal ShoeDescription::price() const
+{
+ return m_price;
+}
+
+void ShoeDescription::setPrice(qreal p)
+{
+ m_price = p;
+}
+QML_DEFINE_NOCREATE_TYPE(ShoeDescription);
+
+Person::Person(QObject *parent)
+: QObject(parent)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+ShoeDescription *Person::shoe()
+{
+ return &m_shoe;
+}
+
+QML_DEFINE_NOCREATE_TYPE(Person);
+
+Boy::Boy(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Boy, Boy);
+
+Girl::Girl(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Girl, Girl);
diff --git a/examples/declarative/extending/attached/person.h b/examples/declarative/extending/attached/person.h
new file mode 100644
index 0000000..c5b7727
--- /dev/null
+++ b/examples/declarative/extending/attached/person.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <QColor>
+#include <qml.h>
+
+class ShoeDescription : public QObject {
+Q_OBJECT
+Q_PROPERTY(int size READ size WRITE setSize)
+Q_PROPERTY(QColor color READ color WRITE setColor)
+Q_PROPERTY(QString brand READ brand WRITE setBrand)
+Q_PROPERTY(qreal price READ price WRITE setPrice)
+public:
+ ShoeDescription(QObject *parent = 0);
+
+ int size() const;
+ void setSize(int);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QString brand() const;
+ void setBrand(const QString &);
+
+ qreal price() const;
+ void setPrice(qreal);
+private:
+ int m_size;
+ QColor m_color;
+ QString m_brand;
+ qreal m_price;
+};
+QML_DECLARE_TYPE(ShoeDescription);
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+Q_PROPERTY(ShoeDescription *shoe READ shoe);
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ ShoeDescription *shoe();
+private:
+ QString m_name;
+ ShoeDescription m_shoe;
+};
+QML_DECLARE_TYPE(Person);
+
+class Boy : public Person {
+Q_OBJECT
+public:
+ Boy(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Boy);
+
+class Girl : public Person {
+Q_OBJECT
+public:
+ Girl(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Girl);
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/binding/binding.pro b/examples/declarative/extending/binding/binding.pro
new file mode 100644
index 0000000..8298565
--- /dev/null
+++ b/examples/declarative/extending/binding/binding.pro
@@ -0,0 +1,15 @@
+TEMPLATE = app
+TARGET = binding
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp \
+ happybirthday.cpp
+HEADERS += person.h \
+ birthdayparty.h \
+ happybirthday.h
+RESOURCES += binding.qrc
diff --git a/examples/declarative/extending/binding/binding.qrc b/examples/declarative/extending/binding/binding.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/binding/binding.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/binding/birthdayparty.cpp b/examples/declarative/extending/binding/birthdayparty.cpp
new file mode 100644
index 0000000..13d6bc8
--- /dev/null
+++ b/examples/declarative/extending/binding/birthdayparty.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayPartyAttached::BirthdayPartyAttached(QObject *object)
+: QObject(object)
+{
+}
+
+QDate BirthdayPartyAttached::rsvp() const
+{
+ return m_rsvp;
+}
+
+void BirthdayPartyAttached::setRsvp(const QDate &d)
+{
+ if (d != m_rsvp) {
+ m_rsvp = d;
+ emit rsvpChanged();
+ }
+}
+
+QML_DEFINE_NOCREATE_TYPE(BirthdayPartyAttached);
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ if (c == m_celebrant) return;
+ m_celebrant = c;
+ emit celebrantChanged();
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+
+void BirthdayParty::startParty()
+{
+ QTime time = QTime::currentTime();
+ emit partyStarted(time);
+}
+
+QString BirthdayParty::speaker() const
+{
+ return QString();
+}
+
+void BirthdayParty::setSpeaker(const QString &speak)
+{
+ qWarning() << qPrintable(speak);
+}
+
+BirthdayPartyAttached *BirthdayParty::qmlAttachedProperties(QObject *object)
+{
+ return new BirthdayPartyAttached(object);
+}
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/binding/birthdayparty.h b/examples/declarative/extending/binding/birthdayparty.h
new file mode 100644
index 0000000..7fde54e
--- /dev/null
+++ b/examples/declarative/extending/binding/birthdayparty.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <QDate>
+#include <QDebug>
+#include <qml.h>
+#include "person.h"
+
+class BirthdayPartyAttached : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp NOTIFY rsvpChanged)
+public:
+ BirthdayPartyAttached(QObject *object);
+
+ QDate rsvp() const;
+ void setRsvp(const QDate &);
+
+signals:
+ void rsvpChanged();
+
+private:
+ QDate m_rsvp;
+};
+QML_DECLARE_TYPE(BirthdayPartyAttached)
+
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+// ![0]
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant NOTIFY celebrantChanged)
+// ![0]
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+Q_PROPERTY(QString speaker READ speaker WRITE setSpeaker)
+Q_CLASSINFO("DefaultProperty", "guests")
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+ QString speaker() const;
+ void setSpeaker(const QString &);
+
+ static BirthdayPartyAttached *qmlAttachedProperties(QObject *);
+
+ void startParty();
+signals:
+ void partyStarted(const QTime &time);
+ void celebrantChanged();
+
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+
+QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(BirthdayParty)
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/binding/example.qml b/examples/declarative/extending/binding/example.qml
new file mode 100644
index 0000000..b66bc86
--- /dev/null
+++ b/examples/declarative/extending/binding/example.qml
@@ -0,0 +1,37 @@
+import People 1.0
+
+// ![0]
+BirthdayParty {
+ id: theParty
+
+ speaker: HappyBirthday { name: theParty.celebrant.name }
+
+ celebrant: Boy {
+ name: "Bob Jones"
+ shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
+ }
+// ![0]
+ onPartyStarted: console.log("This party started rockin' at " + time);
+
+
+ Boy {
+ name: "Joan Hodges"
+ BirthdayParty.rsvp: "2009-07-06"
+ shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
+ }
+ Boy {
+ name: "Jack Smith"
+ shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 }
+ }
+ Girl {
+ name: "Anne Brown"
+ BirthdayParty.rsvp: "2009-07-01"
+ shoe.size: 7
+ shoe.color: "red"
+ shoe.brand: "Marc Jacobs"
+ shoe.price: 699.99
+ }
+
+// ![1]
+}
+// ![1]
diff --git a/examples/declarative/extending/binding/happybirthday.cpp b/examples/declarative/extending/binding/happybirthday.cpp
new file mode 100644
index 0000000..9ce5a3d
--- /dev/null
+++ b/examples/declarative/extending/binding/happybirthday.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "happybirthday.h"
+#include <QTimer>
+
+HappyBirthday::HappyBirthday(QObject *parent)
+: QObject(parent), m_line(-1)
+{
+ setName(QString());
+ QTimer *timer = new QTimer(this);
+ QObject::connect(timer, SIGNAL(timeout()), this, SLOT(advance()));
+ timer->start(1000);
+}
+
+void HappyBirthday::setTarget(const QmlMetaProperty &p)
+{
+ m_target = p;
+}
+
+QString HappyBirthday::name() const
+{
+ return m_name;
+}
+
+void HappyBirthday::setName(const QString &name)
+{
+ if (m_name == name)
+ return;
+
+ m_name = name;
+
+ m_lyrics.clear();
+ m_lyrics << "Happy birthday to you,";
+ m_lyrics << "Happy birthday to you,";
+ m_lyrics << "Happy birthday dear " + m_name + ",";
+ m_lyrics << "Happy birthday to you!";
+ m_lyrics << "";
+
+ emit nameChanged();
+}
+
+void HappyBirthday::advance()
+{
+ m_line = (m_line + 1) % m_lyrics.count();
+
+ m_target.write(m_lyrics.at(m_line));
+}
+
+QML_DEFINE_TYPE(People, 1,0, HappyBirthday, HappyBirthday);
diff --git a/examples/declarative/extending/binding/happybirthday.h b/examples/declarative/extending/binding/happybirthday.h
new file mode 100644
index 0000000..5a492c7
--- /dev/null
+++ b/examples/declarative/extending/binding/happybirthday.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef HAPPYBIRTHDAY_H
+#define HAPPYBIRTHDAY_H
+
+#include <QmlPropertyValueSource>
+#include <QmlMetaProperty>
+#include <qml.h>
+
+#include <QStringList>
+
+class HappyBirthday : public QObject, public QmlPropertyValueSource
+{
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+public:
+ HappyBirthday(QObject *parent = 0);
+
+ virtual void setTarget(const QmlMetaProperty &);
+
+ QString name() const;
+ void setName(const QString &);
+
+private slots:
+ void advance();
+
+signals:
+ void nameChanged();
+private:
+ int m_line;
+ QStringList m_lyrics;
+ QmlMetaProperty m_target;
+ QString m_name;
+};
+QML_DECLARE_TYPE(HappyBirthday);
+
+#endif // HAPPYBIRTHDAY_H
+
diff --git a/examples/declarative/extending/binding/main.cpp b/examples/declarative/extending/binding/main.cpp
new file mode 100644
index 0000000..c4090c4
--- /dev/null
+++ b/examples/declarative/extending/binding/main.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+
+ if (qobject_cast<Boy *>(party->celebrant()))
+ qWarning() << "He is inviting:";
+ else
+ qWarning() << "She is inviting:";
+
+ for (int ii = 0; ii < party->guests()->count(); ++ii) {
+ Person *guest = party->guests()->at(ii);
+
+ QDate rsvpDate;
+ QObject *attached =
+ qmlAttachedPropertiesObject<BirthdayParty>(guest, false);
+ if (attached)
+ rsvpDate = attached->property("rsvp").toDate();
+
+ if (rsvpDate.isNull())
+ qWarning() << " " << guest->name() << "RSVP date: Hasn't RSVP'd";
+ else
+ qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString());
+ }
+
+ party->startParty();
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return app.exec();
+}
diff --git a/examples/declarative/extending/binding/person.cpp b/examples/declarative/extending/binding/person.cpp
new file mode 100644
index 0000000..6ad62e9
--- /dev/null
+++ b/examples/declarative/extending/binding/person.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+ShoeDescription::ShoeDescription(QObject *parent)
+: QObject(parent), m_size(0), m_price(0)
+{
+}
+
+int ShoeDescription::size() const
+{
+ return m_size;
+}
+
+void ShoeDescription::setSize(int s)
+{
+ if (m_size == s)
+ return;
+
+ m_size = s;
+ emit shoeChanged();
+}
+
+QColor ShoeDescription::color() const
+{
+ return m_color;
+}
+
+void ShoeDescription::setColor(const QColor &c)
+{
+ if (m_color == c)
+ return;
+
+ m_color = c;
+ emit shoeChanged();
+}
+
+QString ShoeDescription::brand() const
+{
+ return m_brand;
+}
+
+void ShoeDescription::setBrand(const QString &b)
+{
+ if (m_brand == b)
+ return;
+
+ m_brand = b;
+ emit shoeChanged();
+}
+
+qreal ShoeDescription::price() const
+{
+ return m_price;
+}
+
+void ShoeDescription::setPrice(qreal p)
+{
+ if (m_price == p)
+ return;
+
+ m_price = p;
+ emit shoeChanged();
+}
+QML_DEFINE_NOCREATE_TYPE(ShoeDescription);
+
+Person::Person(QObject *parent)
+: QObject(parent)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ if (m_name == n)
+ return;
+
+ m_name = n;
+ emit nameChanged();
+}
+
+ShoeDescription *Person::shoe()
+{
+ return &m_shoe;
+}
+
+QML_DEFINE_NOCREATE_TYPE(Person);
+
+Boy::Boy(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Boy, Boy);
+
+Girl::Girl(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Girl, Girl);
diff --git a/examples/declarative/extending/binding/person.h b/examples/declarative/extending/binding/person.h
new file mode 100644
index 0000000..ad77d69
--- /dev/null
+++ b/examples/declarative/extending/binding/person.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <QColor>
+#include <qml.h>
+
+class ShoeDescription : public QObject {
+Q_OBJECT
+Q_PROPERTY(int size READ size WRITE setSize NOTIFY shoeChanged)
+Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY shoeChanged)
+Q_PROPERTY(QString brand READ brand WRITE setBrand NOTIFY shoeChanged)
+Q_PROPERTY(qreal price READ price WRITE setPrice NOTIFY shoeChanged)
+public:
+ ShoeDescription(QObject *parent = 0);
+
+ int size() const;
+ void setSize(int);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QString brand() const;
+ void setBrand(const QString &);
+
+ qreal price() const;
+ void setPrice(qreal);
+signals:
+ void shoeChanged();
+
+private:
+ int m_size;
+ QColor m_color;
+ QString m_brand;
+ qreal m_price;
+};
+QML_DECLARE_TYPE(ShoeDescription);
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+// ![0]
+Q_PROPERTY(ShoeDescription *shoe READ shoe CONSTANT);
+// ![0]
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ ShoeDescription *shoe();
+signals:
+ void nameChanged();
+
+private:
+ QString m_name;
+ ShoeDescription m_shoe;
+};
+QML_DECLARE_TYPE(Person);
+
+class Boy : public Person {
+Q_OBJECT
+public:
+ Boy(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Boy);
+
+class Girl : public Person {
+Q_OBJECT
+public:
+ Girl(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Girl);
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/coercion/birthdayparty.cpp b/examples/declarative/extending/coercion/birthdayparty.cpp
new file mode 100644
index 0000000..f3e0846
--- /dev/null
+++ b/examples/declarative/extending/coercion/birthdayparty.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ m_celebrant = c;
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/coercion/birthdayparty.h b/examples/declarative/extending/coercion/birthdayparty.h
new file mode 100644
index 0000000..810cee3
--- /dev/null
+++ b/examples/declarative/extending/coercion/birthdayparty.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <qml.h>
+#include "person.h"
+
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+// ![0]
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant)
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+// ![0]
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+QML_DECLARE_TYPE(BirthdayParty);
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/coercion/coercion.pro b/examples/declarative/extending/coercion/coercion.pro
new file mode 100644
index 0000000..136b210
--- /dev/null
+++ b/examples/declarative/extending/coercion/coercion.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = coercion
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp
+HEADERS += person.h \
+ birthdayparty.h
+RESOURCES += coercion.qrc
diff --git a/examples/declarative/extending/coercion/coercion.qrc b/examples/declarative/extending/coercion/coercion.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/coercion/coercion.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/coercion/example.qml b/examples/declarative/extending/coercion/example.qml
new file mode 100644
index 0000000..64d26b0
--- /dev/null
+++ b/examples/declarative/extending/coercion/example.qml
@@ -0,0 +1,15 @@
+import People 1.0
+
+// ![0]
+BirthdayParty {
+ celebrant: Boy {
+ name: "Bob Jones"
+ shoeSize: 12
+ }
+ guests: [
+ Boy { name: "Joan Hodges" },
+ Boy { name: "Jack Smith" },
+ Girl { name: "Anne Brown" }
+ ]
+}
+// ![0]
diff --git a/examples/declarative/extending/coercion/main.cpp b/examples/declarative/extending/coercion/main.cpp
new file mode 100644
index 0000000..1ad6d26
--- /dev/null
+++ b/examples/declarative/extending/coercion/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+
+ if (qobject_cast<Boy *>(party->celebrant()))
+ qWarning() << "He is inviting:";
+ else
+ qWarning() << "She is inviting:";
+ for (int ii = 0; ii < party->guests()->count(); ++ii)
+ qWarning() << " " << party->guests()->at(ii)->name();
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return 0;
+}
diff --git a/examples/declarative/extending/coercion/person.cpp b/examples/declarative/extending/coercion/person.cpp
new file mode 100644
index 0000000..a897d8d
--- /dev/null
+++ b/examples/declarative/extending/coercion/person.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+Person::Person(QObject *parent)
+: QObject(parent), m_shoeSize(0)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+int Person::shoeSize() const
+{
+ return m_shoeSize;
+}
+
+void Person::setShoeSize(int s)
+{
+ m_shoeSize = s;
+}
+
+// ![0]
+QML_DEFINE_NOCREATE_TYPE(Person);
+// ![0]
+
+// ![1]
+Boy::Boy(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Boy, Boy);
+
+Girl::Girl(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Girl, Girl);
+// ![1]
diff --git a/examples/declarative/extending/coercion/person.h b/examples/declarative/extending/coercion/person.h
new file mode 100644
index 0000000..7cfd3d6
--- /dev/null
+++ b/examples/declarative/extending/coercion/person.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <qml.h>
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ int shoeSize() const;
+ void setShoeSize(int);
+private:
+ QString m_name;
+ int m_shoeSize;
+};
+QML_DECLARE_TYPE(Person);
+
+// ![0]
+class Boy : public Person {
+Q_OBJECT
+public:
+ Boy(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Boy);
+
+class Girl : public Person {
+Q_OBJECT
+public:
+ Girl(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Girl);
+// ![0]
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/default/birthdayparty.cpp b/examples/declarative/extending/default/birthdayparty.cpp
new file mode 100644
index 0000000..f3e0846
--- /dev/null
+++ b/examples/declarative/extending/default/birthdayparty.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ m_celebrant = c;
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/default/birthdayparty.h b/examples/declarative/extending/default/birthdayparty.h
new file mode 100644
index 0000000..cafe4c7
--- /dev/null
+++ b/examples/declarative/extending/default/birthdayparty.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <qml.h>
+#include "person.h"
+
+// ![0]
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant)
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+Q_CLASSINFO("DefaultProperty", "guests")
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+// ![0]
+QML_DECLARE_TYPE(BirthdayParty);
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/default/default.pro b/examples/declarative/extending/default/default.pro
new file mode 100644
index 0000000..0d5d45c
--- /dev/null
+++ b/examples/declarative/extending/default/default.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = default
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp
+HEADERS += person.h \
+ birthdayparty.h
+RESOURCES += default.qrc
diff --git a/examples/declarative/extending/default/default.qrc b/examples/declarative/extending/default/default.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/default/default.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/default/example.qml b/examples/declarative/extending/default/example.qml
new file mode 100644
index 0000000..58035f9
--- /dev/null
+++ b/examples/declarative/extending/default/example.qml
@@ -0,0 +1,14 @@
+import People 1.0
+
+// ![0]
+BirthdayParty {
+ celebrant: Boy {
+ name: "Bob Jones"
+ shoeSize: 12
+ }
+
+ Boy { name: "Joan Hodges" }
+ Boy { name: "Jack Smith" }
+ Girl { name: "Anne Brown" }
+}
+// ![0]
diff --git a/examples/declarative/extending/default/main.cpp b/examples/declarative/extending/default/main.cpp
new file mode 100644
index 0000000..1ad6d26
--- /dev/null
+++ b/examples/declarative/extending/default/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+
+ if (qobject_cast<Boy *>(party->celebrant()))
+ qWarning() << "He is inviting:";
+ else
+ qWarning() << "She is inviting:";
+ for (int ii = 0; ii < party->guests()->count(); ++ii)
+ qWarning() << " " << party->guests()->at(ii)->name();
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return 0;
+}
diff --git a/examples/declarative/extending/default/person.cpp b/examples/declarative/extending/default/person.cpp
new file mode 100644
index 0000000..a5eafc4
--- /dev/null
+++ b/examples/declarative/extending/default/person.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+Person::Person(QObject *parent)
+: QObject(parent), m_shoeSize(0)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+int Person::shoeSize() const
+{
+ return m_shoeSize;
+}
+
+void Person::setShoeSize(int s)
+{
+ m_shoeSize = s;
+}
+
+QML_DEFINE_NOCREATE_TYPE(Person);
+
+Boy::Boy(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Boy, Boy);
+
+Girl::Girl(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Girl, Girl);
diff --git a/examples/declarative/extending/default/person.h b/examples/declarative/extending/default/person.h
new file mode 100644
index 0000000..6fd9232
--- /dev/null
+++ b/examples/declarative/extending/default/person.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <qml.h>
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ int shoeSize() const;
+ void setShoeSize(int);
+private:
+ QString m_name;
+ int m_shoeSize;
+};
+QML_DECLARE_TYPE(Person);
+
+class Boy : public Person {
+Q_OBJECT
+public:
+ Boy(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Boy);
+
+class Girl : public Person {
+Q_OBJECT
+public:
+ Girl(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Girl);
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/extended/example.qml b/examples/declarative/extending/extended/example.qml
new file mode 100644
index 0000000..985ce20
--- /dev/null
+++ b/examples/declarative/extending/extended/example.qml
@@ -0,0 +1,7 @@
+import People 1.0
+
+// ![0]
+QLineEdit {
+ leftMargin: 20
+}
+// ![0]
diff --git a/examples/declarative/extending/extended/extended.pro b/examples/declarative/extending/extended/extended.pro
new file mode 100644
index 0000000..1182226
--- /dev/null
+++ b/examples/declarative/extending/extended/extended.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = extended
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ lineedit.cpp
+HEADERS += lineedit.h
+RESOURCES += extended.qrc
diff --git a/examples/declarative/extending/extended/extended.qrc b/examples/declarative/extending/extended/extended.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/extended/extended.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/extended/lineedit.cpp b/examples/declarative/extending/extended/lineedit.cpp
new file mode 100644
index 0000000..8a31004
--- /dev/null
+++ b/examples/declarative/extending/extended/lineedit.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "lineedit.h"
+#include <qml.h>
+
+LineEditExtension::LineEditExtension(QObject *object)
+: QObject(object), m_lineedit(static_cast<QLineEdit *>(object))
+{
+}
+
+int LineEditExtension::leftMargin() const
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ return l;
+}
+
+void LineEditExtension::setLeftMargin(int m)
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ m_lineedit->setTextMargins(m, t, r, b);
+}
+
+int LineEditExtension::rightMargin() const
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ return r;
+}
+
+void LineEditExtension::setRightMargin(int m)
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ m_lineedit->setTextMargins(l, t, m, b);
+}
+
+int LineEditExtension::topMargin() const
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ return t;
+}
+
+void LineEditExtension::setTopMargin(int m)
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ m_lineedit->setTextMargins(l, m, r, b);
+}
+
+int LineEditExtension::bottomMargin() const
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ return b;
+}
+
+void LineEditExtension::setBottomMargin(int m)
+{
+ int l, r, t, b;
+ m_lineedit->getTextMargins(&l, &t, &r, &b);
+ m_lineedit->setTextMargins(l, t, r, m);
+}
+
+QML_DECLARE_TYPE(QLineEdit);
+QML_DEFINE_EXTENDED_TYPE(People, 1,0, QLineEdit, QLineEdit, LineEditExtension);
diff --git a/examples/declarative/extending/extended/lineedit.h b/examples/declarative/extending/extended/lineedit.h
new file mode 100644
index 0000000..3f03ba1
--- /dev/null
+++ b/examples/declarative/extending/extended/lineedit.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef LINEEDIT_H
+#define LINEEDIT_H
+
+#include <QLineEdit>
+
+class LineEditExtension : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(int leftMargin READ leftMargin WRITE setLeftMargin NOTIFY marginsChanged);
+Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin NOTIFY marginsChanged);
+Q_PROPERTY(int topMargin READ topMargin WRITE setTopMargin NOTIFY marginsChanged);
+Q_PROPERTY(int bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY marginsChanged);
+public:
+ LineEditExtension(QObject *);
+
+ int leftMargin() const;
+ void setLeftMargin(int);
+
+ int rightMargin() const;
+ void setRightMargin(int);
+
+ int topMargin() const;
+ void setTopMargin(int);
+
+ int bottomMargin() const;
+ void setBottomMargin(int);
+signals:
+ void marginsChanged();
+
+private:
+ QLineEdit *m_lineedit;
+};
+
+#endif // LINEEDIT_H
diff --git a/examples/declarative/extending/extended/main.cpp b/examples/declarative/extending/extended/main.cpp
new file mode 100644
index 0000000..c956ebc
--- /dev/null
+++ b/examples/declarative/extending/extended/main.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include <QLineEdit>
+
+int main(int argc, char ** argv)
+{
+ QApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ QLineEdit *edit = qobject_cast<QLineEdit *>(component.create());
+
+ if (edit) {
+ edit->show();
+ return app.exec();
+ } else {
+ qWarning() << "An error occured";
+ return 0;
+ }
+}
diff --git a/examples/declarative/extending/grouped/birthdayparty.cpp b/examples/declarative/extending/grouped/birthdayparty.cpp
new file mode 100644
index 0000000..f3e0846
--- /dev/null
+++ b/examples/declarative/extending/grouped/birthdayparty.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ m_celebrant = c;
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/grouped/birthdayparty.h b/examples/declarative/extending/grouped/birthdayparty.h
new file mode 100644
index 0000000..ba8a68d
--- /dev/null
+++ b/examples/declarative/extending/grouped/birthdayparty.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <qml.h>
+#include "person.h"
+
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant)
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+Q_CLASSINFO("DefaultProperty", "guests")
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+QML_DECLARE_TYPE(BirthdayParty);
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/grouped/example.qml b/examples/declarative/extending/grouped/example.qml
new file mode 100644
index 0000000..55912ed
--- /dev/null
+++ b/examples/declarative/extending/grouped/example.qml
@@ -0,0 +1,33 @@
+import People 1.0
+
+// ![0]
+BirthdayParty {
+ celebrant: Boy {
+ name: "Bob Jones"
+ shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
+ }
+
+ Boy {
+ name: "Joan Hodges"
+ shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
+ }
+ // ![1]
+ Boy {
+ name: "Jack Smith"
+ shoe {
+ size: 8
+ color: "blue"
+ brand: "Puma"
+ price: 19.95
+ }
+ }
+ // ![1]
+ Girl {
+ name: "Anne Brown"
+ shoe.size: 7
+ shoe.color: "red"
+ shoe.brand: "Marc Jacobs"
+ shoe.price: 699.99
+ }
+}
+// ![0]
diff --git a/examples/declarative/extending/grouped/grouped.pro b/examples/declarative/extending/grouped/grouped.pro
new file mode 100644
index 0000000..8fde8e8
--- /dev/null
+++ b/examples/declarative/extending/grouped/grouped.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = grouped
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp
+HEADERS += person.h \
+ birthdayparty.h
+RESOURCES += grouped.qrc
diff --git a/examples/declarative/extending/grouped/grouped.qrc b/examples/declarative/extending/grouped/grouped.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/grouped/grouped.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/grouped/main.cpp b/examples/declarative/extending/grouped/main.cpp
new file mode 100644
index 0000000..baf5349
--- /dev/null
+++ b/examples/declarative/extending/grouped/main.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+
+ if (qobject_cast<Boy *>(party->celebrant()))
+ qWarning() << "He is inviting:";
+ else
+ qWarning() << "She is inviting:";
+
+ Person *bestShoe = 0;
+ for (int ii = 0; ii < party->guests()->count(); ++ii) {
+ Person *guest = party->guests()->at(ii);
+ qWarning() << " " << guest->name();
+
+ if (!bestShoe || bestShoe->shoe()->price() < guest->shoe()->price())
+ bestShoe = guest;
+ }
+ if (bestShoe)
+ qWarning() << bestShoe->name() << "is wearing the best shoes!";
+
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return 0;
+}
diff --git a/examples/declarative/extending/grouped/person.cpp b/examples/declarative/extending/grouped/person.cpp
new file mode 100644
index 0000000..8105ee7
--- /dev/null
+++ b/examples/declarative/extending/grouped/person.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+ShoeDescription::ShoeDescription(QObject *parent)
+: QObject(parent), m_size(0), m_price(0)
+{
+}
+
+int ShoeDescription::size() const
+{
+ return m_size;
+}
+
+void ShoeDescription::setSize(int s)
+{
+ m_size = s;
+}
+
+QColor ShoeDescription::color() const
+{
+ return m_color;
+}
+
+void ShoeDescription::setColor(const QColor &c)
+{
+ m_color = c;
+}
+
+QString ShoeDescription::brand() const
+{
+ return m_brand;
+}
+
+void ShoeDescription::setBrand(const QString &b)
+{
+ m_brand = b;
+}
+
+qreal ShoeDescription::price() const
+{
+ return m_price;
+}
+
+void ShoeDescription::setPrice(qreal p)
+{
+ m_price = p;
+}
+QML_DEFINE_NOCREATE_TYPE(ShoeDescription);
+
+Person::Person(QObject *parent)
+: QObject(parent)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+ShoeDescription *Person::shoe()
+{
+ return &m_shoe;
+}
+
+QML_DEFINE_NOCREATE_TYPE(Person);
+
+Boy::Boy(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Boy, Boy);
+
+Girl::Girl(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Girl, Girl);
diff --git a/examples/declarative/extending/grouped/person.h b/examples/declarative/extending/grouped/person.h
new file mode 100644
index 0000000..5cd3e8f
--- /dev/null
+++ b/examples/declarative/extending/grouped/person.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <QColor>
+#include <qml.h>
+
+class ShoeDescription : public QObject {
+Q_OBJECT
+Q_PROPERTY(int size READ size WRITE setSize)
+Q_PROPERTY(QColor color READ color WRITE setColor)
+Q_PROPERTY(QString brand READ brand WRITE setBrand)
+Q_PROPERTY(qreal price READ price WRITE setPrice)
+public:
+ ShoeDescription(QObject *parent = 0);
+
+ int size() const;
+ void setSize(int);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QString brand() const;
+ void setBrand(const QString &);
+
+ qreal price() const;
+ void setPrice(qreal);
+private:
+ int m_size;
+ QColor m_color;
+ QString m_brand;
+ qreal m_price;
+};
+QML_DECLARE_TYPE(ShoeDescription);
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+// ![1]
+Q_PROPERTY(ShoeDescription *shoe READ shoe);
+// ![1]
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ ShoeDescription *shoe();
+private:
+ QString m_name;
+ ShoeDescription m_shoe;
+};
+QML_DECLARE_TYPE(Person);
+
+class Boy : public Person {
+Q_OBJECT
+public:
+ Boy(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Boy);
+
+class Girl : public Person {
+Q_OBJECT
+public:
+ Girl(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Girl);
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/properties/birthdayparty.cpp b/examples/declarative/extending/properties/birthdayparty.cpp
new file mode 100644
index 0000000..b98a691
--- /dev/null
+++ b/examples/declarative/extending/properties/birthdayparty.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+// ![0]
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ m_celebrant = c;
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+// ![0]
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/properties/birthdayparty.h b/examples/declarative/extending/properties/birthdayparty.h
new file mode 100644
index 0000000..7bc3c3f
--- /dev/null
+++ b/examples/declarative/extending/properties/birthdayparty.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <qml.h>
+#include "person.h"
+
+// ![0]
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+// ![0]
+// ![1]
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant)
+// ![1]
+// ![2]
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+// ![2]
+// ![3]
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+QML_DECLARE_TYPE(BirthdayParty);
+// ![3]
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/properties/example.qml b/examples/declarative/extending/properties/example.qml
new file mode 100644
index 0000000..9594a84
--- /dev/null
+++ b/examples/declarative/extending/properties/example.qml
@@ -0,0 +1,15 @@
+import People 1.0
+
+// ![0]
+BirthdayParty {
+ celebrant: Person {
+ name: "Bob Jones"
+ shoeSize: 12
+ }
+ guests: [
+ Person { name: "Joan Hodges" },
+ Person { name: "Jack Smith" },
+ Person { name: "Anne Brown" }
+ ]
+}
+// ![0]
diff --git a/examples/declarative/extending/properties/main.cpp b/examples/declarative/extending/properties/main.cpp
new file mode 100644
index 0000000..590628e
--- /dev/null
+++ b/examples/declarative/extending/properties/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+ qWarning() << "They are inviting:";
+ for (int ii = 0; ii < party->guests()->count(); ++ii)
+ qWarning() << " " << party->guests()->at(ii)->name();
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return 0;
+}
diff --git a/examples/declarative/extending/properties/person.cpp b/examples/declarative/extending/properties/person.cpp
new file mode 100644
index 0000000..b41d0b6
--- /dev/null
+++ b/examples/declarative/extending/properties/person.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+Person::Person(QObject *parent)
+: QObject(parent), m_shoeSize(0)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+int Person::shoeSize() const
+{
+ return m_shoeSize;
+}
+
+void Person::setShoeSize(int s)
+{
+ m_shoeSize = s;
+}
+
+QML_DEFINE_TYPE(People, 1,0, Person, Person);
diff --git a/examples/declarative/extending/properties/person.h b/examples/declarative/extending/properties/person.h
new file mode 100644
index 0000000..1c69f5a
--- /dev/null
+++ b/examples/declarative/extending/properties/person.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <qml.h>
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ int shoeSize() const;
+ void setShoeSize(int);
+private:
+ QString m_name;
+ int m_shoeSize;
+};
+QML_DECLARE_TYPE(Person);
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/properties/properties.pro b/examples/declarative/extending/properties/properties.pro
new file mode 100644
index 0000000..6355644
--- /dev/null
+++ b/examples/declarative/extending/properties/properties.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = properties
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp
+HEADERS += person.h \
+ birthdayparty.h
+RESOURCES += properties.qrc
diff --git a/examples/declarative/extending/properties/properties.qrc b/examples/declarative/extending/properties/properties.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/properties/properties.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/signal/birthdayparty.cpp b/examples/declarative/extending/signal/birthdayparty.cpp
new file mode 100644
index 0000000..178ce0e
--- /dev/null
+++ b/examples/declarative/extending/signal/birthdayparty.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayPartyAttached::BirthdayPartyAttached(QObject *object)
+: QObject(object)
+{
+}
+
+QDate BirthdayPartyAttached::rsvp() const
+{
+ return m_rsvp;
+}
+
+void BirthdayPartyAttached::setRsvp(const QDate &d)
+{
+ m_rsvp = d;
+}
+
+QML_DEFINE_NOCREATE_TYPE(BirthdayPartyAttached);
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ m_celebrant = c;
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+
+void BirthdayParty::startParty()
+{
+ QTime time = QTime::currentTime();
+ emit partyStarted(time);
+}
+
+BirthdayPartyAttached *BirthdayParty::qmlAttachedProperties(QObject *object)
+{
+ return new BirthdayPartyAttached(object);
+}
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/signal/birthdayparty.h b/examples/declarative/extending/signal/birthdayparty.h
new file mode 100644
index 0000000..56a809e
--- /dev/null
+++ b/examples/declarative/extending/signal/birthdayparty.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <QDate>
+#include <qml.h>
+#include "person.h"
+
+class BirthdayPartyAttached : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp)
+public:
+ BirthdayPartyAttached(QObject *object);
+
+ QDate rsvp() const;
+ void setRsvp(const QDate &);
+
+private:
+ QDate m_rsvp;
+};
+QML_DECLARE_TYPE(BirthdayPartyAttached)
+
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant)
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+Q_CLASSINFO("DefaultProperty", "guests")
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+ static BirthdayPartyAttached *qmlAttachedProperties(QObject *);
+
+ void startParty();
+// ![0]
+signals:
+ void partyStarted(const QTime &time);
+// ![0]
+
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+
+QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(BirthdayParty)
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/signal/example.qml b/examples/declarative/extending/signal/example.qml
new file mode 100644
index 0000000..c7d4792
--- /dev/null
+++ b/examples/declarative/extending/signal/example.qml
@@ -0,0 +1,32 @@
+import People 1.0
+
+// ![0]
+BirthdayParty {
+ onPartyStarted: console.log("This party started rockin' at " + time);
+// ![0]
+
+ celebrant: Boy {
+ name: "Bob Jones"
+ shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
+ }
+
+ Boy {
+ name: "Joan Hodges"
+ BirthdayParty.rsvp: "2009-07-06"
+ shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
+ }
+ Boy {
+ name: "Jack Smith"
+ shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 }
+ }
+ Girl {
+ name: "Anne Brown"
+ BirthdayParty.rsvp: "2009-07-01"
+ shoe.size: 7
+ shoe.color: "red"
+ shoe.brand: "Marc Jacobs"
+ shoe.price: 699.99
+ }
+// ![1]
+}
+// ![1]
diff --git a/examples/declarative/extending/signal/main.cpp b/examples/declarative/extending/signal/main.cpp
new file mode 100644
index 0000000..d4e32a1
--- /dev/null
+++ b/examples/declarative/extending/signal/main.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+
+ if (qobject_cast<Boy *>(party->celebrant()))
+ qWarning() << "He is inviting:";
+ else
+ qWarning() << "She is inviting:";
+
+ for (int ii = 0; ii < party->guests()->count(); ++ii) {
+ Person *guest = party->guests()->at(ii);
+
+ QDate rsvpDate;
+ QObject *attached =
+ qmlAttachedPropertiesObject<BirthdayParty>(guest, false);
+ if (attached)
+ rsvpDate = attached->property("rsvp").toDate();
+
+ if (rsvpDate.isNull())
+ qWarning() << " " << guest->name() << "RSVP date: Hasn't RSVP'd";
+ else
+ qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString());
+ }
+
+ party->startParty();
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return 0;
+}
diff --git a/examples/declarative/extending/signal/person.cpp b/examples/declarative/extending/signal/person.cpp
new file mode 100644
index 0000000..8105ee7
--- /dev/null
+++ b/examples/declarative/extending/signal/person.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+ShoeDescription::ShoeDescription(QObject *parent)
+: QObject(parent), m_size(0), m_price(0)
+{
+}
+
+int ShoeDescription::size() const
+{
+ return m_size;
+}
+
+void ShoeDescription::setSize(int s)
+{
+ m_size = s;
+}
+
+QColor ShoeDescription::color() const
+{
+ return m_color;
+}
+
+void ShoeDescription::setColor(const QColor &c)
+{
+ m_color = c;
+}
+
+QString ShoeDescription::brand() const
+{
+ return m_brand;
+}
+
+void ShoeDescription::setBrand(const QString &b)
+{
+ m_brand = b;
+}
+
+qreal ShoeDescription::price() const
+{
+ return m_price;
+}
+
+void ShoeDescription::setPrice(qreal p)
+{
+ m_price = p;
+}
+QML_DEFINE_NOCREATE_TYPE(ShoeDescription);
+
+Person::Person(QObject *parent)
+: QObject(parent)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+ShoeDescription *Person::shoe()
+{
+ return &m_shoe;
+}
+
+QML_DEFINE_NOCREATE_TYPE(Person);
+
+Boy::Boy(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Boy, Boy);
+
+Girl::Girl(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Girl, Girl);
diff --git a/examples/declarative/extending/signal/person.h b/examples/declarative/extending/signal/person.h
new file mode 100644
index 0000000..c5b7727
--- /dev/null
+++ b/examples/declarative/extending/signal/person.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <QColor>
+#include <qml.h>
+
+class ShoeDescription : public QObject {
+Q_OBJECT
+Q_PROPERTY(int size READ size WRITE setSize)
+Q_PROPERTY(QColor color READ color WRITE setColor)
+Q_PROPERTY(QString brand READ brand WRITE setBrand)
+Q_PROPERTY(qreal price READ price WRITE setPrice)
+public:
+ ShoeDescription(QObject *parent = 0);
+
+ int size() const;
+ void setSize(int);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QString brand() const;
+ void setBrand(const QString &);
+
+ qreal price() const;
+ void setPrice(qreal);
+private:
+ int m_size;
+ QColor m_color;
+ QString m_brand;
+ qreal m_price;
+};
+QML_DECLARE_TYPE(ShoeDescription);
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+Q_PROPERTY(ShoeDescription *shoe READ shoe);
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ ShoeDescription *shoe();
+private:
+ QString m_name;
+ ShoeDescription m_shoe;
+};
+QML_DECLARE_TYPE(Person);
+
+class Boy : public Person {
+Q_OBJECT
+public:
+ Boy(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Boy);
+
+class Girl : public Person {
+Q_OBJECT
+public:
+ Girl(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Girl);
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/signal/signal.pro b/examples/declarative/extending/signal/signal.pro
new file mode 100644
index 0000000..30e413f
--- /dev/null
+++ b/examples/declarative/extending/signal/signal.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = signal
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp
+HEADERS += person.h \
+ birthdayparty.h
+RESOURCES += signal.qrc
diff --git a/examples/declarative/extending/signal/signal.qrc b/examples/declarative/extending/signal/signal.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/signal/signal.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/extending/valuesource/birthdayparty.cpp b/examples/declarative/extending/valuesource/birthdayparty.cpp
new file mode 100644
index 0000000..b0472d0
--- /dev/null
+++ b/examples/declarative/extending/valuesource/birthdayparty.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "birthdayparty.h"
+
+BirthdayPartyAttached::BirthdayPartyAttached(QObject *object)
+: QObject(object)
+{
+}
+
+QDate BirthdayPartyAttached::rsvp() const
+{
+ return m_rsvp;
+}
+
+void BirthdayPartyAttached::setRsvp(const QDate &d)
+{
+ m_rsvp = d;
+}
+
+QML_DEFINE_NOCREATE_TYPE(BirthdayPartyAttached);
+
+BirthdayParty::BirthdayParty(QObject *parent)
+: QObject(parent), m_celebrant(0)
+{
+}
+
+Person *BirthdayParty::celebrant() const
+{
+ return m_celebrant;
+}
+
+void BirthdayParty::setCelebrant(Person *c)
+{
+ m_celebrant = c;
+}
+
+QmlList<Person *> *BirthdayParty::guests()
+{
+ return &m_guests;
+}
+
+void BirthdayParty::startParty()
+{
+ QTime time = QTime::currentTime();
+ emit partyStarted(time);
+}
+
+QString BirthdayParty::speaker() const
+{
+ return QString();
+}
+
+void BirthdayParty::setSpeaker(const QString &speak)
+{
+ qWarning() << qPrintable(speak);
+}
+
+BirthdayPartyAttached *BirthdayParty::qmlAttachedProperties(QObject *object)
+{
+ return new BirthdayPartyAttached(object);
+}
+
+QML_DEFINE_TYPE(People, 1,0, BirthdayParty, BirthdayParty);
diff --git a/examples/declarative/extending/valuesource/birthdayparty.h b/examples/declarative/extending/valuesource/birthdayparty.h
new file mode 100644
index 0000000..11e1fdf
--- /dev/null
+++ b/examples/declarative/extending/valuesource/birthdayparty.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BIRTHDAYPARTY_H
+#define BIRTHDAYPARTY_H
+
+#include <QObject>
+#include <QDate>
+#include <QDebug>
+#include <qml.h>
+#include "person.h"
+
+class BirthdayPartyAttached : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp)
+public:
+ BirthdayPartyAttached(QObject *object);
+
+ QDate rsvp() const;
+ void setRsvp(const QDate &);
+
+private:
+ QDate m_rsvp;
+};
+QML_DECLARE_TYPE(BirthdayPartyAttached)
+
+class BirthdayParty : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant)
+Q_PROPERTY(QmlList<Person *> *guests READ guests)
+// ![0]
+Q_PROPERTY(QString speaker READ speaker WRITE setSpeaker)
+// ![0]
+Q_CLASSINFO("DefaultProperty", "guests")
+public:
+ BirthdayParty(QObject *parent = 0);
+
+ Person *celebrant() const;
+ void setCelebrant(Person *);
+
+ QmlList<Person *> *guests();
+
+ QString speaker() const;
+ void setSpeaker(const QString &);
+
+ static BirthdayPartyAttached *qmlAttachedProperties(QObject *);
+
+ void startParty();
+signals:
+ void partyStarted(const QTime &time);
+
+private:
+ Person *m_celebrant;
+ QmlConcreteList<Person *> m_guests;
+};
+
+QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(BirthdayParty)
+
+#endif // BIRTHDAYPARTY_H
diff --git a/examples/declarative/extending/valuesource/example.qml b/examples/declarative/extending/valuesource/example.qml
new file mode 100644
index 0000000..7cdf8c0
--- /dev/null
+++ b/examples/declarative/extending/valuesource/example.qml
@@ -0,0 +1,36 @@
+import People 1.0
+
+// ![0]
+BirthdayParty {
+ speaker: HappyBirthday { name: "Bob Jones" }
+// ![0]
+
+ onPartyStarted: console.log("This party started rockin' at " + time);
+
+
+ celebrant: Boy {
+ name: "Bob Jones"
+ shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
+ }
+
+ Boy {
+ name: "Joan Hodges"
+ BirthdayParty.rsvp: "2009-07-06"
+ shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
+ }
+ Boy {
+ name: "Jack Smith"
+ shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 }
+ }
+ Girl {
+ name: "Anne Brown"
+ BirthdayParty.rsvp: "2009-07-01"
+ shoe.size: 7
+ shoe.color: "red"
+ shoe.brand: "Marc Jacobs"
+ shoe.price: 699.99
+ }
+
+// ![1]
+}
+// ![1]
diff --git a/examples/declarative/extending/valuesource/happybirthday.cpp b/examples/declarative/extending/valuesource/happybirthday.cpp
new file mode 100644
index 0000000..b453944
--- /dev/null
+++ b/examples/declarative/extending/valuesource/happybirthday.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "happybirthday.h"
+#include <QTimer>
+
+HappyBirthday::HappyBirthday(QObject *parent)
+: QObject(parent), m_line(-1)
+{
+ setName(QString());
+ QTimer *timer = new QTimer(this);
+ QObject::connect(timer, SIGNAL(timeout()), this, SLOT(advance()));
+ timer->start(1000);
+}
+
+void HappyBirthday::setTarget(const QmlMetaProperty &p)
+{
+ m_target = p;
+}
+
+QString HappyBirthday::name() const
+{
+ return m_name;
+}
+
+void HappyBirthday::setName(const QString &name)
+{
+ m_name = name;
+
+ m_lyrics.clear();
+ m_lyrics << "Happy birthday to you,";
+ m_lyrics << "Happy birthday to you,";
+ m_lyrics << "Happy birthday dear " + m_name + ",";
+ m_lyrics << "Happy birthday to you!";
+ m_lyrics << "";
+}
+
+void HappyBirthday::advance()
+{
+ m_line = (m_line + 1) % m_lyrics.count();
+
+ m_target.write(m_lyrics.at(m_line));
+}
+
+QML_DEFINE_TYPE(People, 1,0, HappyBirthday, HappyBirthday);
diff --git a/examples/declarative/extending/valuesource/happybirthday.h b/examples/declarative/extending/valuesource/happybirthday.h
new file mode 100644
index 0000000..4e8e87c
--- /dev/null
+++ b/examples/declarative/extending/valuesource/happybirthday.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef HAPPYBIRTHDAY_H
+#define HAPPYBIRTHDAY_H
+
+#include <QmlPropertyValueSource>
+#include <qml.h>
+
+#include <QStringList>
+
+// ![0]
+class HappyBirthday : public QObject, public QmlPropertyValueSource
+{
+Q_OBJECT
+// ![0]
+Q_PROPERTY(QString name READ name WRITE setName)
+// ![1]
+public:
+ HappyBirthday(QObject *parent = 0);
+
+ virtual void setTarget(const QmlMetaProperty &);
+// ![1]
+
+ QString name() const;
+ void setName(const QString &);
+
+private slots:
+ void advance();
+
+private:
+ int m_line;
+ QStringList m_lyrics;
+ QmlMetaProperty m_target;
+ QString m_name;
+// ![2]
+};
+// ![2]
+QML_DECLARE_TYPE(HappyBirthday);
+
+#endif // HAPPYBIRTHDAY_H
+
diff --git a/examples/declarative/extending/valuesource/main.cpp b/examples/declarative/extending/valuesource/main.cpp
new file mode 100644
index 0000000..c4090c4
--- /dev/null
+++ b/examples/declarative/extending/valuesource/main.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include "birthdayparty.h"
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QmlEngine engine;
+ QmlComponent component(&engine, ":example.qml");
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create());
+
+ if (party && party->celebrant()) {
+ qWarning() << party->celebrant()->name() << "is having a birthday!";
+
+ if (qobject_cast<Boy *>(party->celebrant()))
+ qWarning() << "He is inviting:";
+ else
+ qWarning() << "She is inviting:";
+
+ for (int ii = 0; ii < party->guests()->count(); ++ii) {
+ Person *guest = party->guests()->at(ii);
+
+ QDate rsvpDate;
+ QObject *attached =
+ qmlAttachedPropertiesObject<BirthdayParty>(guest, false);
+ if (attached)
+ rsvpDate = attached->property("rsvp").toDate();
+
+ if (rsvpDate.isNull())
+ qWarning() << " " << guest->name() << "RSVP date: Hasn't RSVP'd";
+ else
+ qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString());
+ }
+
+ party->startParty();
+ } else {
+ qWarning() << "An error occured";
+ }
+
+ return app.exec();
+}
diff --git a/examples/declarative/extending/valuesource/person.cpp b/examples/declarative/extending/valuesource/person.cpp
new file mode 100644
index 0000000..8105ee7
--- /dev/null
+++ b/examples/declarative/extending/valuesource/person.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+ShoeDescription::ShoeDescription(QObject *parent)
+: QObject(parent), m_size(0), m_price(0)
+{
+}
+
+int ShoeDescription::size() const
+{
+ return m_size;
+}
+
+void ShoeDescription::setSize(int s)
+{
+ m_size = s;
+}
+
+QColor ShoeDescription::color() const
+{
+ return m_color;
+}
+
+void ShoeDescription::setColor(const QColor &c)
+{
+ m_color = c;
+}
+
+QString ShoeDescription::brand() const
+{
+ return m_brand;
+}
+
+void ShoeDescription::setBrand(const QString &b)
+{
+ m_brand = b;
+}
+
+qreal ShoeDescription::price() const
+{
+ return m_price;
+}
+
+void ShoeDescription::setPrice(qreal p)
+{
+ m_price = p;
+}
+QML_DEFINE_NOCREATE_TYPE(ShoeDescription);
+
+Person::Person(QObject *parent)
+: QObject(parent)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+ShoeDescription *Person::shoe()
+{
+ return &m_shoe;
+}
+
+QML_DEFINE_NOCREATE_TYPE(Person);
+
+Boy::Boy(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Boy, Boy);
+
+Girl::Girl(QObject * parent)
+: Person(parent)
+{
+}
+
+QML_DEFINE_TYPE(People, 1,0, Girl, Girl);
diff --git a/examples/declarative/extending/valuesource/person.h b/examples/declarative/extending/valuesource/person.h
new file mode 100644
index 0000000..c5b7727
--- /dev/null
+++ b/examples/declarative/extending/valuesource/person.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <QColor>
+#include <qml.h>
+
+class ShoeDescription : public QObject {
+Q_OBJECT
+Q_PROPERTY(int size READ size WRITE setSize)
+Q_PROPERTY(QColor color READ color WRITE setColor)
+Q_PROPERTY(QString brand READ brand WRITE setBrand)
+Q_PROPERTY(qreal price READ price WRITE setPrice)
+public:
+ ShoeDescription(QObject *parent = 0);
+
+ int size() const;
+ void setSize(int);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QString brand() const;
+ void setBrand(const QString &);
+
+ qreal price() const;
+ void setPrice(qreal);
+private:
+ int m_size;
+ QColor m_color;
+ QString m_brand;
+ qreal m_price;
+};
+QML_DECLARE_TYPE(ShoeDescription);
+
+class Person : public QObject {
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+Q_PROPERTY(ShoeDescription *shoe READ shoe);
+public:
+ Person(QObject *parent = 0);
+
+ QString name() const;
+ void setName(const QString &);
+
+ ShoeDescription *shoe();
+private:
+ QString m_name;
+ ShoeDescription m_shoe;
+};
+QML_DECLARE_TYPE(Person);
+
+class Boy : public Person {
+Q_OBJECT
+public:
+ Boy(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Boy);
+
+class Girl : public Person {
+Q_OBJECT
+public:
+ Girl(QObject * parent = 0);
+};
+QML_DECLARE_TYPE(Girl);
+
+#endif // PERSON_H
diff --git a/examples/declarative/extending/valuesource/valuesource.pro b/examples/declarative/extending/valuesource/valuesource.pro
new file mode 100644
index 0000000..9e54448
--- /dev/null
+++ b/examples/declarative/extending/valuesource/valuesource.pro
@@ -0,0 +1,15 @@
+TEMPLATE = app
+TARGET = valuesource
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ person.cpp \
+ birthdayparty.cpp \
+ happybirthday.cpp
+HEADERS += person.h \
+ birthdayparty.h \
+ happybirthday.h
+RESOURCES += valuesource.qrc
diff --git a/examples/declarative/extending/valuesource/valuesource.qrc b/examples/declarative/extending/valuesource/valuesource.qrc
new file mode 100644
index 0000000..e2fa01d
--- /dev/null
+++ b/examples/declarative/extending/valuesource/valuesource.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>example.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/fillmode/face.png b/examples/declarative/fillmode/face.png
new file mode 100644
index 0000000..9623b1a
--- /dev/null
+++ b/examples/declarative/fillmode/face.png
Binary files differ
diff --git a/examples/declarative/fillmode/fillmode.qml b/examples/declarative/fillmode/fillmode.qml
new file mode 100644
index 0000000..ec3717f
--- /dev/null
+++ b/examples/declarative/fillmode/fillmode.qml
@@ -0,0 +1,41 @@
+import Qt 4.6
+
+Image {
+ width: 400
+ height: 250
+ source: "face.png"
+ fillMode: SequentialAnimation {
+ repeat: true
+ PropertyAction { value: Image.Stretch }
+ PropertyAction { target: label; property: "text"; value: "Stretch" }
+ PauseAnimation { duration: 1000 }
+ PropertyAction { value: Image.PreserveAspectFit }
+ PropertyAction { target: label; property: "text"; value: "PreserveAspectFit" }
+ PauseAnimation { duration: 1000 }
+ PropertyAction { value: Image.PreserveAspectCrop }
+ PropertyAction { target: label; property: "text"; value: "PreserveAspectCrop" }
+ PauseAnimation { duration: 1000 }
+ PropertyAction { value: Image.Tile }
+ PropertyAction { target: label; property: "text"; value: "Tile" }
+ PauseAnimation { duration: 1000 }
+ PropertyAction { value: Image.TileHorizontally }
+ PropertyAction { target: label; property: "text"; value: "TileHorizontally" }
+ PauseAnimation { duration: 1000 }
+ PropertyAction { value: Image.TileVertically }
+ PropertyAction { target: label; property: "text"; value: "TileVertically" }
+ PauseAnimation { duration: 1000 }
+ }
+ Text {
+ id: label
+ font.pointSize: 24
+ color: "blue"
+ style: Text.Outline
+ styleColor: "white"
+ anchors { centerIn: parent }
+ }
+ Rectangle {
+ border.color: "black"
+ color: "transparent"
+ anchors { fill: parent; rightMargin: 1; bottomMargin: 1}
+ }
+}
diff --git a/examples/declarative/focusscope/test.qml b/examples/declarative/focusscope/test.qml
new file mode 100644
index 0000000..e4332e7
--- /dev/null
+++ b/examples/declarative/focusscope/test.qml
@@ -0,0 +1,76 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 800
+ height: 600
+
+ Keys.onDigit9Pressed: console.log("Error - Root")
+
+ FocusScope {
+ id: myScope
+ focus: true
+
+ Keys.onDigit9Pressed: console.log("Error - FocusScope")
+
+ Rectangle {
+ height: 120
+ width: 420
+
+ color: "transparent"
+ border.width: 5
+ border.color: myScope.wantsFocus?"blue":"black"
+
+ Rectangle {
+ id: item1
+ x: 10; y: 10
+ width: 100; height: 100; color: "green"
+ border.width: 5
+ border.color: wantsFocus?"blue":"black"
+ Keys.onDigit9Pressed: console.log("Top Left");
+ KeyNavigation.right: item2
+ focus: true
+
+ Rectangle {
+ width: 50; height: 50; anchors.centerIn: parent
+ color: parent.focus?"red":"transparent"
+ }
+ }
+
+ Rectangle {
+ id: item2
+ x: 310; y: 10
+ width: 100; height: 100; color: "green"
+ border.width: 5
+ border.color: wantsFocus?"blue":"black"
+ KeyNavigation.left: item1
+ Keys.onDigit9Pressed: console.log("Top Right");
+
+ Rectangle {
+ width: 50; height: 50; anchors.centerIn: parent
+ color: parent.focus?"red":"transparent"
+ }
+ }
+ }
+ KeyNavigation.down: item3
+ }
+
+ Text { x:100; y:170; text: "Blue border indicates scoped focus\nBlack border indicates NOT scoped focus\nRed box indicates active focus\nUse arrow keys to navigate\nPress \"9\" to print currently focused item" }
+
+ Rectangle {
+ id: item3
+ x: 10; y: 300
+ width: 100; height: 100; color: "green"
+ border.width: 5
+ border.color: wantsFocus?"blue":"black"
+
+ Keys.onDigit9Pressed: console.log("Bottom Left");
+ KeyNavigation.up: myScope
+
+ Rectangle {
+ width: 50; height: 50; anchors.centerIn: parent
+ color: parent.focus?"red":"transparent"
+ }
+ }
+
+}
diff --git a/examples/declarative/focusscope/test2.qml b/examples/declarative/focusscope/test2.qml
new file mode 100644
index 0000000..5b6971a
--- /dev/null
+++ b/examples/declarative/focusscope/test2.qml
@@ -0,0 +1,40 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 800
+ height: 600
+
+ Text { text: "All five rectangles should be red" }
+
+ FocusScope {
+ y: 100
+ focus: true
+ Rectangle { width: 50; height: 50; color: parent.wantsFocus?"red":"blue" }
+
+ FocusScope {
+ y: 100
+ focus: true
+ Rectangle { width: 50; height: 50; color: parent.wantsFocus?"red":"blue" }
+
+ FocusScope {
+ y: 100
+ focus: true
+ Rectangle { width: 50; height: 50; color: parent.wantsFocus?"red":"blue" }
+
+ FocusScope {
+ y: 100
+ focus: true
+ Rectangle { width: 50; height: 50; color: parent.wantsFocus?"red":"blue" }
+
+ FocusScope {
+ y: 100
+ focus: true
+ Rectangle { width: 50; height: 50; color: parent.wantsFocus?"red":"blue" }
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/examples/declarative/focusscope/test3.qml b/examples/declarative/focusscope/test3.qml
new file mode 100644
index 0000000..9344d07
--- /dev/null
+++ b/examples/declarative/focusscope/test3.qml
@@ -0,0 +1,52 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 800
+ height: 600
+
+ ListModel {
+ id: model
+ ListElement { name: "1" }
+ ListElement { name: "2" }
+ ListElement { name: "3" }
+ ListElement { name: "4" }
+ ListElement { name: "5" }
+ ListElement { name: "6" }
+ ListElement { name: "6" }
+ ListElement { name: "8" }
+ ListElement { name: "9" }
+ }
+
+ Component {
+ id: verticalDelegate
+ FocusScope {
+ id: root
+ width: 50; height: 50;
+ Keys.onDigit9Pressed: console.log("Error - " + name)
+ Rectangle {
+ focus: true
+ Keys.onDigit9Pressed: console.log(name)
+ width: 50; height: 50;
+ color: root.ListView.isCurrentItem?"red":"green"
+ Text { text: name; anchors.centerIn: parent }
+ }
+ }
+ }
+
+ ListView {
+ width: 800; height: 50; orientation: "Horizontal"
+ focus: true
+ model: model
+ delegate: verticalDelegate
+ preferredHighlightBegin: 100
+ preferredHighlightEnd: 100
+ highlightRangeMode: "StrictlyEnforceRange"
+ }
+
+
+ Text {
+ y: 100; x: 50
+ text: "Currently selected element should be red\nPressing \"9\" should print the number of the currently selected item\nBe sure to scroll all the way to the right, pause, and then all the way to the left."
+ }
+}
diff --git a/examples/declarative/focusscope/test4.qml b/examples/declarative/focusscope/test4.qml
new file mode 100644
index 0000000..cc96df9
--- /dev/null
+++ b/examples/declarative/focusscope/test4.qml
@@ -0,0 +1,75 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 800
+ height: 600
+
+ Keys.onDigit9Pressed: console.log("Error - Root")
+
+ FocusScope {
+ id: myScope
+
+ Keys.onDigit9Pressed: console.log("Error - FocusScope")
+
+ Rectangle {
+ height: 120
+ width: 420
+
+ color: "transparent"
+ border.width: 5
+ border.color: myScope.wantsFocus?"blue":"black"
+
+ Rectangle {
+ id: item1
+ x: 10; y: 10
+ width: 100; height: 100; color: "green"
+ border.width: 5
+ border.color: wantsFocus?"blue":"black"
+ Keys.onDigit9Pressed: console.log("Error - Top Left");
+ KeyNavigation.right: item2
+ focus: true
+
+ Rectangle {
+ width: 50; height: 50; anchors.centerIn: parent
+ color: parent.focus?"red":"transparent"
+ }
+ }
+
+ Rectangle {
+ id: item2
+ x: 310; y: 10
+ width: 100; height: 100; color: "green"
+ border.width: 5
+ border.color: wantsFocus?"blue":"black"
+ KeyNavigation.left: item1
+ Keys.onDigit9Pressed: console.log("Error - Top Right");
+
+ Rectangle {
+ width: 50; height: 50; anchors.centerIn: parent
+ color: parent.focus?"red":"transparent"
+ }
+ }
+ }
+ KeyNavigation.down: item3
+ }
+
+ Text { x:100; y:170; text: "There should be no blue borders, or red squares.\nPressing \"9\" should do nothing.\nArrow keys should have no effect." }
+
+ Rectangle {
+ id: item3
+ x: 10; y: 300
+ width: 100; height: 100; color: "green"
+ border.width: 5
+ border.color: wantsFocus?"blue":"black"
+
+ Keys.onDigit9Pressed: console.log("Error - Bottom Left");
+ KeyNavigation.up: myScope
+
+ Rectangle {
+ width: 50; height: 50; anchors.centerIn: parent
+ color: parent.focus?"red":"transparent"
+ }
+ }
+
+}
diff --git a/examples/declarative/fonts/banner.qml b/examples/declarative/fonts/banner.qml
new file mode 100644
index 0000000..00b8660
--- /dev/null
+++ b/examples/declarative/fonts/banner.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen
+ width: 640; height: 320; color: "steelblue"
+
+ property int pixelSize: screen.height * 1.25
+ property color textColor: "lightsteelblue"
+ property string text: "Hello world! "
+
+ Row {
+ y: -screen.height / 4.5
+ x: NumberAnimation { from: 0; to: -text.width; duration: 6000; repeat: true }
+ Text { id: text; font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
+ Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
+ Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
+ }
+}
diff --git a/examples/declarative/fonts/fonts.qml b/examples/declarative/fonts/fonts.qml
new file mode 100644
index 0000000..275ad43
--- /dev/null
+++ b/examples/declarative/fonts/fonts.qml
@@ -0,0 +1,69 @@
+import Qt 4.6
+
+Rectangle {
+ property string myText: "The quick brown fox jumps over the lazy dog."
+
+ width: 800; height: 480
+ color: "steelblue"
+
+ FontLoader { id: fixedFont; name: "Courier" }
+
+ FontLoader { id: localFont; source: "fonts/tarzenau-ocr-a.ttf" }
+
+ FontLoader { id: webFont; source: "http://www.princexml.com/fonts/steffmann/Starburst.ttf" }
+ FontLoader { id: webFont2; source: "http://wrong.address.org" }
+
+ Column {
+ anchors.fill: parent; spacing: 10
+ anchors.leftMargin: 10; anchors.rightMargin: 10
+ Text {
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideRight
+ font.family: "Times"; font.pointSize: 36
+ }
+ Text {
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideLeft
+ font.family: "Times"; font.pointSize: 36
+ font.capitalization: "AllUppercase"
+ }
+ Text {
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideMiddle
+ font.family: fixedFont.name; font.pointSize: 36; font.weight: "Bold"
+ font.capitalization: "AllLowercase"
+ }
+ Text {
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideRight
+ font.family: fixedFont.name; font.pointSize: 36; font.italic: true
+ font.capitalization: "SmallCaps"
+ }
+ Text {
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideLeft
+ font.family: localFont.name; font.pointSize: 36
+ font.capitalization: "Capitalize"
+ }
+ Text {
+ text: {
+ if (webFont.status == 1) myText
+ else if (webFont.status == 2) "Loading..."
+ else if (webFont.status == 3) "Error loading font"
+ }
+ color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideMiddle
+ font.family: webFont.name; font.pointSize: 36
+ }
+ Text {
+ text: {
+ if (webFont2.status == 1) myText
+ else if (webFont2.status == 2) "Loading..."
+ else if (webFont2.status == 3) "Error loading font"
+ }
+ color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideRight
+ font.family: webFont2.name; font.pointSize: 36
+ }
+ }
+}
diff --git a/examples/declarative/fonts/fonts/tarzeau_ocr_a.ttf b/examples/declarative/fonts/fonts/tarzeau_ocr_a.ttf
new file mode 100644
index 0000000..cf93f96
--- /dev/null
+++ b/examples/declarative/fonts/fonts/tarzeau_ocr_a.ttf
Binary files differ
diff --git a/examples/declarative/fonts/hello.qml b/examples/declarative/fonts/hello.qml
new file mode 100644
index 0000000..c682477
--- /dev/null
+++ b/examples/declarative/fonts/hello.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen; width: 800; height: 480; color: "black"
+
+ Item {
+ id: container; x: screen.width / 2; y: screen.height / 2
+ Text {
+ id: text; color: "white"; anchors.centerIn: parent
+ text: "Hello world!"; font.pixelSize: 60
+
+ font.letterSpacing: SequentialAnimation {
+ repeat: true;
+ NumberAnimation { from: 100; to: 300; easing: "easeInQuad"; duration: 3000 }
+ ScriptAction { script: {
+ container.y = (screen.height / 4) + (Math.random() * screen.height / 2)
+ container.x = (screen.width / 4) + (Math.random() * screen.width / 2)
+ } }
+ }
+ opacity: SequentialAnimation {
+ repeat: true;
+ NumberAnimation { from: 1; to: 0; duration: 2600 }
+ PauseAnimation { duration: 400 }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/gridview/gridview.qml b/examples/declarative/gridview/gridview.qml
new file mode 100644
index 0000000..93931c7
--- /dev/null
+++ b/examples/declarative/gridview/gridview.qml
@@ -0,0 +1,38 @@
+import Qt 4.6
+
+Rectangle {
+ width: 300; height: 400; color: "white"
+
+ ListModel {
+ id: appModel
+ ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" }
+ ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" }
+ ListElement { name: "Camera"; icon: "pics/Camera_48.png" }
+ ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" }
+ ListElement { name: "Messaging"; icon: "pics/EMail_48.png" }
+ ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" }
+ ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" }
+ }
+
+ Component {
+ id: appDelegate
+ Item {
+ width: 100; height: 100
+ Image { id: myIcon; y: 20; anchors.horizontalCenter: parent.horizontalCenter; source: icon }
+ Text { anchors.top: myIcon.bottom; anchors.horizontalCenter: parent.horizontalCenter; text: name }
+ }
+ }
+
+ Component {
+ id: appHighlight
+ Rectangle { width: 80; height: 80; color: "lightsteelblue" }
+ }
+
+ GridView {
+ anchors.fill: parent
+ cellWidth: 100; cellHeight: 100
+ model: appModel; delegate: appDelegate
+ highlight: appHighlight
+ focus: true
+ }
+}
diff --git a/examples/declarative/gridview/pics/AddressBook_48.png b/examples/declarative/gridview/pics/AddressBook_48.png
new file mode 100644
index 0000000..1ab7c8e
--- /dev/null
+++ b/examples/declarative/gridview/pics/AddressBook_48.png
Binary files differ
diff --git a/examples/declarative/gridview/pics/AudioPlayer_48.png b/examples/declarative/gridview/pics/AudioPlayer_48.png
new file mode 100644
index 0000000..f4b8689
--- /dev/null
+++ b/examples/declarative/gridview/pics/AudioPlayer_48.png
Binary files differ
diff --git a/examples/declarative/gridview/pics/Camera_48.png b/examples/declarative/gridview/pics/Camera_48.png
new file mode 100644
index 0000000..c76b524
--- /dev/null
+++ b/examples/declarative/gridview/pics/Camera_48.png
Binary files differ
diff --git a/examples/declarative/gridview/pics/DateBook_48.png b/examples/declarative/gridview/pics/DateBook_48.png
new file mode 100644
index 0000000..58f5787
--- /dev/null
+++ b/examples/declarative/gridview/pics/DateBook_48.png
Binary files differ
diff --git a/examples/declarative/gridview/pics/EMail_48.png b/examples/declarative/gridview/pics/EMail_48.png
new file mode 100644
index 0000000..d6d84a6
--- /dev/null
+++ b/examples/declarative/gridview/pics/EMail_48.png
Binary files differ
diff --git a/examples/declarative/gridview/pics/TodoList_48.png b/examples/declarative/gridview/pics/TodoList_48.png
new file mode 100644
index 0000000..0988448
--- /dev/null
+++ b/examples/declarative/gridview/pics/TodoList_48.png
Binary files differ
diff --git a/examples/declarative/gridview/pics/VideoPlayer_48.png b/examples/declarative/gridview/pics/VideoPlayer_48.png
new file mode 100644
index 0000000..52638c5
--- /dev/null
+++ b/examples/declarative/gridview/pics/VideoPlayer_48.png
Binary files differ
diff --git a/examples/declarative/layouts/Button.qml b/examples/declarative/layouts/Button.qml
new file mode 100644
index 0000000..215b536
--- /dev/null
+++ b/examples/declarative/layouts/Button.qml
@@ -0,0 +1,22 @@
+import Qt 4.6
+
+Rectangle { border.color: "black"; color: "steelblue"; radius: 5; width: pix.width + textelement.width + 13; height: pix.height + 10; id: page
+ property string text
+ property string icon
+ signal clicked
+
+ Image { id: pix; x: 5; y:5; source: parent.icon}
+ Text { id: textelement; text: page.text; color: "white"; x:pix.width+pix.x+3; anchors.verticalCenter: pix.verticalCenter;}
+ MouseRegion{ id:mr; anchors.fill: parent; onClicked: {parent.focus = true; page.clicked()}}
+
+ states:
+ State{ name:"pressed"; when:mr.pressed
+ PropertyChanges {target:textelement; x: 5}
+ PropertyChanges {target:pix; x:textelement.x+textelement.width + 3}
+ }
+
+ transitions:
+ Transition{
+ NumberAnimation { matchProperties:"x,left"; easing:"easeInOutQuad"; duration:200 }
+ }
+}
diff --git a/examples/declarative/layouts/add.png b/examples/declarative/layouts/add.png
new file mode 100644
index 0000000..f29d84b
--- /dev/null
+++ b/examples/declarative/layouts/add.png
Binary files differ
diff --git a/examples/declarative/layouts/del.png b/examples/declarative/layouts/del.png
new file mode 100644
index 0000000..1d753a3
--- /dev/null
+++ b/examples/declarative/layouts/del.png
Binary files differ
diff --git a/examples/declarative/layouts/layouts.qml b/examples/declarative/layouts/layouts.qml
new file mode 100644
index 0000000..accd969
--- /dev/null
+++ b/examples/declarative/layouts/layouts.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Item {
+ id: resizable
+ width:400
+ height:400
+
+ GraphicsObjectContainer {
+ anchors.fill:parent
+
+ QGraphicsWidget {
+ size.width:parent.width
+ size.height:parent.height
+
+ layout: QGraphicsLinearLayout {
+ LayoutItem {
+ minimumSize: "100x100"
+ maximumSize: "300x300"
+ preferredSize: "100x100"
+ Rectangle { color: "yellow"; anchors.fill: parent }
+ }
+ LayoutItem {
+ minimumSize: "100x100"
+ maximumSize: "400x400"
+ preferredSize: "200x200"
+ Rectangle { color: "green"; anchors.fill: parent }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/layouts/positioners.qml b/examples/declarative/layouts/positioners.qml
new file mode 100644
index 0000000..46762f7
--- /dev/null
+++ b/examples/declarative/layouts/positioners.qml
@@ -0,0 +1,163 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ width: 420
+ height: 420
+ color: "white"
+
+ Column {
+ id: layout1
+ y: 0
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "y"; easing: "easeOutBounce"
+ }
+ }
+ add: Transition {
+ NumberAnimation {
+ matchProperties: "y"; easing: "easeOutQuad"
+ }
+ }
+ Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueV1; color: "lightsteelblue"; width: 100; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "green"; width: 100; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueV2; color: "lightsteelblue"; width: 100; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "orange"; width: 100; height: 50; border.color: "black"; radius: 15 }
+ }
+
+ Row {
+ id: layout2
+ y: 300
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x"; easing: "easeOutBounce"
+ }
+ }
+ add: Transition {
+ NumberAnimation {
+ matchProperties: "x"; easing: "easeOutQuad"
+ }
+ }
+ Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 }
+ Rectangle { id: blueH1; color: "lightsteelblue"; width: 50; height: 100; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "green"; width: 50; height: 100; border.color: "black"; radius: 15 }
+ Rectangle { id: blueH2; color: "lightsteelblue"; width: 50; height: 100; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "orange"; width: 50; height: 100; border.color: "black"; radius: 15 }
+ }
+
+ Button {
+ text: "Remove"
+ icon: "del.png"
+ x: 135
+ y: 90
+
+ onClicked: {
+ blueH2.opacity = 0
+ blueH1.opacity = 0
+ blueV1.opacity = 0
+ blueV2.opacity = 0
+ blueG1.opacity = 0
+ blueG2.opacity = 0
+ blueG3.opacity = 0
+ blueF1.opacity = 0
+ blueF2.opacity = 0
+ blueF3.opacity = 0
+ }
+ }
+
+ Button {
+ text: "Add"
+ icon: "add.png"
+ x: 145
+ y: 140
+
+ onClicked: {
+ blueH2.opacity = 1
+ blueH1.opacity = 1
+ blueV1.opacity = 1
+ blueV2.opacity = 1
+ blueG1.opacity = 1
+ blueG2.opacity = 1
+ blueG3.opacity = 1
+ blueF1.opacity = 1
+ blueF2.opacity = 1
+ blueF3.opacity = 1
+ }
+ }
+
+ Grid {
+ x: 260
+ y: 0
+ columns: 3
+
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x,y"; easing: "easeOutBounce"
+ }
+ }
+
+ add: Transition {
+ NumberAnimation {
+ matchProperties: "x,y"; easing: "easeOutBounce"
+ }
+ }
+
+ Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueG1; color: "lightsteelblue"; width: 50; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueG2; color: "lightsteelblue"; width: 50; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueG3; color: "lightsteelblue"; width: 50; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ }
+
+ Flow {
+ id: layout4
+ x: 260
+ y: 250
+ width: 150
+
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x,y"; easing: "easeOutBounce"
+ }
+ }
+
+ add: Transition {
+ NumberAnimation {
+ matchProperties: "x,y"; easing: "easeOutBounce"
+ }
+ }
+ Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueF1; color: "lightsteelblue"; width: 60; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "green"; width: 30; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueF2; color: "lightsteelblue"; width: 60; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 }
+ Rectangle { id: blueF3; color: "lightsteelblue"; width: 40; height: 50; border.color: "black"; radius: 15
+ opacity: Behavior{NumberAnimation{}}
+ }
+ Rectangle { color: "red"; width: 80; height: 50; border.color: "black"; radius: 15 }
+ }
+
+}
diff --git a/examples/declarative/listview/content/ClickAutoRepeating.qml b/examples/declarative/listview/content/ClickAutoRepeating.qml
new file mode 100644
index 0000000..796f9e3
--- /dev/null
+++ b/examples/declarative/listview/content/ClickAutoRepeating.qml
@@ -0,0 +1,30 @@
+import Qt 4.6
+
+Item {
+ id: page
+ property int repeatdelay: 300
+ property int repeatperiod: 75
+ property bool isPressed: false
+
+ signal pressed
+ signal released
+ signal clicked
+
+ isPressed: SequentialAnimation {
+ id: autoRepeat
+ PropertyAction { target: page; property: "isPressed"; value: true }
+ ScriptAction { script: page.pressed() }
+ ScriptAction { script: page.clicked() }
+ PauseAnimation { duration: repeatdelay }
+ SequentialAnimation {
+ repeat: true
+ ScriptAction { script: page.clicked() }
+ PauseAnimation { duration: repeatperiod }
+ }
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onPressed: autoRepeat.start()
+ onReleased: { autoRepeat.stop(); parent.isPressed = false; page.released() }
+ }
+}
diff --git a/examples/declarative/listview/content/MediaButton.qml b/examples/declarative/listview/content/MediaButton.qml
new file mode 100644
index 0000000..1c88844
--- /dev/null
+++ b/examples/declarative/listview/content/MediaButton.qml
@@ -0,0 +1,35 @@
+import Qt 4.6
+
+Item {
+ property var text
+ signal clicked
+
+ id: container
+ Image {
+ id: normal
+ source: "pics/button.png"
+ }
+ Image {
+ id: pressed
+ source: "pics/button-pressed.png"
+ opacity: 0
+ }
+ MouseRegion {
+ id: clickRegion
+ anchors.fill: normal
+ onClicked: { container.clicked(); }
+ }
+ Text {
+ font.bold: true
+ color: "white"
+ anchors.centerIn: normal
+ text: container.text
+ }
+ width: normal.width
+
+ states: State {
+ name: "Pressed"
+ when: clickRegion.pressed == true
+ PropertyChanges { target: pressed; opacity: 1 }
+ }
+}
diff --git a/examples/declarative/listview/content/pics/add.png b/examples/declarative/listview/content/pics/add.png
new file mode 100644
index 0000000..f29d84b
--- /dev/null
+++ b/examples/declarative/listview/content/pics/add.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/archive-insert.png b/examples/declarative/listview/content/pics/archive-insert.png
new file mode 100644
index 0000000..b706248
--- /dev/null
+++ b/examples/declarative/listview/content/pics/archive-insert.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/archive-remove.png b/examples/declarative/listview/content/pics/archive-remove.png
new file mode 100644
index 0000000..9640f6b
--- /dev/null
+++ b/examples/declarative/listview/content/pics/archive-remove.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/button-pressed.png b/examples/declarative/listview/content/pics/button-pressed.png
new file mode 100644
index 0000000..e434d32
--- /dev/null
+++ b/examples/declarative/listview/content/pics/button-pressed.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/button.png b/examples/declarative/listview/content/pics/button.png
new file mode 100644
index 0000000..56a63ce
--- /dev/null
+++ b/examples/declarative/listview/content/pics/button.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/del.png b/examples/declarative/listview/content/pics/del.png
new file mode 100644
index 0000000..1d753a3
--- /dev/null
+++ b/examples/declarative/listview/content/pics/del.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/fruit-salad.jpg b/examples/declarative/listview/content/pics/fruit-salad.jpg
new file mode 100644
index 0000000..da5a6b1
--- /dev/null
+++ b/examples/declarative/listview/content/pics/fruit-salad.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/go-down.png b/examples/declarative/listview/content/pics/go-down.png
new file mode 100644
index 0000000..63331a5
--- /dev/null
+++ b/examples/declarative/listview/content/pics/go-down.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/go-up.png b/examples/declarative/listview/content/pics/go-up.png
new file mode 100644
index 0000000..4459024
--- /dev/null
+++ b/examples/declarative/listview/content/pics/go-up.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/hamburger.jpg b/examples/declarative/listview/content/pics/hamburger.jpg
new file mode 100644
index 0000000..d0a15be
--- /dev/null
+++ b/examples/declarative/listview/content/pics/hamburger.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/lemonade.jpg b/examples/declarative/listview/content/pics/lemonade.jpg
new file mode 100644
index 0000000..db445c9
--- /dev/null
+++ b/examples/declarative/listview/content/pics/lemonade.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/list-add.png b/examples/declarative/listview/content/pics/list-add.png
new file mode 100644
index 0000000..e029787
--- /dev/null
+++ b/examples/declarative/listview/content/pics/list-add.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/list-remove.png b/examples/declarative/listview/content/pics/list-remove.png
new file mode 100644
index 0000000..2bb1a59
--- /dev/null
+++ b/examples/declarative/listview/content/pics/list-remove.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/moreDown.png b/examples/declarative/listview/content/pics/moreDown.png
new file mode 100644
index 0000000..31a35d5
--- /dev/null
+++ b/examples/declarative/listview/content/pics/moreDown.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/moreUp.png b/examples/declarative/listview/content/pics/moreUp.png
new file mode 100644
index 0000000..fefb9c9
--- /dev/null
+++ b/examples/declarative/listview/content/pics/moreUp.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/pancakes.jpg b/examples/declarative/listview/content/pics/pancakes.jpg
new file mode 100644
index 0000000..60c4396
--- /dev/null
+++ b/examples/declarative/listview/content/pics/pancakes.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/trash.png b/examples/declarative/listview/content/pics/trash.png
new file mode 100644
index 0000000..2042595
--- /dev/null
+++ b/examples/declarative/listview/content/pics/trash.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/vegetable-soup.jpg b/examples/declarative/listview/content/pics/vegetable-soup.jpg
new file mode 100644
index 0000000..9dce332
--- /dev/null
+++ b/examples/declarative/listview/content/pics/vegetable-soup.jpg
Binary files differ
diff --git a/examples/declarative/listview/dummydata/MyPetsModel.qml b/examples/declarative/listview/dummydata/MyPetsModel.qml
new file mode 100644
index 0000000..1ac37bb
--- /dev/null
+++ b/examples/declarative/listview/dummydata/MyPetsModel.qml
@@ -0,0 +1,61 @@
+import Qt 4.6
+
+// ListModel allows free form list models to be defined and populated.
+
+ListModel {
+ id: petsModel
+ ListElement {
+ name: "Polly"
+ type: "Parrot"
+ age: 12
+ size: "Small"
+ }
+ ListElement {
+ name: "Penny"
+ type: "Turtle"
+ age: 4
+ size: "Small"
+ }
+ ListElement {
+ name: "Warren"
+ type: "Rabbit"
+ age: 2
+ size: "Small"
+ }
+ ListElement {
+ name: "Spot"
+ type: "Dog"
+ age: 9
+ size: "Medium"
+ }
+ ListElement {
+ name: "Schrödinger"
+ type: "Cat"
+ age: 2
+ size: "Medium"
+ }
+ ListElement {
+ name: "Joey"
+ type: "Kangaroo"
+ age: 1
+ size: "Medium"
+ }
+ ListElement {
+ name: "Kimba"
+ type: "Bunny"
+ age: 65
+ size: "Large"
+ }
+ ListElement {
+ name: "Rover"
+ type: "Dog"
+ age: 5
+ size: "Large"
+ }
+ ListElement {
+ name: "Tiny"
+ type: "Elephant"
+ age: 15
+ size: "Large"
+ }
+}
diff --git a/examples/declarative/listview/dummydata/Recipes.qml b/examples/declarative/listview/dummydata/Recipes.qml
new file mode 100644
index 0000000..68e94ac
--- /dev/null
+++ b/examples/declarative/listview/dummydata/Recipes.qml
@@ -0,0 +1,90 @@
+import Qt 4.6
+
+ListModel {
+ id: recipesModel
+ ListElement {
+ title: "Pancakes"
+ picture: "content/pics/pancakes.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 1 cup (150g) self-raising flour
+ <li> 1 tbs caster sugar
+ <li> 3/4 cup (185ml) milk
+ <li> 1 egg
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
+ <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
+ <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
+ <li> Turn over and cook other side until golden.
+ </ol>
+ </html>"
+ }
+ ListElement {
+ title: "Fruit Salad"
+ picture: "content/pics/fruit-salad.jpg"
+ ingredients: "* Seasonal Fruit"
+ method: "* Chop fruit and place in a bowl."
+ }
+ ListElement {
+ title: "Vegetable Soup"
+ picture: "content/pics/vegetable-soup.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 1 onion
+ <li> 1 turnip
+ <li> 1 potato
+ <li> 1 carrot
+ <li> 1 head of celery
+ <li> 1 1/2 litres of water
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Chop vegetables.
+ <li> Boil in water until vegetables soften.
+ <li> Season with salt and pepper to taste.
+ </ol>
+ </html>"
+ }
+ ListElement {
+ title: "Hamburger"
+ picture: "content/pics/hamburger.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 500g minced beef
+ <li> Seasoning
+ <li> lettuce, tomato, onion, cheese
+ <li> 1 hamburger bun for each burger
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Mix the beef, together with seasoning, in a food processor.
+ <li> Shape the beef into burgers.
+ <li> Grill the burgers for about 5 mins on each side (until cooked through)
+ <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
+ </ol>
+ </html>"
+ }
+ ListElement {
+ title: "Lemonade"
+ picture: "content/pics/lemonade.jpg"
+ ingredients: "<html>
+ <ul>
+ <li> 1 cup Lemon Juice
+ <li> 1 cup Sugar
+ <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
+ </ul>
+ </html>"
+ method: "<html>
+ <ol>
+ <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
+ <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
+ <li> Chill or serve over ice cubes.
+ </ol>
+ </html>"
+ }
+}
diff --git a/examples/declarative/listview/dynamic.qml b/examples/declarative/listview/dynamic.qml
new file mode 100644
index 0000000..101b708
--- /dev/null
+++ b/examples/declarative/listview/dynamic.qml
@@ -0,0 +1,160 @@
+import Qt 4.6
+import "content"
+import "../scrollbar"
+
+Rectangle {
+ width: 640; height: 480
+ color: "#343434"
+
+ ListModel {
+ id: fruitModel
+ ListElement {
+ name: "Apple"; cost: 2.45
+ attributes: [
+ ListElement { description: "Core" },
+ ListElement { description: "Deciduous" }
+ ]
+ }
+ ListElement {
+ name: "Banana"; cost: 1.95
+ attributes: [
+ ListElement { description: "Tropical" },
+ ListElement { description: "Seedless" }
+ ]
+ }
+ ListElement {
+ name: "Cumquat"; cost: 3.25
+ types: [ "Small", "Smaller" ]
+ attributes: [
+ ListElement { description: "Citrus" }
+ ]
+ }
+ ListElement {
+ name: "Durian"; cost: 9.95
+ attributes: [
+ ListElement { description: "Tropical" },
+ ListElement { description: "Smelly" }
+ ]
+ }
+ ListElement {
+ name: "Elderberry"; cost: 0.05
+ attributes: [
+ ListElement { description: "Berry" }
+ ]
+ }
+ ListElement {
+ name: "Fig"; cost: 0.25
+ attributes: [
+ ListElement { description: "Flower" }
+ ]
+ }
+ }
+
+ Component {
+ id: fruitDelegate
+ Item {
+ width: parent.width; height: 55
+
+ Column {
+ id: moveButtons; x: 5; width: childrenRect.width; anchors.verticalCenter: parent.verticalCenter
+ Image { source: "content/pics/go-up.png"
+ MouseRegion { anchors.fill: parent; onClicked: fruitModel.move(index,index-1,1) }
+ }
+ Image { source: "content/pics/go-down.png"
+ MouseRegion { anchors.fill: parent; onClicked: fruitModel.move(index,index+1,1) }
+ }
+ }
+
+ Column {
+ anchors { right: itemButtons.left; verticalCenter: parent.verticalCenter; left: moveButtons.right; leftMargin: 10 }
+ Text {
+ id: label; font.bold: true; text: name; elide: Text.ElideRight; font.pixelSize: 15
+ width: parent.width; color: "White"
+ }
+ Row {
+ spacing: 5
+ Repeater { model: attributes; Component { Text { text: description; color: "White" } } }
+ }
+ }
+
+ Row {
+ id: itemButtons
+ anchors.right: removeButton.left; anchors.rightMargin: 35; spacing: 10
+ width: childrenRect.width; anchors.verticalCenter: parent.verticalCenter
+ Image { source: "content/pics/list-add.png"
+ ClickAutoRepeating { id: clickUp; anchors.fill: parent; onClicked: fruitModel.set(index,"cost",Number(cost)+0.25) }
+ scale: clickUp.isPressed ? 0.9 : 1; transformOrigin: Item.Center
+ }
+ Text { id: costText; text: '$'+Number(cost).toFixed(2); font.pixelSize: 15; color: "White"; font.bold: true; }
+ Image { source: "content/pics/list-remove.png"
+ ClickAutoRepeating { id: clickDown; anchors.fill: parent; onClicked: fruitModel.set(index,"cost",Math.max(0,Number(cost)-0.25)) }
+ scale: clickDown.isPressed ? 0.9 : 1; transformOrigin: Item.Center
+ }
+ }
+ Image {
+ id: removeButton; source: "content/pics/archive-remove.png"
+ anchors { verticalCenter: parent.verticalCenter; right: parent.right; rightMargin: 10 }
+ MouseRegion { anchors.fill:parent; onClicked: fruitModel.remove(index) }
+ }
+ }
+ }
+
+ ListView {
+ id: view
+ model: fruitModel; delegate: fruitDelegate
+ anchors { top: parent.top; left: parent.left; right: parent.right; bottom: buttons.top }
+ }
+
+ // Attach scrollbar to the right edge of the view.
+ ScrollBar {
+ id: verticalScrollBar
+ opacity: 0
+ orientation: "Vertical"
+ position: view.visibleArea.yPosition
+ pageSize: view.visibleArea.heightRatio
+ width: 8
+ height: view.height
+ anchors.right: view.right
+ // Only show the scrollbar when the view is moving.
+ states: [
+ State {
+ name: "ShowBars"; when: view.moving
+ PropertyChanges { target: verticalScrollBar; opacity: 1 }
+ }
+ ]
+ transitions: [ Transition { NumberAnimation { matchProperties: "opacity"; duration: 400 } } ]
+ }
+
+ Row {
+ x: 8; width: childrenRect.width
+ height: childrenRect.height
+ anchors { bottom: parent.bottom; bottomMargin: 8 }
+ spacing: 8
+ id: buttons
+ Image { source: "content/pics/archive-insert.png"
+ MouseRegion { anchors.fill: parent;
+ onClicked: {
+ fruitModel.append({
+ "name":"Pizza Margarita",
+ "cost":5.95,
+ "attributes":[{"description": "Cheese"},{"description": "Tomato"}]
+ })
+ }
+ }
+ }
+ Image { source: "content/pics/archive-insert.png"
+ MouseRegion { anchors.fill: parent;
+ onClicked: {
+ fruitModel.insert(0,{
+ "name":"Pizza Supreme",
+ "cost":9.95,
+ "attributes":[{"description": "Cheese"},{"description": "Tomato"},{"description": "The Works"}]
+ })
+ }
+ }
+ }
+ Image { source: "content/pics/archive-remove.png"
+ MouseRegion { anchors.fill: parent; onClicked: fruitModel.clear() }
+ }
+ }
+}
diff --git a/examples/declarative/listview/highlight.qml b/examples/declarative/listview/highlight.qml
new file mode 100644
index 0000000..9665499
--- /dev/null
+++ b/examples/declarative/listview/highlight.qml
@@ -0,0 +1,57 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 300; color: "white"
+
+ // MyPets model is defined in dummydata/MyPetsModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+ // This one contains my pets.
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+ Component {
+ id: petDelegate
+ Item {
+ id: wrapper
+ width: 200; height: 50
+ Column {
+ Text { text: 'Name: ' + name }
+ Text { text: 'Type: ' + type }
+ Text { text: 'Age: ' + age }
+ }
+ // Use the ListView.isCurrentItem attached property to
+ // indent the item if it is the current item.
+ states: [
+ State {
+ name: "Current"
+ when: wrapper.ListView.isCurrentItem
+ PropertyChanges { target: wrapper; x: 10 }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation {
+ matchProperties: "x"; duration: 200
+ }
+ }
+ ]
+ }
+ }
+ // Specify a highlight with custom movement. Note that highlightFollowsCurrentItem
+ // is set to false in the ListView so that we can control how the
+ // highlight moves to the current item.
+ Component {
+ id: petHighlight
+ Rectangle {
+ width: 200; height: 50; color: "#FFFF88"
+ y: SpringFollow { source: list1.currentItem.y; spring: 3; damping: 0.1 }
+ }
+ }
+ ListView {
+ id: list1
+ width: 200; height: parent.height
+ model: MyPetsModel; delegate: petDelegate
+ highlight: petHighlight; highlightFollowsCurrentItem: false
+ focus: true
+ }
+}
diff --git a/examples/declarative/listview/itemlist.qml b/examples/declarative/listview/itemlist.qml
new file mode 100644
index 0000000..6392153
--- /dev/null
+++ b/examples/declarative/listview/itemlist.qml
@@ -0,0 +1,60 @@
+// This example demonstrates placing items in a view using
+// a VisualItemModel
+
+import Qt 4.6
+
+Rectangle {
+ color: "lightgray"
+ width: 240
+ height: 320
+
+ VisualItemModel {
+ id: itemModel
+ Rectangle {
+ height: view.height; width: view.width; color: "#FFFEF0"
+ Text { text: "Page 1"; font.bold: true; anchors.centerIn: parent }
+ }
+ Rectangle {
+ height: view.height; width: view.width; color: "#F0FFF7"
+ Text { text: "Page 2"; font.bold: true; anchors.centerIn: parent }
+ }
+ Rectangle {
+ height: view.height; width: view.width; color: "#F4F0FF"
+ Text { text: "Page 3"; font.bold: true; anchors.centerIn: parent }
+ }
+ }
+
+ ListView {
+ id: view
+ anchors.fill: parent
+ anchors.bottomMargin: 30
+ model: itemModel
+ preferredHighlightBegin: 0
+ preferredHighlightEnd: 0
+ highlightRangeMode: "StrictlyEnforceRange"
+ orientation: ListView.Horizontal
+ flickDeceleration: 2000
+ }
+
+ Rectangle {
+ color: "gray"
+ anchors.top: view.bottom
+ anchors.bottom: parent.bottom
+ height: 30
+ width: 240
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 20
+ Repeater {
+ model: itemModel.count
+ Rectangle {
+ width: 5; height: 5
+ radius: 3
+ MouseRegion { width: 20; height: 20; anchors.centerIn: parent; onClicked: view.currentIndex = index }
+ color: view.currentIndex == index ? "blue" : "white"
+ }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/listview/listview.qml b/examples/declarative/listview/listview.qml
new file mode 100644
index 0000000..92acce1
--- /dev/null
+++ b/examples/declarative/listview/listview.qml
@@ -0,0 +1,77 @@
+import Qt 4.6
+
+Rectangle {
+ width: 600; height: 300; color: "white"
+
+ // MyPets model is defined in dummydata/MyPetsModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+ // This one contains my pets.
+ // Define a delegate component. A component will be
+ // instantiated for each visible item in the list.
+ Component {
+ id: petDelegate
+ Item {
+ width: 200; height: 50
+ Column {
+ Text { text: 'Name: ' + name }
+ Text { text: 'Type: ' + type }
+ Text { text: 'Age: ' + age }
+ }
+ }
+ }
+
+ // Define a highlight component. Just one of these will be instantiated
+ // by each ListView and placed behind the current item.
+ Component {
+ id: petHighlight
+ Rectangle { color: "#FFFF88" }
+ }
+
+ // Show the model in three lists, with different highlight ranges.
+ // preferredHighlightBegin and preferredHighlightEnd set the
+ // range in which to attempt to maintain the highlight.
+ // Note that the second and third ListView
+ // set their currentIndex to be the same as the first, and that
+ // the first ListView is given keyboard focus.
+ // The default mode allows the currentItem to move freely
+ // within the visible area. If it would move outside the visible
+ // area, the view is scrolled to keep it visible.
+ // The second list sets a highlight range which attempts to keep the
+ // current item within the the bounds of the range, however
+ // items will not scroll beyond the beginning or end of the view,
+ // forcing the highlight to move outside the range at the ends.
+ // The third list sets the highlightRangeMode to StrictlyEnforceRange
+ // and sets a range smaller than the height of an item. This
+ // forces the current item to change when the view is flicked,
+ // since the highlight is unable to move.
+ // Note that the first ListView sets its currentIndex to be equal to
+ // the third ListView's currentIndex. By flicking List3 with
+ // the mouse, the current index of List1 will be changed.
+ ListView {
+ id: list1
+ width: 200; height: parent.height
+ model: MyPetsModel; delegate: petDelegate
+ highlight: petHighlight; currentIndex: list3.currentIndex
+ focus: true
+ }
+ ListView {
+ id: list2
+ x: 200; width: 200; height: parent.height
+ model: MyPetsModel; delegate: petDelegate; highlight: petHighlight
+ preferredHighlightBegin: 80
+ preferredHighlightEnd: 220
+ highlightRangeMode: "ApplyRange"
+ currentIndex: list1.currentIndex
+ }
+ ListView {
+ id: list3
+ x: 400; width: 200; height: parent.height
+ model: MyPetsModel; delegate: petDelegate; highlight: petHighlight
+ currentIndex: list1.currentIndex
+ preferredHighlightBegin: 125
+ preferredHighlightEnd: 125
+ highlightRangeMode: "StrictlyEnforceRange"
+ flickDeceleration: 1000
+ }
+}
diff --git a/examples/declarative/listview/recipes.qml b/examples/declarative/listview/recipes.qml
new file mode 100644
index 0000000..c133351
--- /dev/null
+++ b/examples/declarative/listview/recipes.qml
@@ -0,0 +1,140 @@
+import Qt 4.6
+import "content"
+
+// This example illustrates expanding a list item to show a more detailed view
+
+Rectangle {
+ id: page
+ width: 400; height: 240; color: "black"
+
+ // Delegate for the recipes. This delegate has two modes:
+ // 1. the list mode (default), which just shows the picture and title of the recipe.
+ // 2. the details mode, which also shows the ingredients and method.
+ Component {
+ id: recipeDelegate
+ Item {
+ id: wrapper
+ width: list.width
+
+ // Create a property to contain the visibility of the details.
+ // We can bind multiple element's opacity to this one property,
+ // rather than having a "PropertyChanges" line for each element we
+ // want to fade.
+ property real detailsOpacity : 0
+
+ // A simple rounded rectangle for the background
+ Rectangle {
+ id: background
+ x: 1; y: 2; width: parent.width - 2; height: parent.height - 4
+ color: "#FEFFEE"; border.color: "#FFBE4F"; radius: 5
+ }
+
+ // This mouse region covers the entire delegate.
+ // When clicked it changes mode to 'Details'. If we are already
+ // in Details mode, then no change will happen.
+ MouseRegion {
+ id: pageMouse
+ anchors.fill: parent
+ onClicked: wrapper.state = 'Details';
+ }
+
+ // Layout the page. Picture, title and ingredients at the top, method at the
+ // bottom. Note that elements that should not be visible in the list
+ // mode have their opacity set to wrapper.detailsOpacity.
+ Row {
+ id: topLayout
+ x: 10; y: 10; height: recipePic.height; width: parent.width
+ spacing: 10
+
+ Image {
+ id: recipePic
+ source: picture; width: 48; height: 48
+ }
+
+ Column {
+ height: recipePic.height; width: background.width-recipePic.width-20
+ spacing: 5
+ Text { id: name; text: title; font.bold: true; font.pointSize: 16 }
+ Text {
+ text: "Ingredients"; font.pointSize: 12; font.bold: true
+ opacity: wrapper.detailsOpacity
+ }
+ Text {
+ text: ingredients; wrap: true; width: parent.width
+ opacity: wrapper.detailsOpacity
+ }
+ }
+ }
+
+ Item {
+ id: details
+ x: 10; width: parent.width-20
+ anchors.top: topLayout.bottom; anchors.topMargin: 10
+ anchors.bottom: parent.bottom; anchors.bottomMargin: 10
+ opacity: wrapper.detailsOpacity
+
+ Text {
+ id: methodTitle
+ text: "Method"; font.pointSize: 12; font.bold: true
+ anchors.top: parent.top
+ }
+ Flickable {
+ id: flick
+ anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom
+ width: parent.width; viewportHeight: methodText.height; clip: true
+ Text { id: methodText; text: method; wrap: true; width: details.width }
+ }
+ Image {
+ anchors.right: flick.right; anchors.top: flick.top
+ source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1
+ }
+ Image {
+ anchors.right: flick.right; anchors.bottom: flick.bottom
+ source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1
+ }
+ }
+
+ // A button to close the detailed view, i.e. set the state back to default ('').
+ MediaButton {
+ anchors.right: background.right; anchors.rightMargin: 5
+ y: 10; opacity: wrapper.detailsOpacity
+ text: "Close"; onClicked: wrapper.state = '';
+ }
+
+ // Make the default height equal the hight of the picture, plus margin.
+ height: 68
+
+ states: State {
+ name: "Details"
+ PropertyChanges { target: background; color: "white" }
+ // Make the picture bigger
+ PropertyChanges { target: recipePic; width: 128; height: 128 }
+ // Make details visible
+ PropertyChanges { target: wrapper; detailsOpacity: 1; x: 0 }
+ // Make the detailed view fill the entire list area
+ PropertyChanges { target: wrapper; height: list.height }
+ // Move the list so that this item is at the top.
+ PropertyChanges { target: wrapper.ListView.view; explicit: true; viewportY: wrapper.y }
+ // Disallow flicking while we're in detailed view
+ PropertyChanges { target: wrapper.ListView.view; interactive: false }
+ }
+
+ transitions: Transition {
+ // Make the state changes smooth
+ ParallelAnimation {
+ ColorAnimation { property: "color"; duration: 500 }
+ NumberAnimation {
+ duration: 300; matchProperties: "detailsOpacity,x,viewportY,height,width"
+ }
+ }
+ }
+ }
+ }
+
+ // The actual list
+ ListView {
+ id: list
+ model: Recipes; delegate: recipeDelegate
+ anchors.fill: parent; clip: true
+ }
+}
diff --git a/examples/declarative/listview/sections.qml b/examples/declarative/listview/sections.qml
new file mode 100644
index 0000000..877026b
--- /dev/null
+++ b/examples/declarative/listview/sections.qml
@@ -0,0 +1,67 @@
+import Qt 4.6
+
+//! [0]
+Rectangle {
+ width: 200
+ height: 240
+ color: "white"
+ // MyPets model is defined in dummydata/MyPetsModel.qml
+ // The viewer automatically loads files in dummydata/* to assist
+ // development without a real data source.
+ // This one contains my pets.
+
+ // Define a delegate component that includes a separator for sections.
+ Component {
+ id: petDelegate
+ Item {
+ id: wrapper
+ width: 200
+ // My height is the combined height of the description and the section separator
+ height: desc.height
+ Item {
+ id: desc
+ x: 5
+ height: layout.height + 4
+ Column {
+ id: layout
+ y: 2
+ Text { text: 'Name: ' + name }
+ Text { text: 'Type: ' + type }
+ Text { text: 'Age: ' + age }
+ }
+ }
+ }
+ }
+ // Define a highlight component. Just one of these will be instantiated
+ // by each ListView and placed behind the current item.
+ Component {
+ id: petHighlight
+ Rectangle {
+ color: "#FFFF88"
+ }
+ }
+ // The list
+ ListView {
+ id: myList
+ width: 200
+ height: parent.height
+ model: MyPetsModel
+ delegate: petDelegate
+ highlight: petHighlight
+ // The sectionExpression is simply the size of the pet.
+ // We use this to determine which section we are in above.
+ section.property: "size"
+ section.criteria: ViewSection.FullString
+ section.delegate: Rectangle {
+ color: "lightsteelblue"
+ width: 200
+ height: 20
+ Text {
+ text: section; font.bold: true
+ x: 2; height: parent.height; verticalAlignment: 'AlignVCenter'
+ }
+ }
+ focus: true
+ }
+}
+//! [0]
diff --git a/examples/declarative/mouseregion/mouse.qml b/examples/declarative/mouseregion/mouse.qml
new file mode 100644
index 0000000..d07d471
--- /dev/null
+++ b/examples/declarative/mouseregion/mouse.qml
@@ -0,0 +1,40 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 200; height: 200
+ Rectangle {
+ width: 50; height: 50
+ color: "red"
+ Text { text: "Click"; anchors.centerIn: parent }
+ MouseRegion {
+ hoverEnabled: true
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onPressed: { console.log('press (x: ' + mouse.x + ' y: ' + mouse.y + ' button: ' + (mouse.button == Qt.RightButton ? 'right' : 'left') + ' Shift: ' + (mouse.modifiers & Qt.ShiftModifier ? 'true' : 'false') + ')') }
+ onReleased: { console.log('release (x: ' + mouse.x + ' y: ' + mouse.y + ' isClick: ' + mouse.isClick + ' wasHeld: ' + mouse.wasHeld + ')') }
+ onClicked: { console.log('click (x: ' + mouse.x + ' y: ' + mouse.y + ' wasHeld: ' + mouse.wasHeld + ')') }
+ onDoubleClicked: { console.log('double click (x: ' + mouse.x + ' y: ' + mouse.y + ')') }
+ onPressAndHold: { console.log('press and hold') }
+ onEntered: { console.log('entered ' + pressed) }
+ onExited: { console.log('exited ' + pressed) }
+ anchors.fill: parent
+ }
+ }
+ Rectangle {
+ y: 100; width: 50; height: 50
+ color: "blue"
+ Text { text: "Drag"; anchors.centerIn: parent }
+ MouseRegion {
+ drag.target: parent
+ drag.axis: "XAxis"
+ drag.minimumX: 0
+ drag.maximumX: 150
+ onPressed: { console.log('press') }
+ onReleased: { console.log('release (isClick: ' + mouse.isClick + ') (wasHeld: ' + mouse.wasHeld + ')') }
+ onClicked: { console.log('click' + '(wasHeld: ' + mouse.wasHeld + ')') }
+ onDoubleClicked: { console.log('double click') }
+ onPressAndHold: { console.log('press and hold') }
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/examples/declarative/objectlistmodel/dataobject.cpp b/examples/declarative/objectlistmodel/dataobject.cpp
new file mode 100644
index 0000000..da85fe2
--- /dev/null
+++ b/examples/declarative/objectlistmodel/dataobject.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include "dataobject.h"
+
+DataObject::DataObject(QObject *parent)
+ : QObject(parent)
+{
+}
+
+DataObject::DataObject(const QString &name, const QString &color, QObject *parent)
+ : QObject(parent), m_name(name), m_color(color)
+{
+}
+
+QString DataObject::name() const
+{
+ return m_name;
+}
+
+void DataObject::setName(const QString &name)
+{
+ m_name = name;
+}
+
+QString DataObject::color() const
+{
+ return m_color;
+}
+
+void DataObject::setColor(const QString &color)
+{
+ m_color = color;
+}
diff --git a/examples/declarative/objectlistmodel/dataobject.h b/examples/declarative/objectlistmodel/dataobject.h
new file mode 100644
index 0000000..c0aa159
--- /dev/null
+++ b/examples/declarative/objectlistmodel/dataobject.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DATAOBJECT_H
+#define DATAOBJECT_H
+
+#include <QObject>
+
+class DataObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString color READ color WRITE setColor)
+
+public:
+ DataObject(QObject *parent=0);
+ DataObject(const QString &name, const QString &color, QObject *parent=0);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString color() const;
+ void setColor(const QString &color);
+
+private:
+ QString m_name;
+ QString m_color;
+};
+
+#endif // DATAOBJECT_H
diff --git a/examples/declarative/objectlistmodel/main.cpp b/examples/declarative/objectlistmodel/main.cpp
new file mode 100644
index 0000000..3f2ac6d
--- /dev/null
+++ b/examples/declarative/objectlistmodel/main.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qml.h>
+#include <qmlgraphicsitem.h>
+#include <qmlview.h>
+
+#include "dataobject.h"
+
+/*
+ This example illustrates exposing a QList<QObject*> as a
+ model in QML
+*/
+
+int main(int argc, char ** argv)
+{
+ QApplication app(argc, argv);
+
+ QmlView view;
+ view.setUrl(QUrl("qrc:view.qml"));
+
+ QList<QObject*> dataList;
+ dataList.append(new DataObject("Item 1", "red"));
+ dataList.append(new DataObject("Item 2", "green"));
+ dataList.append(new DataObject("Item 3", "blue"));
+ dataList.append(new DataObject("Item 4", "yellow"));
+
+ QmlContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", QVariant::fromValue(&dataList));
+
+ view.execute();
+ view.show();
+
+ return app.exec();
+}
+
diff --git a/examples/declarative/objectlistmodel/objectlistmodel.pro b/examples/declarative/objectlistmodel/objectlistmodel.pro
new file mode 100644
index 0000000..ca61e4c
--- /dev/null
+++ b/examples/declarative/objectlistmodel/objectlistmodel.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = objectlistmodel
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += declarative
+
+# Input
+SOURCES += main.cpp \
+ dataobject.cpp
+HEADERS += dataobject.h
+RESOURCES += objectlistmodel.qrc
diff --git a/examples/declarative/objectlistmodel/objectlistmodel.qrc b/examples/declarative/objectlistmodel/objectlistmodel.qrc
new file mode 100644
index 0000000..17e9301
--- /dev/null
+++ b/examples/declarative/objectlistmodel/objectlistmodel.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>view.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/declarative/objectlistmodel/view.qml b/examples/declarative/objectlistmodel/view.qml
new file mode 100644
index 0000000..5f5e415
--- /dev/null
+++ b/examples/declarative/objectlistmodel/view.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+ListView {
+ width: 100
+ height: 100
+ anchors.fill: parent
+ model: myModel
+ delegate: Component {
+ Rectangle {
+ height: 25
+ width: 100
+ color: model.color
+ Text { text: name }
+ }
+ }
+}
diff --git a/examples/declarative/parallax/parallax.qml b/examples/declarative/parallax/parallax.qml
new file mode 100644
index 0000000..6193f27
--- /dev/null
+++ b/examples/declarative/parallax/parallax.qml
@@ -0,0 +1,41 @@
+import Qt 4.6
+import "../clocks/content"
+import "qml"
+
+Rectangle {
+ id: root
+
+ width: 320; height: 480
+
+ ParallaxView {
+ id: parallax
+ anchors.fill: parent
+ background: "pics/background.jpg"
+
+ Item {
+ property url icon: "pics/yast-wol.png"
+ width: 320; height: 480
+ Clock { anchors.centerIn: parent }
+ }
+
+ Item {
+ property url icon: "pics/home-page.svg"
+ width: 320; height: 480
+ Smiley { }
+ }
+
+ Item {
+ property url icon: "pics/yast-joystick.png"
+ width: 320; height: 480
+
+ Loader {
+ anchors { top: parent.top; topMargin: 10; horizontalCenter: parent.horizontalCenter }
+ width: 300; height: 400
+ clip: true; resizeMode: Loader.SizeItemToLoader
+ source: "../../../demos/declarative/samegame/samegame.qml"
+ }
+ }
+
+ currentIndex: root.currentIndex
+ }
+}
diff --git a/examples/declarative/parallax/pics/background.jpg b/examples/declarative/parallax/pics/background.jpg
new file mode 100644
index 0000000..61cca2f
--- /dev/null
+++ b/examples/declarative/parallax/pics/background.jpg
Binary files differ
diff --git a/examples/declarative/parallax/pics/face-smile.png b/examples/declarative/parallax/pics/face-smile.png
new file mode 100644
index 0000000..3d66d72
--- /dev/null
+++ b/examples/declarative/parallax/pics/face-smile.png
Binary files differ
diff --git a/examples/declarative/parallax/pics/home-page.svg b/examples/declarative/parallax/pics/home-page.svg
new file mode 100644
index 0000000..4f16958
--- /dev/null
+++ b/examples/declarative/parallax/pics/home-page.svg
@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48"
+ height="48"
+ overflow="visible"
+ enable-background="new 0 0 128 129.396"
+ xml:space="preserve"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="go-home.svg"
+ sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
+ version="1.0"
+ inkscape:export-filename="/home/tigert/My Downloads/go-home.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+ id="metadata367"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" /><dc:title>Go Home</dc:title><dc:creator><cc:Agent><dc:title>Jakub Steiner</dc:title></cc:Agent></dc:creator><dc:source>http://jimmac.musichall.cz</dc:source><dc:subject><rdf:Bag><rdf:li>home</rdf:li><rdf:li>return</rdf:li><rdf:li>go</rdf:li><rdf:li>default</rdf:li><rdf:li>user</rdf:li><rdf:li>directory</rdf:li></rdf:Bag></dc:subject><dc:contributor><cc:Agent><dc:title>Tuomas Kuosmanen</dc:title></cc:Agent></dc:contributor></cc:Work><cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/"><cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata><defs
+ id="defs365"><inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 24 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="48 : 24 : 1"
+ inkscape:persp3d-origin="24 : 16 : 1"
+ id="perspective92" /><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient5031"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" /><linearGradient
+ inkscape:collect="always"
+ id="linearGradient5060"><stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop5062" /><stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5064" /></linearGradient><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient5029"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" /><linearGradient
+ id="linearGradient5048"><stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop5050" /><stop
+ id="stop5056"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" /><stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5052" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5048"
+ id="linearGradient5027"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+ x1="302.85715"
+ y1="366.64789"
+ x2="302.85715"
+ y2="609.50507" /><linearGradient
+ id="linearGradient2406"><stop
+ style="stop-color:#7c7e79;stop-opacity:1;"
+ offset="0"
+ id="stop2408" /><stop
+ id="stop2414"
+ offset="0.1724138"
+ style="stop-color:#848681;stop-opacity:1;" /><stop
+ style="stop-color:#898c86;stop-opacity:1;"
+ offset="1"
+ id="stop2410" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ id="linearGradient2390"><stop
+ style="stop-color:#919191;stop-opacity:1;"
+ offset="0"
+ id="stop2392" /><stop
+ style="stop-color:#919191;stop-opacity:0;"
+ offset="1"
+ id="stop2394" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ id="linearGradient2378"><stop
+ style="stop-color:#575757;stop-opacity:1;"
+ offset="0"
+ id="stop2380" /><stop
+ style="stop-color:#575757;stop-opacity:0;"
+ offset="1"
+ id="stop2382" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ id="linearGradient2368"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop2370" /><stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop2372" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ id="linearGradient2349"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop2351" /><stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop2353" /></linearGradient><linearGradient
+ id="linearGradient2341"><stop
+ id="stop2343"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" /><stop
+ id="stop2345"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" /></linearGradient><linearGradient
+ id="linearGradient2329"><stop
+ style="stop-color:#000000;stop-opacity:0.18556701;"
+ offset="0"
+ id="stop2331" /><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop2333" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ id="linearGradient2319"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop2321" /><stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop2323" /></linearGradient><linearGradient
+ id="linearGradient2307"><stop
+ style="stop-color:#edd400;stop-opacity:1;"
+ offset="0"
+ id="stop2309" /><stop
+ style="stop-color:#998800;stop-opacity:1;"
+ offset="1"
+ id="stop2311" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ id="linearGradient2299"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop2301" /><stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop2303" /></linearGradient><linearGradient
+ id="XMLID_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="80.223602"
+ y1="117.5205"
+ x2="48.046001"
+ y2="59.7995"
+ gradientTransform="matrix(0.314683,0.000000,0.000000,0.314683,4.128264,3.742874)">
+ <stop
+ offset="0"
+ style="stop-color:#CCCCCC"
+ id="stop17" />
+ <stop
+ offset="0.9831"
+ style="stop-color:#FFFFFF"
+ id="stop19" />
+ <midPointStop
+ offset="0"
+ style="stop-color:#CCCCCC"
+ id="midPointStop48" />
+ <midPointStop
+ offset="0.5"
+ style="stop-color:#CCCCCC"
+ id="midPointStop50" />
+ <midPointStop
+ offset="0.9831"
+ style="stop-color:#FFFFFF"
+ id="midPointStop52" />
+ </linearGradient><linearGradient
+ inkscape:collect="always"
+ xlink:href="#XMLID_2_"
+ id="linearGradient1514"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.336922,0.000000,0.000000,0.166888,17.98288,15.46151)"
+ x1="52.006104"
+ y1="166.1331"
+ x2="14.049017"
+ y2="-42.218513" /><linearGradient
+ id="XMLID_39_"
+ gradientUnits="userSpaceOnUse"
+ x1="64.387703"
+ y1="65.124001"
+ x2="64.387703"
+ y2="35.569"
+ gradientTransform="matrix(0.354101,0.000000,0.000000,0.354101,1.638679,-8.364921e-2)">
+ <stop
+ offset="0"
+ style="stop-color:#FFFFFF"
+ id="stop336" />
+ <stop
+ offset="0.8539"
+ style="stop-color:#FF6200"
+ id="stop338" />
+ <stop
+ offset="1"
+ style="stop-color:#F25D00"
+ id="stop340" />
+ <midPointStop
+ offset="0"
+ style="stop-color:#FFFFFF"
+ id="midPointStop335" />
+ <midPointStop
+ offset="0.5"
+ style="stop-color:#FFFFFF"
+ id="midPointStop337" />
+ <midPointStop
+ offset="0.8539"
+ style="stop-color:#FF6200"
+ id="midPointStop339" />
+ <midPointStop
+ offset="0.5"
+ style="stop-color:#FF6200"
+ id="midPointStop341" />
+ <midPointStop
+ offset="1"
+ style="stop-color:#F25D00"
+ id="midPointStop343" />
+ </linearGradient><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2299"
+ id="radialGradient2305"
+ cx="7.5326638"
+ cy="24.202574"
+ fx="7.5326638"
+ fy="24.202574"
+ r="8.2452128"
+ gradientTransform="matrix(4.100086,-1.627292e-17,2.125447e-14,4.201322,-25.41506,-78.53967)"
+ gradientUnits="userSpaceOnUse" /><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2307"
+ id="radialGradient2313"
+ cx="19.985598"
+ cy="36.77816"
+ fx="19.985598"
+ fy="36.77816"
+ r="1.0821035"
+ gradientTransform="matrix(1.125263,0.000000,0.000000,0.982744,-3.428678,0.565787)"
+ gradientUnits="userSpaceOnUse" /><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2319"
+ id="radialGradient2325"
+ cx="20.443665"
+ cy="37.425829"
+ fx="20.443665"
+ fy="37.425829"
+ r="1.0821035"
+ gradientTransform="matrix(1.125263,0.000000,0.000000,0.982744,-3.428678,0.731106)"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2329"
+ id="linearGradient2335"
+ x1="17.602522"
+ y1="26.057423"
+ x2="17.682528"
+ y2="32.654099"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.898789,0,0,1.071914,0.478025,-2.080838)" /><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2341"
+ id="radialGradient2339"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(4.100086,1.627292e-17,2.125447e-14,-4.201322,-5.198109,105.3535)"
+ cx="11.68129"
+ cy="19.554111"
+ fx="11.68129"
+ fy="19.554111"
+ r="8.2452126" /><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2349"
+ id="radialGradient2355"
+ cx="24.023088"
+ cy="40.56913"
+ fx="24.023088"
+ fy="40.56913"
+ r="16.28684"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.431250,1.157278e-15,23.07369)"
+ gradientUnits="userSpaceOnUse" /><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2368"
+ id="radialGradient2374"
+ cx="29.913452"
+ cy="30.442923"
+ fx="29.913452"
+ fy="30.442923"
+ r="4.0018832"
+ gradientTransform="matrix(3.751495,-2.191984e-22,1.723265e-22,3.147818,-82.00907,-65.70704)"
+ gradientUnits="userSpaceOnUse" /><radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2378"
+ id="radialGradient2384"
+ cx="24.195112"
+ cy="10.577631"
+ fx="24.195112"
+ fy="10.577631"
+ r="15.242914"
+ gradientTransform="matrix(1.125263,-3.585417e-8,4.269819e-8,1.340059,-3.006704,1.355395)"
+ gradientUnits="userSpaceOnUse" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2390"
+ id="linearGradient2396"
+ x1="30.603519"
+ y1="37.337803"
+ x2="30.603519"
+ y2="36.112415"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.263867,0,0,0.859794,-6.499556,8.390924)" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2406"
+ id="linearGradient2412"
+ x1="17.850183"
+ y1="28.939463"
+ x2="19.040216"
+ y2="41.03223"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888785,0,0,1.08932,2.41099,-1.524336)" /></defs><sodipodi:namedview
+ inkscape:cy="-2.3755359"
+ inkscape:cx="25.234802"
+ inkscape:zoom="1"
+ inkscape:window-height="691"
+ inkscape:window-width="872"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="0.21568627"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:showpageshadow="false"
+ inkscape:window-x="466"
+ inkscape:window-y="157"
+ inkscape:current-layer="svg2"
+ fill="#555753"
+ showgrid="false"
+ stroke="#a40000"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <g
+ style="display:inline"
+ id="g5022"
+ transform="matrix(2.158196e-2,0,0,1.859457e-2,43.12251,41.63767)"><rect
+ y="-150.69685"
+ x="-1559.2523"
+ height="478.35718"
+ width="1339.6335"
+ id="rect4173"
+ style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
+ sodipodi:nodetypes="cccc"
+ id="path5058"
+ d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+ id="path5018"
+ sodipodi:nodetypes="cccc" /></g><path
+ style="color:#000000;fill:url(#linearGradient1514);fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:1.0000006;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 21.619576,8.1833733 L 27.577035,8.1833733 C 28.416767,8.1833733 41.46351,23.618701 41.46351,24.524032 L 41.019989,43.020777 C 41.019989,43.92611 40.343959,44.654954 39.504227,44.654954 L 8.0469496,44.654954 C 7.2072167,44.654954 6.5311871,43.92611 6.5311871,43.020777 L 6.5876651,24.524032 C 6.5876651,23.618701 20.779844,8.1833733 21.619576,8.1833733 z "
+ id="rect1512"
+ sodipodi:nodetypes="ccccccccc" /><path
+ style="fill:none"
+ id="path5"
+ d="M 46.963575,45.735573 L 1.6386762,45.735573 L 1.6386762,0.41067554 L 46.963575,0.41067554 L 46.963575,45.735573 z " /><path
+ style="fill:url(#linearGradient2335);fill-opacity:1;fill-rule:evenodd"
+ id="path2327"
+ d="M 23,29 L 22.954256,44.090942 L 11.111465,44.090942 L 11,29 L 23,29 z "
+ clip-rule="evenodd"
+ sodipodi:nodetypes="ccccc" /><path
+ sodipodi:nodetypes="ccccccccc"
+ id="path2357"
+ d="M 21.780459,9.405584 L 27.339556,9.405584 C 28.123138,9.405584 40.340425,23.805172 40.340425,24.649756 L 39.993267,42.862067 C 39.993267,43.321326 39.84953,43.515532 39.480892,43.515532 L 8.0936894,43.529812 C 7.7250517,43.529812 7.5097258,43.449894 7.5097258,43.076262 L 7.7250676,24.649756 C 7.7250676,23.805172 20.99688,9.405584 21.780459,9.405584 z "
+ style="opacity:0.3125;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
+ clip-rule="evenodd"
+ d="M 7.2075295,27.943053 L 7.1532728,30.538247 L 25.521437,17.358993 L 40.807832,28.513421 L 40.879142,28.201707 L 24.508686,12.297576 L 7.2075295,27.943053 z "
+ id="path23"
+ style="opacity:0.2;fill:url(#radialGradient2384);fill-opacity:1;fill-rule:evenodd"
+ sodipodi:nodetypes="ccccccc" /><path
+ clip-rule="evenodd"
+ d="M 22,30 L 22,44.090942 L 12.188971,44.090942 L 12,30 L 22,30 z "
+ id="path188"
+ style="fill:url(#linearGradient2412);fill-opacity:1;fill-rule:evenodd"
+ sodipodi:nodetypes="ccccc" /><path
+ style="opacity:0.40909089;fill:url(#radialGradient2325);fill-opacity:1;fill-rule:evenodd"
+ id="path2315"
+ d="M 19.576856,36.44767 C 20.249646,36.44767 20.793472,36.922275 20.793472,37.506177 C 20.793472,38.095988 20.249646,38.574532 19.576856,38.574532 C 18.904584,38.574532 18.35817,38.095988 18.35817,37.506177 C 18.358685,36.922275 18.904584,36.44767 19.576856,36.44767 z "
+ clip-rule="evenodd" /><path
+ clip-rule="evenodd"
+ d="M 19.462314,35.932229 C 20.135103,35.932229 20.678929,36.406834 20.678929,36.990736 C 20.678929,37.580545 20.135103,38.059089 19.462314,38.059089 C 18.790041,38.059089 18.243627,37.580545 18.243627,36.990736 C 18.244142,36.406834 18.790041,35.932229 19.462314,35.932229 z "
+ id="path217"
+ style="fill:url(#radialGradient2313);fill-opacity:1;fill-rule:evenodd" /><path
+ d="M 24.447748,11.559337 L 43.374808,28.729205 L 43.869487,29.121196 L 44.273163,28.949811 L 43.900293,28.188138 L 43.622679,27.964702 L 24.447748,12.392396 L 5.0582327,28.135731 L 4.8206309,28.279851 L 4.603921,28.986637 L 5.0373408,29.115885 L 5.4218948,28.807462 L 24.447748,11.559337 z "
+ id="path342"
+ style="fill:url(#XMLID_39_)"
+ sodipodi:nodetypes="ccccccccccccc" /><path
+ style="fill:#ef2929;stroke:#a40000"
+ id="path362"
+ d="M 24.330168,2.2713382 L 2.4484294,20.372675 L 1.8237005,27.538603 L 3.8236367,29.602926 C 3.8236367,29.602926 24.231018,12.445641 24.44773,12.274963 L 44.08027,29.818223 L 45.978694,27.494226 L 44.362903,20.382852 L 24.44773,2.1668788 L 24.330168,2.2713382 z "
+ sodipodi:nodetypes="cccccccccc" />
+<path
+ style="opacity:0.40909089;color:#000000;fill:url(#radialGradient2305);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 2.8413446,20.613129 L 2.5497894,27.236494 L 24.369219,8.980075 L 24.298891,3.0867443 L 2.8413446,20.613129 z "
+ id="path1536"
+ sodipodi:nodetypes="ccccc" /><path
+ sodipodi:nodetypes="ccccc"
+ id="path2337"
+ d="M 24.483763,8.7509884 L 24.583223,2.9098867 L 43.912186,20.56184 L 45.403998,27.062652 L 24.483763,8.7509884 z "
+ style="opacity:0.13636367;color:#000000;fill:url(#radialGradient2339);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
+ style="opacity:0.31818183;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.99999934;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 27.102228,27.719824 L 36.142223,27.719824 C 36.912818,27.719824 37.53319,28.340194 37.53319,29.110791 L 37.525229,38.190012 C 37.525229,38.960608 36.928907,39.455981 36.158311,39.455981 L 27.102228,39.455981 C 26.331631,39.455981 25.711261,38.835608 25.711261,38.065012 L 25.711261,29.110791 C 25.711261,28.340194 26.331631,27.719824 27.102228,27.719824 z "
+ id="rect2361"
+ sodipodi:nodetypes="ccccccccc" /><rect
+ style="opacity:1;color:#000000;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:0.9999994;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect3263"
+ width="10.001333"
+ height="9.9624557"
+ x="26.507767"
+ y="28.514256"
+ rx="0.38128215"
+ ry="0.38128215" /><path
+ style="opacity:0.39772728;color:#000000;fill:url(#radialGradient2374);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999958;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 27.107118,34.408261 C 30.725101,34.739438 32.634842,32.962557 35.97527,32.855521 L 36,29.00603 L 27.088388,29 L 27.107118,34.408261 z "
+ id="rect2363"
+ sodipodi:nodetypes="ccccc" /></svg> \ No newline at end of file
diff --git a/examples/declarative/parallax/pics/shadow.png b/examples/declarative/parallax/pics/shadow.png
new file mode 100644
index 0000000..8270565
--- /dev/null
+++ b/examples/declarative/parallax/pics/shadow.png
Binary files differ
diff --git a/examples/declarative/parallax/pics/yast-joystick.png b/examples/declarative/parallax/pics/yast-joystick.png
new file mode 100644
index 0000000..858cea0
--- /dev/null
+++ b/examples/declarative/parallax/pics/yast-joystick.png
Binary files differ
diff --git a/examples/declarative/parallax/pics/yast-wol.png b/examples/declarative/parallax/pics/yast-wol.png
new file mode 100644
index 0000000..7712180
--- /dev/null
+++ b/examples/declarative/parallax/pics/yast-wol.png
Binary files differ
diff --git a/examples/declarative/parallax/qml/ParallaxView.qml b/examples/declarative/parallax/qml/ParallaxView.qml
new file mode 100644
index 0000000..ff4a85a
--- /dev/null
+++ b/examples/declarative/parallax/qml/ParallaxView.qml
@@ -0,0 +1,83 @@
+import Qt 4.6
+
+Item {
+ id: root
+
+ property alias background: background.source
+ default property alias content: visualModel.children
+ property int currentIndex: 0
+
+ Image {
+ id: background
+ fillMode: Image.TileHorizontally
+ x: -list.viewportX / 2
+ width: Math.max(list.viewportWidth, parent.width)
+ }
+
+ ListView {
+ id: list
+
+ currentIndex: root.currentIndex
+ onCurrentIndexChanged: root.currentIndex = currentIndex
+
+ orientation: "Horizontal"
+ overShoot: false
+ anchors.fill: parent
+ model: VisualItemModel { id: visualModel }
+
+ snapMode: ListView.SnapOneItem
+ }
+
+ ListView {
+ id: selector
+
+ Rectangle {
+ color: "#60FFFFFF"
+ x: -10; y: -10; radius: 10; z: -1
+ width: parent.width + 20; height: parent.height + 20
+ }
+ currentIndex: root.currentIndex
+ onCurrentIndexChanged: root.currentIndex = currentIndex
+
+ height: 50
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.min(count * 50, parent.width - 20)
+ interactive: width == parent.width - 20
+ orientation: "Horizontal"
+
+ delegate: Item {
+ width: 50; height: 50
+ id: delegateRoot
+
+ Image {
+ id: image
+ source: modelData.icon
+ smooth: true
+ scale: 0.8
+ transformOrigin: "Center"
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { root.currentIndex = index }
+ }
+
+ states: State {
+ name: "Selected"
+ when: delegateRoot.ListView.isCurrentItem == true
+ PropertyChanges {
+ target: image
+ scale: 1
+ y: -5
+ }
+ }
+ transitions: Transition {
+ NumberAnimation {
+ matchProperties: "scale,y"
+ }
+ }
+ }
+ model: visualModel.children
+ }
+}
diff --git a/examples/declarative/parallax/qml/Smiley.qml b/examples/declarative/parallax/qml/Smiley.qml
new file mode 100644
index 0000000..fc5b4fe
--- /dev/null
+++ b/examples/declarative/parallax/qml/Smiley.qml
@@ -0,0 +1,47 @@
+import Qt 4.6
+
+Item {
+ id: window
+ width: 320; height: 480
+
+ // The shadow for the smiley face
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: "../pics/shadow.png"; y: smiley.minHeight + 58
+ transformOrigin: Item.Center
+
+ // The scale property depends on the y position of the smiley face.
+ scale: smiley.y * 0.5 / (smiley.minHeight - smiley.maxHeight)
+ }
+
+ Image {
+ id: smiley
+ property int maxHeight: window.height / 3
+ property int minHeight: 2 * window.height / 3
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: "../pics/face-smile.png"; y: minHeight
+
+ // Animate the y property. Setting repeat to true makes the
+ // animation repeat indefinitely, otherwise it would only run once.
+ y: SequentialAnimation {
+ repeat: true
+
+ // Move from minHeight to maxHeight in 300ms, using the easeOutExpo easing function
+ NumberAnimation {
+ from: smiley.minHeight; to: smiley.maxHeight
+ easing: "easeOutExpo"; duration: 300
+ }
+
+ // Then move back to minHeight in 1 second, using the easeOutBounce easing function
+ NumberAnimation {
+ from: smiley.maxHeight; to: smiley.minHeight
+ easing: "easeOutBounce"; duration: 1000
+ }
+
+ // Then pause for 500ms
+ PauseAnimation { duration: 500 }
+ }
+ }
+}
+
diff --git a/examples/declarative/plugins/README b/examples/declarative/plugins/README
new file mode 100644
index 0000000..621f570
--- /dev/null
+++ b/examples/declarative/plugins/README
@@ -0,0 +1,9 @@
+This example shows a module "com.nokia.TimeExample" that is implelement
+by a C++ plugin (providing the "Time" type), and by QML files (providing the
+"Clock" type).
+
+To run:
+
+ make install
+ qmlviewer plugins.qml
+
diff --git a/examples/declarative/plugins/files/Clock.qml b/examples/declarative/plugins/files/Clock.qml
new file mode 100644
index 0000000..01ec686
--- /dev/null
+++ b/examples/declarative/plugins/files/Clock.qml
@@ -0,0 +1,50 @@
+import Qt 4.6
+
+Item {
+ id: clock
+ width: 200; height: 200
+
+ property alias city: cityLabel.text
+ property var hours
+ property var minutes
+ property var shift : 0
+
+ Image { id: background; source: "clock.png" }
+
+ Image {
+ x: 92.5; y: 27
+ source: "hour.png"
+ smooth: true
+ transform: Rotation {
+ id: hourRotation
+ origin.x: 7.5; origin.y: 73; angle: 0
+ angle: SpringFollow {
+ spring: 2; damping: 0.2; modulus: 360
+ source: (clock.hours * 30) + (clock.minutes * 0.5)
+ }
+ }
+ }
+
+ Image {
+ x: 93.5; y: 17
+ source: "minute.png"
+ smooth: true
+ transform: Rotation {
+ id: minuteRotation
+ origin.x: 6.5; origin.y: 83; angle: 0
+ angle: SpringFollow {
+ spring: 2; damping: 0.2; modulus: 360
+ source: clock.minutes * 6
+ }
+ }
+ }
+
+ Image {
+ anchors.centerIn: background; source: "center.png"
+ }
+
+ Text {
+ id: cityLabel; font.bold: true; font.pixelSize: 14; y:200; color: "white"
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+}
diff --git a/examples/declarative/plugins/files/center.png b/examples/declarative/plugins/files/center.png
new file mode 100644
index 0000000..7fbd802
--- /dev/null
+++ b/examples/declarative/plugins/files/center.png
Binary files differ
diff --git a/examples/declarative/plugins/files/clock.png b/examples/declarative/plugins/files/clock.png
new file mode 100644
index 0000000..462edac
--- /dev/null
+++ b/examples/declarative/plugins/files/clock.png
Binary files differ
diff --git a/examples/declarative/plugins/files/hour.png b/examples/declarative/plugins/files/hour.png
new file mode 100644
index 0000000..f8061a1
--- /dev/null
+++ b/examples/declarative/plugins/files/hour.png
Binary files differ
diff --git a/examples/declarative/plugins/files/minute.png b/examples/declarative/plugins/files/minute.png
new file mode 100644
index 0000000..1297ec7
--- /dev/null
+++ b/examples/declarative/plugins/files/minute.png
Binary files differ
diff --git a/examples/declarative/plugins/plugin.cpp b/examples/declarative/plugins/plugin.cpp
new file mode 100644
index 0000000..f4aa36b
--- /dev/null
+++ b/examples/declarative/plugins/plugin.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDeclarative/qmlmoduleplugin.h>
+#include <QtDeclarative/qml.h>
+#include <qdebug.h>
+#include <qdatetime.h>
+#include <qbasictimer.h>
+#include <qapplication.h>
+
+// Implements a "Time" class with hour and minute properties
+// that change on-the-minute yet efficiently sleep the rest
+// of the time.
+
+class MinuteTimer : public QObject
+{
+ Q_OBJECT
+public:
+ MinuteTimer(QObject *parent) : QObject(parent)
+ {
+ }
+
+ void start()
+ {
+ if (!timer.isActive()) {
+ time = QTime::currentTime();
+ timer.start(60000-time.second()*1000, this);
+ }
+ }
+
+ void stop()
+ {
+ timer.stop();
+ }
+
+ int hour() const { return time.hour(); }
+ int minute() const { return time.minute(); }
+
+signals:
+ void timeChanged();
+
+protected:
+ void timerEvent(QTimerEvent *)
+ {
+ QTime now = QTime::currentTime();
+ if (now.second() == 59 && now.minute() == time.minute() && now.hour() == time.hour()) {
+ // just missed time tick over, force it, wait extra 0.5 seconds
+ time.addSecs(60);
+ timer.start(60500, this);
+ } else {
+ time = now;
+ timer.start(60000-time.second()*1000, this);
+ }
+ emit timeChanged();
+ }
+
+private:
+ QTime time;
+ QBasicTimer timer;
+};
+
+class Time : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int hour READ hour NOTIFY timeChanged)
+ Q_PROPERTY(int minute READ minute NOTIFY timeChanged)
+
+public:
+ Time(QObject *parent=0) : QObject(parent)
+ {
+ if (++instances == 1) {
+ if (!timer)
+ timer = new MinuteTimer(qApp);
+ connect(timer, SIGNAL(timeChanged()), this, SIGNAL(timeChanged()));
+ timer->start();
+ }
+ }
+
+ ~Time()
+ {
+ if (--instances == 0) {
+ timer->stop();
+ }
+ }
+
+ int minute() const { return timer->minute(); }
+ int hour() const { return timer->hour(); }
+
+signals:
+ void timeChanged();
+
+private:
+ QTime t;
+ static MinuteTimer *timer;
+ static int instances;
+};
+
+int Time::instances=0;
+MinuteTimer *Time::timer=0;
+
+
+QML_DECLARE_TYPE(Time);
+
+
+class QExampleQmlPlugin : public QmlModulePlugin
+{
+ Q_OBJECT
+public:
+ QStringList keys() const
+ {
+ return QStringList() << QLatin1String("com.nokia.TimeExample");
+ }
+
+ void defineModule(const QString& uri)
+ {
+ Q_ASSERT(uri == QLatin1String("com.nokia.TimeExample"));
+ qmlRegisterType<Time>("com.nokia.TimeExample", 1, 0, "Time", "Time");
+ }
+};
+
+#include "plugin.moc"
+
+Q_EXPORT_PLUGIN2(qtimeexampleqmlplugin, QExampleQmlPlugin);
diff --git a/examples/declarative/plugins/plugins.pro b/examples/declarative/plugins/plugins.pro
new file mode 100644
index 0000000..84ab8da
--- /dev/null
+++ b/examples/declarative/plugins/plugins.pro
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+TARGET = qtimeexampleqmlplugin
+CONFIG += qt plugin
+QT += declarative
+
+SOURCES += plugin.cpp
+
+target.path += $$[QT_INSTALL_PLUGINS]/qmlmodules
+sources.files += files/Clock.qml files/qmldir files/background.png files/center.png files/clock-night.png files/clock.png files/hour.png files/minute.png
+sources.path += $$[QT_INSTALL_DATA]/qml/com/nokia/TimeExample
+INSTALLS += target sources
+
+
+VERSION=1.0.0
+
diff --git a/examples/declarative/plugins/plugins.qml b/examples/declarative/plugins/plugins.qml
new file mode 100644
index 0000000..dbeb001
--- /dev/null
+++ b/examples/declarative/plugins/plugins.qml
@@ -0,0 +1,12 @@
+import com.nokia.TimeExample 1.0 // import types from the plugin
+import 'files' // import types from the 'files' directory
+
+Clock { // this class is defined in QML (files/Clock.qml)
+
+ Time { // this class is defined in C++ (plugins.cpp)
+ id: time
+ }
+
+ hours: time.hour
+ minutes: time.minute
+}
diff --git a/examples/declarative/progressbar/content/ProgressBar.qml b/examples/declarative/progressbar/content/ProgressBar.qml
new file mode 100644
index 0000000..bfc801c
--- /dev/null
+++ b/examples/declarative/progressbar/content/ProgressBar.qml
@@ -0,0 +1,36 @@
+import Qt 4.6
+
+Item {
+ id: progressbar
+ width: 250; height: 23; clip: true
+
+ property int minimum: 0
+ property int maximum: 100
+ property int value: 0
+ property alias color: g1.color
+ property alias secondColor: g2.color
+
+ BorderImage {
+ source: "background.png"
+ width: parent.width; height: parent.height
+ border.left: 4; border.top: 4; border.right: 4; border.bottom: 4
+ }
+
+ Rectangle {
+ property int widthDest: ((progressbar.width * (value - minimum)) / (maximum - minimum) - 6)
+ id: highlight; radius: 1
+ anchors.left: parent.left; anchors.top: parent.top; anchors.bottom: parent.bottom
+ anchors.leftMargin: 3; anchors.topMargin: 3; anchors.bottomMargin: 3
+ width: EaseFollow { source: highlight.widthDest; velocity: 1200 }
+ gradient: Gradient {
+ GradientStop { id: g1; position: 0.0 }
+ GradientStop { id: g2; position: 1.0 }
+ }
+ }
+ Text {
+ anchors.right: highlight.right; anchors.rightMargin: 6
+ color: "white"; font.bold: true
+ anchors.verticalCenter: parent.verticalCenter
+ text: Math.floor((value - minimum) / (maximum - minimum) * 100) + '%'
+ }
+}
diff --git a/examples/declarative/progressbar/content/background.png b/examples/declarative/progressbar/content/background.png
new file mode 100644
index 0000000..9044226
--- /dev/null
+++ b/examples/declarative/progressbar/content/background.png
Binary files differ
diff --git a/examples/declarative/progressbar/progressbars.qml b/examples/declarative/progressbar/progressbars.qml
new file mode 100644
index 0000000..fdd4ca7
--- /dev/null
+++ b/examples/declarative/progressbar/progressbars.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ id: main
+ width: 600; height: 405; color: "#edecec"
+
+ Flickable {
+ anchors.fill: parent; viewportHeight: column.height + 20
+ Column {
+ id: column; x: 10; y: 10; spacing: 10
+ Repeater {
+ model: 25
+ ProgressBar {
+ property int r: Math.floor(Math.random() * 5000 + 1000)
+ width: main.width - 20
+ value: NumberAnimation { duration: r; from: 0; to: 100; repeat: true }
+ color: ColorAnimation { duration: r; from: "lightsteelblue"; to: "thistle"; repeat: true }
+ secondColor: ColorAnimation { duration: r; from: "steelblue"; to: "#CD96CD"; repeat: true }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/scrollbar/ScrollBar.qml b/examples/declarative/scrollbar/ScrollBar.qml
new file mode 100644
index 0000000..f68775c
--- /dev/null
+++ b/examples/declarative/scrollbar/ScrollBar.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Item {
+ id: scrollBar
+ // The matchProperties that define the scrollbar's state.
+ // position and pageSize are in the range 0.0 - 1.0. They are relative to the
+ // height of the page, i.e. a pageSize of 0.5 means that you can see 50%
+ // of the height of the view.
+ // orientation can be either 'Vertical' or 'Horizontal'
+ property real position
+ property real pageSize
+ property var orientation : "Vertical"
+
+ // A light, semi-transparent background
+ Rectangle {
+ id: background
+ radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1)
+ color: "white"; opacity: 0.3
+ anchors.fill: parent
+ }
+ // Size the bar to the required size, depending upon the orientation.
+ Rectangle {
+ opacity: 0.7
+ color: "black"
+ radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1)
+ x: orientation == 'Vertical' ? 1 : (scrollBar.position * (scrollBar.width-2) + 1)
+ y: orientation == 'Vertical' ? (scrollBar.position * (scrollBar.height-2) + 1) : 1
+ width: orientation == 'Vertical' ? (parent.width-2) : (scrollBar.pageSize * (scrollBar.width-2))
+ height: orientation == 'Vertical' ? (scrollBar.pageSize * (scrollBar.height-2)) : (parent.height-2)
+ }
+}
diff --git a/examples/declarative/scrollbar/display.qml b/examples/declarative/scrollbar/display.qml
new file mode 100644
index 0000000..0b9f95a
--- /dev/null
+++ b/examples/declarative/scrollbar/display.qml
@@ -0,0 +1,57 @@
+import Qt 4.6
+
+Rectangle {
+ width: 640
+ height: 480
+ // Create a flickable to view a large image.
+ Flickable {
+ id: view
+ anchors.fill: parent
+ Image {
+ id: picture
+ source: "pics/niagara_falls.jpg"
+ }
+ viewportWidth: picture.width
+ viewportHeight: picture.height
+ // Only show the scrollbars when the view is moving.
+ states: [
+ State {
+ name: "ShowBars"
+ when: view.moving
+ PropertyChanges { target: verticalScrollBar; opacity: 1 }
+ PropertyChanges { target: horizontalScrollBar; opacity: 1 }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"
+ to: "*"
+ NumberAnimation {
+ matchProperties: "opacity"
+ duration: 400
+ }
+ }
+ ]
+ }
+ // Attach scrollbars to the right and bottom edges of the view.
+ ScrollBar {
+ id: verticalScrollBar
+ opacity: 0
+ orientation: "Vertical"
+ position: view.visibleArea.yPosition
+ pageSize: view.visibleArea.heightRatio
+ width: 12
+ height: view.height-12
+ anchors.right: view.right
+ }
+ ScrollBar {
+ id: horizontalScrollBar
+ opacity: 0
+ orientation: "Horizontal"
+ position: view.visibleArea.xPosition
+ pageSize: view.visibleArea.widthRatio
+ height: 12
+ width: view.width-12
+ anchors.bottom: view.bottom
+ }
+}
diff --git a/examples/declarative/scrollbar/pics/niagara_falls.jpg b/examples/declarative/scrollbar/pics/niagara_falls.jpg
new file mode 100644
index 0000000..618d808
--- /dev/null
+++ b/examples/declarative/scrollbar/pics/niagara_falls.jpg
Binary files differ
diff --git a/examples/declarative/searchbox/SearchBox.qml b/examples/declarative/searchbox/SearchBox.qml
new file mode 100644
index 0000000..42b5d67
--- /dev/null
+++ b/examples/declarative/searchbox/SearchBox.qml
@@ -0,0 +1,60 @@
+import Qt 4.6
+
+FocusScope {
+ id: focusScope
+ width: 250; height: 28
+
+ BorderImage {
+ source: "images/lineedit-bg.png"
+ width: parent.width; height: parent.height
+ border { left: 4; top: 4; right: 4; bottom: 4 }
+ }
+
+ BorderImage {
+ source: "images/lineedit-bg-focus.png"
+ width: parent.width; height: parent.height
+ border { left: 4; top: 4; right: 4; bottom: 4 }
+ visible: parent.wantsFocus ? true : false
+ }
+
+ Text {
+ id: typeSomething; anchors.fill: parent; anchors.leftMargin: 8
+ verticalAlignment: Text.AlignVCenter
+ text: "Type something..."; color: "gray"; font.italic: true
+ }
+
+ MouseRegion { anchors.fill: parent; onClicked: focusScope.focus = true }
+
+ TextInput {
+ id: textInput
+ anchors.left: parent.left; anchors.leftMargin: 8
+ anchors.verticalCenter: parent.verticalCenter
+ focus: if (1) true
+ }
+
+ Image {
+ id: clear
+ anchors.right: parent.right; anchors.rightMargin: 8
+ anchors.verticalCenter: parent.verticalCenter
+ source: "images/edit-clear-locationbar-rtl.png"; opacity: 0
+
+ MouseRegion { anchors.fill: parent; onClicked: { textInput.text = ''; focusScope.focus = true } }
+ }
+
+ states: State {
+ name: "hasText"; when: textInput.text != ''
+ PropertyChanges { target: typeSomething; opacity: 0 }
+ PropertyChanges { target: clear; opacity: 1 }
+ }
+
+ transitions: [
+ Transition {
+ from: ""; to: "hasText"
+ NumberAnimation { exclude: typeSomething; matchProperties: "opacity" }
+ },
+ Transition {
+ from: "hasText"; to: ""
+ NumberAnimation { matchProperties: "opacity" }
+ }
+ ]
+}
diff --git a/examples/declarative/searchbox/images/edit-clear-locationbar-rtl.png b/examples/declarative/searchbox/images/edit-clear-locationbar-rtl.png
new file mode 100644
index 0000000..91eb270
--- /dev/null
+++ b/examples/declarative/searchbox/images/edit-clear-locationbar-rtl.png
Binary files differ
diff --git a/examples/declarative/searchbox/images/lineedit-bg-focus.png b/examples/declarative/searchbox/images/lineedit-bg-focus.png
new file mode 100644
index 0000000..bbfac38
--- /dev/null
+++ b/examples/declarative/searchbox/images/lineedit-bg-focus.png
Binary files differ
diff --git a/examples/declarative/searchbox/images/lineedit-bg.png b/examples/declarative/searchbox/images/lineedit-bg.png
new file mode 100644
index 0000000..9044226
--- /dev/null
+++ b/examples/declarative/searchbox/images/lineedit-bg.png
Binary files differ
diff --git a/examples/declarative/searchbox/main.qml b/examples/declarative/searchbox/main.qml
new file mode 100644
index 0000000..39c3720
--- /dev/null
+++ b/examples/declarative/searchbox/main.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+Rectangle {
+ width: 500; height: 250; color: "#edecec"
+
+ Column {
+ anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: parent.verticalCenter; spacing: 10
+
+ SearchBox { id: search1; KeyNavigation.down: search2; focus: true }
+ SearchBox { id: search2; KeyNavigation.up: search1; KeyNavigation.down: search3 }
+ SearchBox { id: search3; KeyNavigation.up: search2 }
+ }
+}
diff --git a/examples/declarative/slideswitch/content/Switch.qml b/examples/declarative/slideswitch/content/Switch.qml
new file mode 100644
index 0000000..29a62f7
--- /dev/null
+++ b/examples/declarative/slideswitch/content/Switch.qml
@@ -0,0 +1,73 @@
+//![0]
+import Qt 4.6
+
+Item {
+ id: toggleswitch
+ width: background.width; height: background.height
+
+//![1]
+ property bool on: false
+//![1]
+
+//![2]
+ function toggle() {
+ if (toggleswitch.state == "on")
+ toggleswitch.state = "off";
+ else toggleswitch.state = "on";
+ }
+//![2]
+
+//![3]
+ function dorelease() {
+ if (knob.x == 1) {
+ if (toggleswitch.state == "off") return;
+ }
+ if (knob.x == 78) {
+ if (toggleswitch.state == "on") return;
+ }
+ toggle();
+ }
+//![3]
+
+//![4]
+ Image {
+ id: background; source: "background.svg"
+ MouseRegion { anchors.fill: parent; onClicked: toggle() }
+ }
+//![4]
+
+//![5]
+ Image {
+ id: knob; source: "knob.svg"; x: 1; y: 2
+
+ MouseRegion {
+ anchors.fill: parent
+ drag.target: knob; drag.axis: "XAxis"; drag.minimumX: 1; drag.maximumX: 78
+ onClicked: toggle()
+ onReleased: dorelease()
+ }
+ }
+//![5]
+
+//![6]
+ states: [
+ State {
+ name: "on"
+ PropertyChanges { target: knob; x: 78 }
+ PropertyChanges { target: toggleswitch; on: true }
+ },
+ State {
+ name: "off"
+ PropertyChanges { target: knob; x: 1 }
+ PropertyChanges { target: toggleswitch; on: false }
+ }
+ ]
+//![6]
+
+//![7]
+ transitions: Transition {
+ NumberAnimation { matchProperties: "x"; easing: "easeInOutQuad"; duration: 200 }
+ }
+//![7]
+}
+//![0]
diff --git a/examples/declarative/slideswitch/content/background.svg b/examples/declarative/slideswitch/content/background.svg
new file mode 100644
index 0000000..f920d3e
--- /dev/null
+++ b/examples/declarative/slideswitch/content/background.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="130px" height="56px" viewBox="0 0 130 56" enable-background="new 0 0 130 56" xml:space="preserve">
+<defs>
+</defs>
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-37.5005" y1="-66" x2="-37.5005" y2="-121.9985" gradientTransform="matrix(1 0 0 -1 102.5 -66)">
+ <stop offset="0.0056" style="stop-color:#000000"/>
+ <stop offset="1" style="stop-color:#EAECEF"/>
+</linearGradient>
+<path fill="url(#SVGID_1_)" d="M101.998,55.998H28c-15.439,0-28-12.562-28-28C0,12.56,12.561,0,28,0h73.998
+ c15.439,0,28,12.559,28,27.998C129.998,43.438,117.438,55.998,101.998,55.998L101.998,55.998z"/>
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-5.5" y1="-132.1338" x2="-69.5002" y2="-55.8613" gradientTransform="matrix(1 0 0 -1 102.5 -66)">
+ <stop offset="0.0056" style="stop-color:#000000"/>
+ <stop offset="1" style="stop-color:#828385"/>
+</linearGradient>
+<path fill="url(#SVGID_2_)" d="M127.999,27.998c0,14.359-11.642,26-26,26h-74c-14.359,0-26-11.641-26-26l0,0
+ c0-14.359,11.641-26,26-26h74C116.357,1.998,127.999,13.639,127.999,27.998L127.999,27.998z"/>
+</svg>
diff --git a/examples/declarative/slideswitch/content/knob.svg b/examples/declarative/slideswitch/content/knob.svg
new file mode 100644
index 0000000..fb69337
--- /dev/null
+++ b/examples/declarative/slideswitch/content/knob.svg
@@ -0,0 +1,867 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ x="0px"
+ y="0px"
+ width="52px"
+ height="52px"
+ viewBox="0 0 52 52"
+ enable-background="new 0 0 52 52"
+ xml:space="preserve"
+ id="svg3883"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docname="knob_on.svg"
+ sodipodi:docbase="/local/axel/embeddedwidgets/embeddedstories/skins/svgslideswitch/MetallicBrush"><metadata
+ id="metadata4200"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ inkscape:window-height="640"
+ inkscape:window-width="937"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="8.3653846"
+ inkscape:cx="26.000002"
+ inkscape:cy="26"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg3883" />
+<defs
+ id="defs3885">
+</defs>
+<linearGradient
+ id="SVGID_1_"
+ gradientUnits="userSpaceOnUse"
+ x1="-59.7866"
+ y1="-115.917"
+ x2="-93.2123"
+ y2="-76.0818"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#000000"
+ id="stop3888" />
+ <stop
+ offset="1"
+ style="stop-color:#EAECEF"
+ id="stop3890" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="26"
+ id="circle3892"
+ style="fill:url(#SVGID_1_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="26"
+ sodipodi:ry="26"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="-100.5"
+ y1="-96"
+ x2="-52.5"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3895" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3897" />
+ <stop
+ offset="0.6043"
+ style="stop-color:#E7EAED"
+ id="stop3899" />
+ <stop
+ offset="0.6751"
+ style="stop-color:#DEE4E7"
+ id="stop3901" />
+ <stop
+ offset="0.7358"
+ style="stop-color:#CFD9DD"
+ id="stop3903" />
+ <stop
+ offset="0.791"
+ style="stop-color:#B9CACF"
+ id="stop3905" />
+ <stop
+ offset="0.8425"
+ style="stop-color:#9EB6BD"
+ id="stop3907" />
+ <stop
+ offset="0.891"
+ style="stop-color:#7B9EA7"
+ id="stop3909" />
+ <stop
+ offset="0.9374"
+ style="stop-color:#53828C"
+ id="stop3911" />
+ <stop
+ offset="0.9809"
+ style="stop-color:#25626E"
+ id="stop3913" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3915" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="24"
+ id="circle3917"
+ style="fill:url(#SVGID_2_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="24"
+ sodipodi:ry="24"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_3_"
+ gradientUnits="userSpaceOnUse"
+ x1="-98.6328"
+ y1="-96"
+ x2="-54.3672"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3920" />
+ <stop
+ offset="0.073"
+ style="stop-color:#8FAECB"
+ id="stop3922" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3924" />
+ <stop
+ offset="0.5902"
+ style="stop-color:#E7E9ED"
+ id="stop3926" />
+ <stop
+ offset="0.618"
+ style="stop-color:#E4E7EB"
+ id="stop3928" />
+ <stop
+ offset="0.6697"
+ style="stop-color:#E0E4E9"
+ id="stop3930" />
+ <stop
+ offset="0.7211"
+ style="stop-color:#D4DCE1"
+ id="stop3932" />
+ <stop
+ offset="0.7722"
+ style="stop-color:#C0CFD5"
+ id="stop3934" />
+ <stop
+ offset="0.809"
+ style="stop-color:#ADC2C9"
+ id="stop3936" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3938" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="22.132999"
+ id="circle3940"
+ style="fill:url(#SVGID_3_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="22.132999"
+ sodipodi:ry="22.132999"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_4_"
+ gradientUnits="userSpaceOnUse"
+ x1="-96.7671"
+ y1="-96"
+ x2="-56.2324"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3943" />
+ <stop
+ offset="0.073"
+ style="stop-color:#86A7C4"
+ id="stop3945" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3947" />
+ <stop
+ offset="0.577"
+ style="stop-color:#E7EAED"
+ id="stop3949" />
+ <stop
+ offset="0.618"
+ style="stop-color:#E1E6EA"
+ id="stop3951" />
+ <stop
+ offset="0.6697"
+ style="stop-color:#DDE3E8"
+ id="stop3953" />
+ <stop
+ offset="0.7211"
+ style="stop-color:#D1DBE1"
+ id="stop3955" />
+ <stop
+ offset="0.7722"
+ style="stop-color:#BDCDD5"
+ id="stop3957" />
+ <stop
+ offset="0.809"
+ style="stop-color:#AAC0CA"
+ id="stop3959" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3961" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="20.267"
+ id="circle3963"
+ style="fill:url(#SVGID_4_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="20.267"
+ sodipodi:ry="20.267"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_5_"
+ gradientUnits="userSpaceOnUse"
+ x1="-94.8999"
+ y1="-96"
+ x2="-58.0996"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3966" />
+ <stop
+ offset="0.073"
+ style="stop-color:#7E9FBC"
+ id="stop3968" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3970" />
+ <stop
+ offset="0.5709"
+ style="stop-color:#E6E9ED"
+ id="stop3972" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DFE4E9"
+ id="stop3974" />
+ <stop
+ offset="0.6687"
+ style="stop-color:#DBE1E7"
+ id="stop3976" />
+ <stop
+ offset="0.7193"
+ style="stop-color:#CFD9E0"
+ id="stop3978" />
+ <stop
+ offset="0.7695"
+ style="stop-color:#BBCCD6"
+ id="stop3980" />
+ <stop
+ offset="0.809"
+ style="stop-color:#A6BECA"
+ id="stop3982" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3984" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="18.4"
+ id="circle3986"
+ style="fill:url(#SVGID_5_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="18.4"
+ sodipodi:ry="18.4"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_6_"
+ gradientUnits="userSpaceOnUse"
+ x1="-93.0332"
+ y1="-96"
+ x2="-59.9668"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3989" />
+ <stop
+ offset="0.073"
+ style="stop-color:#7697B4"
+ id="stop3991" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3993" />
+ <stop
+ offset="0.5636"
+ style="stop-color:#E6E9ED"
+ id="stop3995" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DCE2E8"
+ id="stop3997" />
+ <stop
+ offset="0.6687"
+ style="stop-color:#D8DFE6"
+ id="stop3999" />
+ <stop
+ offset="0.7193"
+ style="stop-color:#CCD7E0"
+ id="stop4001" />
+ <stop
+ offset="0.7695"
+ style="stop-color:#B8CAD5"
+ id="stop4003" />
+ <stop
+ offset="0.809"
+ style="stop-color:#A3BCCA"
+ id="stop4005" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4007" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="16.533001"
+ id="circle4009"
+ style="fill:url(#SVGID_6_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="16.533001"
+ sodipodi:ry="16.533001"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_7_"
+ gradientUnits="userSpaceOnUse"
+ x1="-91.167"
+ y1="-96"
+ x2="-61.833"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4012" />
+ <stop
+ offset="0.073"
+ style="stop-color:#6D8FAD"
+ id="stop4014" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4016" />
+ <stop
+ offset="0.5605"
+ style="stop-color:#E5E8EC"
+ id="stop4018" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DAE1E7"
+ id="stop4020" />
+ <stop
+ offset="0.6679"
+ style="stop-color:#D6DEE5"
+ id="stop4022" />
+ <stop
+ offset="0.7175"
+ style="stop-color:#CAD6DF"
+ id="stop4024" />
+ <stop
+ offset="0.7669"
+ style="stop-color:#B6C9D6"
+ id="stop4026" />
+ <stop
+ offset="0.809"
+ style="stop-color:#9FBACB"
+ id="stop4028" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4030" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="14.667"
+ id="circle4032"
+ style="fill:url(#SVGID_7_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="14.667"
+ sodipodi:ry="14.667"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_8_"
+ gradientUnits="userSpaceOnUse"
+ x1="-89.2998"
+ y1="-96"
+ x2="-63.7002"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4035" />
+ <stop
+ offset="0.073"
+ style="stop-color:#6587A5"
+ id="stop4037" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4039" />
+ <stop
+ offset="0.5588"
+ style="stop-color:#E4E8EC"
+ id="stop4041" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D8DFE7"
+ id="stop4043" />
+ <stop
+ offset="0.6675"
+ style="stop-color:#D4DCE5"
+ id="stop4045" />
+ <stop
+ offset="0.7167"
+ style="stop-color:#C8D5E0"
+ id="stop4047" />
+ <stop
+ offset="0.7657"
+ style="stop-color:#B4C8D6"
+ id="stop4049" />
+ <stop
+ offset="0.809"
+ style="stop-color:#9CB8CB"
+ id="stop4051" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4053" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="12.8"
+ id="circle4055"
+ style="fill:url(#SVGID_8_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="12.8"
+ sodipodi:ry="12.8"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_9_"
+ gradientUnits="userSpaceOnUse"
+ x1="-87.4331"
+ y1="-96"
+ x2="-65.5664"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4058" />
+ <stop
+ offset="0.073"
+ style="stop-color:#5D809D"
+ id="stop4060" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4062" />
+ <stop
+ offset="0.5567"
+ style="stop-color:#E3E7EC"
+ id="stop4064" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D5DDE6"
+ id="stop4066" />
+ <stop
+ offset="0.6671"
+ style="stop-color:#D1DAE4"
+ id="stop4068" />
+ <stop
+ offset="0.7159"
+ style="stop-color:#C5D3DF"
+ id="stop4070" />
+ <stop
+ offset="0.7645"
+ style="stop-color:#B1C6D6"
+ id="stop4072" />
+ <stop
+ offset="0.809"
+ style="stop-color:#98B5CB"
+ id="stop4074" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4076" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="10.933"
+ id="circle4078"
+ style="fill:url(#SVGID_9_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="10.933"
+ sodipodi:ry="10.933"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_10_"
+ gradientUnits="userSpaceOnUse"
+ x1="-85.5659"
+ y1="-96"
+ x2="-67.4336"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4081" />
+ <stop
+ offset="0.073"
+ style="stop-color:#547896"
+ id="stop4083" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4085" />
+ <stop
+ offset="0.5588"
+ style="stop-color:#E1E6EB"
+ id="stop4087" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D3DCE5"
+ id="stop4089" />
+ <stop
+ offset="0.6663"
+ style="stop-color:#CFD9E3"
+ id="stop4091" />
+ <stop
+ offset="0.7143"
+ style="stop-color:#C3D2DF"
+ id="stop4093" />
+ <stop
+ offset="0.7621"
+ style="stop-color:#AFC5D7"
+ id="stop4095" />
+ <stop
+ offset="0.809"
+ style="stop-color:#94B3CC"
+ id="stop4097" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4099" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="9.066"
+ id="circle4101"
+ style="fill:url(#SVGID_10_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="9.066"
+ sodipodi:ry="9.066"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_11_"
+ gradientUnits="userSpaceOnUse"
+ x1="-83.7002"
+ y1="-96"
+ x2="-69.2998"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4104" />
+ <stop
+ offset="0.073"
+ style="stop-color:#4C708E"
+ id="stop4106" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4108" />
+ <stop
+ offset="0.5625"
+ style="stop-color:#DEE4EA"
+ id="stop4110" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D0DAE4"
+ id="stop4112" />
+ <stop
+ offset="0.6663"
+ style="stop-color:#CCD7E2"
+ id="stop4114" />
+ <stop
+ offset="0.7143"
+ style="stop-color:#C0D0DE"
+ id="stop4116" />
+ <stop
+ offset="0.7621"
+ style="stop-color:#ACC3D6"
+ id="stop4118" />
+ <stop
+ offset="0.809"
+ style="stop-color:#91B1CC"
+ id="stop4120" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4122" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="7.1999998"
+ id="circle4124"
+ style="fill:url(#SVGID_11_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="7.1999998"
+ sodipodi:ry="7.1999998"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_12_"
+ gradientUnits="userSpaceOnUse"
+ x1="-81.833"
+ y1="-96"
+ x2="-71.167"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4127" />
+ <stop
+ offset="0.073"
+ style="stop-color:#446986"
+ id="stop4129" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4131" />
+ <stop
+ offset="0.5757"
+ style="stop-color:#D9E0E8"
+ id="stop4133" />
+ <stop
+ offset="0.618"
+ style="stop-color:#CED8E3"
+ id="stop4135" />
+ <stop
+ offset="0.6655"
+ style="stop-color:#CAD5E2"
+ id="stop4137" />
+ <stop
+ offset="0.7129"
+ style="stop-color:#BECEDD"
+ id="stop4139" />
+ <stop
+ offset="0.7601"
+ style="stop-color:#AAC1D6"
+ id="stop4141" />
+ <stop
+ offset="0.807"
+ style="stop-color:#8EB0CC"
+ id="stop4143" />
+ <stop
+ offset="0.809"
+ style="stop-color:#8DAFCC"
+ id="stop4145" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4147" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="5.3330002"
+ id="circle4149"
+ style="fill:url(#SVGID_12_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="5.3330002"
+ sodipodi:ry="5.3330002"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_13_"
+ gradientUnits="userSpaceOnUse"
+ x1="-79.9658"
+ y1="-96"
+ x2="-73.0342"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4152" />
+ <stop
+ offset="0.073"
+ style="stop-color:#3B617F"
+ id="stop4154" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4156" />
+ <stop
+ offset="0.6087"
+ style="stop-color:#CED9E3"
+ id="stop4158" />
+ <stop
+ offset="0.618"
+ style="stop-color:#CBD7E2"
+ id="stop4160" />
+ <stop
+ offset="0.6655"
+ style="stop-color:#C7D4E1"
+ id="stop4162" />
+ <stop
+ offset="0.7129"
+ style="stop-color:#BBCDDD"
+ id="stop4164" />
+ <stop
+ offset="0.7601"
+ style="stop-color:#A7C0D6"
+ id="stop4166" />
+ <stop
+ offset="0.807"
+ style="stop-color:#8BAECD"
+ id="stop4168" />
+ <stop
+ offset="0.809"
+ style="stop-color:#8AADCD"
+ id="stop4170" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4172" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="3.4660001"
+ id="circle4174"
+ style="fill:url(#SVGID_13_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="3.4660001"
+ sodipodi:ry="3.4660001"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_14_"
+ gradientUnits="userSpaceOnUse"
+ x1="-78.1001"
+ y1="-96"
+ x2="-74.9004"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4177" />
+ <stop
+ offset="0.073"
+ style="stop-color:#335977"
+ id="stop4179" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4181" />
+ <stop
+ offset="0.618"
+ style="stop-color:#C9D5E1"
+ id="stop4183" />
+ <stop
+ offset="0.6648"
+ style="stop-color:#C5D3E0"
+ id="stop4185" />
+ <stop
+ offset="0.7114"
+ style="stop-color:#B9CBDC"
+ id="stop4187" />
+ <stop
+ offset="0.758"
+ style="stop-color:#A5BFD6"
+ id="stop4189" />
+ <stop
+ offset="0.8042"
+ style="stop-color:#89ADCE"
+ id="stop4191" />
+ <stop
+ offset="0.809"
+ style="stop-color:#86ABCD"
+ id="stop4193" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4195" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="1.6"
+ id="circle4197"
+ style="fill:url(#SVGID_14_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="1.6"
+ sodipodi:ry="1.6"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+</svg> \ No newline at end of file
diff --git a/examples/declarative/slideswitch/slideswitch.qml b/examples/declarative/slideswitch/slideswitch.qml
new file mode 100644
index 0000000..396749f
--- /dev/null
+++ b/examples/declarative/slideswitch/slideswitch.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ color: "white"
+ width: 400; height: 250
+
+//![0]
+ Switch { anchors.centerIn: parent; on: false }
+//![0]
+}
diff --git a/examples/declarative/snow/ImageBatch.qml b/examples/declarative/snow/ImageBatch.qml
new file mode 100644
index 0000000..1d738b2
--- /dev/null
+++ b/examples/declarative/snow/ImageBatch.qml
@@ -0,0 +1,72 @@
+import Qt 4.6
+
+GridView {
+ id: grid
+ property int offset: 0
+ property var ref
+ property bool isSelected: ref.selectedItemColumn >= offset && ref.selectedItemColumn < offset + 5
+
+ currentIndex: (ref.selectedItemColumn - offset) + ref.selectedItemRow * 5
+
+ property int imageWidth: ref.imageWidth
+ property int imageHeight: ref.imageHeight
+
+ width: 5 * imageWidth
+ height: 4 * imageHeight
+ cellWidth: imageWidth
+ cellHeight: imageHeight
+
+ states: State {
+ name: "selected"; when: grid.isSelected
+ PropertyChanges { target: grid; z: 150 }
+ }
+ transitions: Transition {
+ SequentialAnimation {
+ PauseAnimation { duration: 150 }
+ PropertyAction { matchProperties: "z" }
+ }
+ }
+ model: XmlListModel {
+ property string tags : ""
+ source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+ query: "/rss/channel/item"
+ namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+ XmlRole { name: "url"; query: "media:content/@url/string()" }
+ }
+
+ delegate: Item {
+ id: root
+ property bool isSelected: GridView.isCurrentItem && grid.isSelected
+ transformOrigin: Item.Center
+ width: grid.imageWidth; height: grid.imageHeight;
+
+ Image { id: flickrImage; source: url; fillMode: Image.PreserveAspectFit; smooth: true; anchors.fill: parent;
+ opacity: (status == Image.Ready)?1:0; opacity: Behavior { NumberAnimation { } } }
+ Loading { anchors.centerIn: parent; visible: flickrImage.status!=1 }
+
+ states: State {
+ name: "selected"
+ when: root.isSelected
+ PropertyChanges { target: root; scale: 3; z: 100 }
+ }
+ transitions: [
+ Transition {
+ to: "selected"
+ SequentialAnimation {
+ PauseAnimation { duration: 150 }
+ PropertyAction { matchProperties: "z" }
+ NumberAnimation { matchProperties: "scale"; duration: 150; }
+ }
+ },
+ Transition {
+ from: "selected"
+ SequentialAnimation {
+ NumberAnimation { matchProperties: "scale"; duration: 150 }
+ PropertyAction { matchProperties: "z" }
+ }
+ }
+ ]
+ }
+}
+
diff --git a/examples/declarative/snow/Loading.qml b/examples/declarative/snow/Loading.qml
new file mode 100644
index 0000000..238d9c7
--- /dev/null
+++ b/examples/declarative/snow/Loading.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Image {
+ id: loading; source: "pics/loading.png"; transformOrigin: Item.Center
+ rotation: NumberAnimation {
+ id: rotationAnimation; from: 0; to: 360; running: loading.visible == true; repeat: true; duration: 900
+ }
+}
diff --git a/examples/declarative/snow/create.js b/examples/declarative/snow/create.js
new file mode 100644
index 0000000..2bdae4a
--- /dev/null
+++ b/examples/declarative/snow/create.js
@@ -0,0 +1,12 @@
+var myComponent = null;
+
+function createNewBlock() {
+ if (myComponent == null)
+ myComponent = createComponent("ImageBatch.qml");
+
+ var obj = myComponent.createObject();
+ obj.parent = layout;
+ obj.offset = maximumColumn + 1;
+ obj.ref = imagePanel;
+ maximumColumn += 5;
+}
diff --git a/examples/declarative/snow/pics/loading.png b/examples/declarative/snow/pics/loading.png
new file mode 100644
index 0000000..0296cfe
--- /dev/null
+++ b/examples/declarative/snow/pics/loading.png
Binary files differ
diff --git a/examples/declarative/snow/snow.qml b/examples/declarative/snow/snow.qml
new file mode 100644
index 0000000..39c9c43
--- /dev/null
+++ b/examples/declarative/snow/snow.qml
@@ -0,0 +1,69 @@
+import Qt 4.6
+
+Rectangle {
+ id: imagePanel
+ width: 1024
+ height: 768
+ color: "black"
+
+ property int maximumColumn: 4
+ property int selectedItemRow: 0
+ property int selectedItemColumn: 0
+
+ Script { source: "create.js" }
+
+ onSelectedItemColumnChanged: if (selectedItemColumn == maximumColumn) createNewBlock();
+
+ property int imageWidth: 200
+ property int imageHeight: 200
+
+ property int selectedX: selectedItemColumn * imageWidth
+ property int selectedY: selectedItemRow * imageHeight
+
+ Item {
+ anchors.centerIn: parent
+ Row {
+ id: layout
+ property real targetX: -(selectedX + imageWidth / 2)
+
+ property real targetDeform: 0
+ property bool slowDeform: true
+
+ property real deform: 0
+ deform: SpringFollow {
+ id: deformFollow; source: layout.targetDeform; velocity: layout.slowDeform?0.1:2
+ onSyncChanged: if(inSync) { layout.slowDeform = true; layout.targetDeform = 0; }
+ }
+
+ ImageBatch { offset: 0; ref: imagePanel }
+
+ x: SpringFollow { source: layout.targetX; velocity: 1000 }
+ y: SpringFollow { source: -(selectedY + imageHeight / 2); velocity: 500 }
+ }
+
+ transform: Rotation {
+ axis.y: 1; axis.z: 0
+ angle: layout.deform * -100
+ }
+ }
+
+ Script {
+ function left() {
+ if (selectedItemColumn <= 0) return;
+ selectedItemColumn -= 1;
+ layout.slowDeform = false;
+ layout.targetDeform = Math.max(Math.min(layout.deform - 0.1, -0.1), -0.4);
+ }
+ function right() {
+ selectedItemColumn += 1;
+ layout.slowDeform = false;
+ layout.targetDeform = Math.min(Math.max(layout.deform + 0.1, 0.1), 0.4);
+ }
+ }
+
+ focus: true
+ Keys.onLeftPressed: "left()"
+ Keys.onRightPressed: "right()"
+ Keys.onUpPressed: "if (selectedItemRow > 0) selectedItemRow = selectedItemRow - 1"
+ Keys.onDownPressed: "if (selectedItemRow < 3) selectedItemRow = selectedItemRow + 1"
+}
diff --git a/examples/declarative/sql/hello.qml b/examples/declarative/sql/hello.qml
new file mode 100644
index 0000000..96e0675
--- /dev/null
+++ b/examples/declarative/sql/hello.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Text {
+ Script {
+ function findGreetings() {
+ var db = openDatabaseSync("QmlExampleDB", "1.0", "The Example QML SQL!", 1000000);
+
+ db.transaction(
+ function(tx) {
+ // Create the database if it doesn't already exist
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
+
+ // Add (another) greeting row
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+
+ // Show all added greetings
+ var rs = tx.executeSql('SELECT * FROM Greeting');
+
+ var r = ""
+ for(var i = 0; i < rs.rows.length; i++) {
+ r += rs.rows.item(i).salutation + ", " + rs.rows.item(i).salutee + "\n"
+ }
+ text = r
+ }
+ )
+ }
+ }
+ text: "?"
+ Component.onCompleted: findGreetings()
+}
+
diff --git a/examples/declarative/states/states.qml b/examples/declarative/states/states.qml
new file mode 100644
index 0000000..6f6b40f
--- /dev/null
+++ b/examples/declarative/states/states.qml
@@ -0,0 +1,50 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ width: 640; height: 480; color: "#343434"
+
+ // A target region. Clicking in here sets the state to the default state
+ Rectangle {
+ id: initialPosition
+ anchors { left: parent.left; top: parent.top; leftMargin: 10; topMargin: 20 }
+ width: 64; height: 64; radius: 6
+ color: "Transparent"; border.color: "Gray"
+ MouseRegion { anchors.fill: parent; onClicked: page.state = '' }
+ }
+
+ // Another target region. Clicking in here sets the state to 'Position1'
+ Rectangle {
+ id: position1
+ anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 20 }
+ width: 64; height: 64; radius: 6
+ color: "Transparent"; border.color: "Gray"
+ MouseRegion { anchors.fill: parent; onClicked: page.state = 'Position1' }
+ }
+
+ // Another target region. Clicking in here sets the state to 'Position2'
+ Rectangle {
+ id: position2
+ anchors { left: parent.left; bottom: parent.bottom; leftMargin: 10; bottomMargin: 20 }
+ width: 64; height: 64; radius: 6
+ color: "Transparent"; border.color: "Gray"
+ MouseRegion { anchors.fill: parent; onClicked: page.state = 'Position2' }
+ }
+
+ // The image which will be moved when my state changes
+ Image { id: user; source: "user.png"; x: initialPosition.x; y: initialPosition.y }
+
+ states: [
+ // In state 'Position1', change the 'user' item position to rect2's position.
+ State {
+ name: "Position1"
+ PropertyChanges { target: user; x: position1.x; y: position1.y }
+ },
+
+ // In state 'Position2', change the 'user' item position to rect3's position.
+ State {
+ name: "Position2"
+ PropertyChanges { target: user; x: position2.x; y: position2.y }
+ }
+ ]
+}
diff --git a/examples/declarative/states/transitions.qml b/examples/declarative/states/transitions.qml
new file mode 100644
index 0000000..925d90e
--- /dev/null
+++ b/examples/declarative/states/transitions.qml
@@ -0,0 +1,70 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ width: 640; height: 480; color: "#343434"
+
+ // A target region. Clicking in here sets the state to the default state
+ Rectangle {
+ id: initialPosition
+ anchors { left: parent.left; top: parent.top; leftMargin: 10; topMargin: 20 }
+ width: 64; height: 64; radius: 6
+ color: "Transparent"; border.color: "Gray"
+ MouseRegion { anchors.fill: parent; onClicked: page.state = '' }
+ }
+
+ // Another target region. Clicking in here sets the state to 'Position1'
+ Rectangle {
+ id: position1
+ anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 20 }
+ width: 64; height: 64; radius: 6
+ color: "Transparent"; border.color: "Gray"
+ MouseRegion { anchors.fill: parent; onClicked: page.state = 'Position1' }
+ }
+
+ // Another target region. Clicking in here sets the state to 'Position2'
+ Rectangle {
+ id: position2
+ anchors { left: parent.left; bottom: parent.bottom; leftMargin: 10; bottomMargin: 20 }
+ width: 64; height: 64; radius: 6
+ color: "Transparent"; border.color: "Gray"
+ MouseRegion { anchors.fill: parent; onClicked: page.state = 'Position2' }
+ }
+
+ // The image which will be moved when my state changes
+ Image { id: user; source: "user.png"; x: initialPosition.x; y: initialPosition.y }
+
+ states: [
+ // In state 'Position1', change the 'user' item position to rect2's position.
+ State {
+ name: "Position1"
+ PropertyChanges { target: user; x: position1.x; y: position1.y }
+ },
+
+ // In state 'Position2', change the 'user' item position to rect3's position.
+ State {
+ name: "Position2"
+ PropertyChanges { target: user; x: position2.x; y: position2.y }
+ }
+ ]
+
+ // transitions define how the matchProperties change.
+ transitions: [
+ // When transitioning to 'Position1' move x,y over a duration of 1 second,
+ // with easeOutBounce easing function.
+ Transition {
+ from: "*"; to: "Position1"
+ NumberAnimation { matchProperties: "x,y"; easing: "easeOutBounce"; duration: 1000 }
+ },
+ // When transitioning to 'Position2' move x,y over a duration of 2 seconds,
+ // with easeInOutQuad easing function.
+ Transition {
+ from: "*"; to: "Position2"
+ NumberAnimation { matchProperties: "x,y"; easing: "easeInOutQuad"; duration: 2000 }
+ },
+ // For any other state changes move x,y linearly over duration of 200ms.
+ Transition {
+ NumberAnimation { matchProperties: "x,y"; duration: 200 }
+ }
+ ]
+}
diff --git a/examples/declarative/states/user.png b/examples/declarative/states/user.png
new file mode 100644
index 0000000..dd7d7a2
--- /dev/null
+++ b/examples/declarative/states/user.png
Binary files differ
diff --git a/examples/declarative/tabwidget/TabWidget.qml b/examples/declarative/tabwidget/TabWidget.qml
new file mode 100644
index 0000000..c56f41e
--- /dev/null
+++ b/examples/declarative/tabwidget/TabWidget.qml
@@ -0,0 +1,42 @@
+import Qt 4.6
+
+Item {
+ id: page
+ property int current: 0
+ default property alias content: stack.children
+ onCurrentChanged: setOpacities()
+ Component.onCompleted: setOpacities()
+ function setOpacities()
+ {
+ for (var i=0; i<stack.children.length; ++i) {
+ stack.children[i].opacity = i==current ? 1 : 0
+ }
+ }
+ Row {
+ id: header
+ Repeater {
+ delegate:
+ Rectangle {
+ width: page.width / stack.children.length
+ height: 15
+ color: page.current == index ? "grey" : "lightGrey"
+ Text {
+ anchors.fill: parent
+ text: stack.children[index].title
+ elide: Text.ElideRight
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: page.current = index
+ }
+ }
+ model: stack.children.length
+ }
+ }
+ Item {
+ id: stack
+ anchors.top: header.bottom
+ anchors.bottom: page.bottom
+ width: page.width
+ }
+}
diff --git a/examples/declarative/tabwidget/tabs.qml b/examples/declarative/tabwidget/tabs.qml
new file mode 100644
index 0000000..54ed7df
--- /dev/null
+++ b/examples/declarative/tabwidget/tabs.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+TabWidget {
+ id: tabs
+ width: 200
+ height: 200
+ current: 2
+ Rectangle {
+ property string title: "Red"
+ color: "red"
+ anchors.fill: parent
+ Text { anchors.centerIn: parent; text: "<div align=center>Roses are red"; font.pixelSize: 24
+ wrap: true; width: parent.width-20 }
+ }
+ Rectangle {
+ property string title: "Green"
+ color: "green"
+ anchors.fill: parent
+ Text { anchors.centerIn: parent; text: "<div align=center>Flower stems are green"; font.pixelSize: 24;
+ wrap: true; width: parent.width-20 }
+ }
+ Rectangle {
+ property string title: "Blue"
+ color: "blue"
+ anchors.fill: parent
+ Text { anchors.centerIn: parent; text: "<div align=center>Violets are blue"; color: "white"; font.pixelSize: 24
+ wrap: true; width: parent.width-20 }
+ }
+}
diff --git a/examples/declarative/tic-tac-toe/content/TicTac.qml b/examples/declarative/tic-tac-toe/content/TicTac.qml
new file mode 100644
index 0000000..eb80743
--- /dev/null
+++ b/examples/declarative/tic-tac-toe/content/TicTac.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+Item {
+ signal clicked
+
+ states: [
+ State { name: "X"; PropertyChanges { target: image; source: "pics/x.png" } },
+ State { name: "O"; PropertyChanges { target: image; source: "pics/o.png" } }
+ ]
+
+ Image {
+ id: image
+ anchors.centerIn: parent
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.clicked()
+ }
+}
diff --git a/examples/declarative/tic-tac-toe/content/pics/board.png b/examples/declarative/tic-tac-toe/content/pics/board.png
new file mode 100644
index 0000000..cd85971
--- /dev/null
+++ b/examples/declarative/tic-tac-toe/content/pics/board.png
Binary files differ
diff --git a/examples/declarative/tic-tac-toe/content/pics/o.png b/examples/declarative/tic-tac-toe/content/pics/o.png
new file mode 100644
index 0000000..abc7ee0
--- /dev/null
+++ b/examples/declarative/tic-tac-toe/content/pics/o.png
Binary files differ
diff --git a/examples/declarative/tic-tac-toe/content/pics/x.png b/examples/declarative/tic-tac-toe/content/pics/x.png
new file mode 100644
index 0000000..ddc65c8
--- /dev/null
+++ b/examples/declarative/tic-tac-toe/content/pics/x.png
Binary files differ
diff --git a/examples/declarative/tic-tac-toe/tic-tac-toe.qml b/examples/declarative/tic-tac-toe/tic-tac-toe.qml
new file mode 100644
index 0000000..63ee483
--- /dev/null
+++ b/examples/declarative/tic-tac-toe/tic-tac-toe.qml
@@ -0,0 +1,115 @@
+import Qt 4.6
+import "content"
+
+Item {
+ width: boardimage.width
+ height: boardimage.height
+
+ Image {
+ id: boardimage
+ source: "content/pics/board.png"
+ }
+
+ Grid {
+ id: board
+ anchors.fill: boardimage
+
+ columns: 3
+
+ Repeater {
+ model: 9
+ TicTac {
+ width: board.width/3
+ height: board.height/3
+ onClicked: {
+ if (!endtimer.running) {
+ if (!makeMove(index,"X"))
+ computerTurn()
+ }
+ }
+ }
+ }
+
+ Script {
+ function winner()
+ {
+ for (var i=0; i<3; ++i) {
+ if (board.children[i].state!=""
+ && board.children[i].state==board.children[i+3].state
+ && board.children[i].state==board.children[i+6].state)
+ return true
+
+ if (board.children[i*3].state!=""
+ && board.children[i*3].state==board.children[i*3+1].state
+ && board.children[i*3].state==board.children[i*3+2].state)
+ return true
+ }
+
+ if (board.children[0].state!=""
+ && board.children[0].state==board.children[4].state!=""
+ && board.children[0].state==board.children[8].state!="")
+ return true
+
+ if (board.children[2].state!=""
+ && board.children[2].state==board.children[4].state!=""
+ && board.children[2].state==board.children[6].state!="")
+ return true
+
+ return false
+ }
+
+ function restart()
+ {
+ // No moves left - start again
+ for (var i=0; i<9; ++i)
+ board.children[i].state = ""
+ }
+
+ function makeMove(pos,player)
+ {
+ board.children[pos].state = player
+ if (winner()) {
+ win(player + " wins")
+ return true
+ } else {
+ return false
+ }
+ }
+
+ function computerTurn()
+ {
+ // world's dumbest player
+ for (var i=0; i<9; ++i)
+ if (board.children[i].state == "") {
+ makeMove(i,"O")
+ return
+ }
+ restart()
+ }
+
+ function win(s)
+ {
+ msg.text = s
+ msg.opacity = 1
+ endtimer.running = true
+ }
+ }
+
+ Timer {
+ id: endtimer
+ interval: 1600
+ onTriggered: { msg.opacity = 0; restart() }
+ }
+ }
+
+ Text {
+ id: msg
+ opacity: 0
+ anchors.centerIn: parent
+ color: "blue"
+ styleColor: "white"
+ style: Text.Outline
+ font.pixelSize: 50
+ font.bold: true
+ }
+}
diff --git a/examples/declarative/tutorials/helloworld/Cell.qml b/examples/declarative/tutorials/helloworld/Cell.qml
new file mode 100644
index 0000000..c38b40e
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/Cell.qml
@@ -0,0 +1,32 @@
+//![0]
+import Qt 4.6
+
+//![1]
+Item {
+ id: container
+//![4]
+ property alias color: rectangle.color
+//![4]
+//![5]
+ signal clicked(color color)
+//![5]
+
+ width: 40; height: 25
+//![1]
+
+//![2]
+ Rectangle {
+ id: rectangle
+ border.color: "white"
+ anchors.fill: parent
+ }
+//![2]
+
+//![3]
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: container.clicked(container.color)
+ }
+//![3]
+}
+//![0]
diff --git a/examples/declarative/tutorials/helloworld/tutorial1.qml b/examples/declarative/tutorials/helloworld/tutorial1.qml
new file mode 100644
index 0000000..93d3c34
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/tutorial1.qml
@@ -0,0 +1,22 @@
+//![0]
+//![3]
+import Qt 4.6
+//![3]
+
+//![1]
+Rectangle {
+ id: page
+ width: 500; height: 200
+ color: "lightgray"
+//![1]
+
+//![2]
+ Text {
+ id: helloText
+ text: "Hello world!"
+ font.pointSize: 24; font.bold: true
+ y: 30; anchors.horizontalCenter: page.horizontalCenter
+ }
+//![2]
+}
+//![0]
diff --git a/examples/declarative/tutorials/helloworld/tutorial2.qml b/examples/declarative/tutorials/helloworld/tutorial2.qml
new file mode 100644
index 0000000..99889d7
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/tutorial2.qml
@@ -0,0 +1,31 @@
+//![0]
+import Qt 4.6
+
+Rectangle {
+ id: page
+ width: 500; height: 200
+ color: "lightgray"
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ font.pointSize: 24; font.bold: true
+ y: 30; anchors.horizontalCenter: page.horizontalCenter
+ }
+
+ Grid {
+ id: colorPicker
+ anchors.bottom: page.bottom
+ rows: 2; columns: 3; spacing: 3
+
+//![1]
+ Cell { color: "red"; onClicked: helloText.color = color }
+//![1]
+ Cell { color: "green"; onClicked: helloText.color = color }
+ Cell { color: "blue"; onClicked: helloText.color = color }
+ Cell { color: "yellow"; onClicked: helloText.color = color }
+ Cell { color: "steelblue"; onClicked: helloText.color = color }
+ Cell { color: "black"; onClicked: helloText.color = color }
+ }
+}
+//![0]
diff --git a/examples/declarative/tutorials/helloworld/tutorial3.qml b/examples/declarative/tutorials/helloworld/tutorial3.qml
new file mode 100644
index 0000000..0f27f86
--- /dev/null
+++ b/examples/declarative/tutorials/helloworld/tutorial3.qml
@@ -0,0 +1,51 @@
+//![0]
+import Qt 4.6
+
+Rectangle {
+ id: page
+ width: 500; height: 200
+ color: "lightgray"
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ font.pointSize: 24; font.bold: true
+ y: 30; anchors.horizontalCenter: page.horizontalCenter
+ transformOrigin: Item.Center
+
+//![1]
+ MouseRegion { id: mouseRegion; anchors.fill: parent }
+//![1]
+
+//![2]
+ states: State {
+ name: "down"; when: mouseRegion.pressed == true
+ PropertyChanges { target: helloText; y: 160; rotation: 180; color: "red" }
+ }
+//![2]
+
+//![3]
+ transitions: Transition {
+ from: ""; to: "down"; reversible: true
+ ParallelAnimation {
+ NumberAnimation { matchProperties: "y,rotation"; duration: 500; easing: "easeInOutQuad" }
+ ColorAnimation { duration: 500 }
+ }
+ }
+//![3]
+ }
+
+ Grid {
+ id: colorPicker
+ anchors.bottom: page.bottom
+ rows: 2; columns: 3; spacing: 3
+
+ Cell { color: "red"; onClicked: helloText.color = color }
+ Cell { color: "green"; onClicked: helloText.color = color }
+ Cell { color: "blue"; onClicked: helloText.color = color }
+ Cell { color: "yellow"; onClicked: helloText.color = color }
+ Cell { color: "steelblue"; onClicked: helloText.color = color }
+ Cell { color: "black"; onClicked: helloText.color = color }
+ }
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame1/Block.qml b/examples/declarative/tutorials/samegame/samegame1/Block.qml
new file mode 100644
index 0000000..b76e61a
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame1/Block.qml
@@ -0,0 +1,12 @@
+//![0]
+import Qt 4.6
+
+Item {
+ id:block
+
+ Image { id: img
+ source: "pics/redStone.png";
+ anchors.fill: parent
+ }
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame1/Button.qml b/examples/declarative/tutorials/samegame/samegame1/Button.qml
new file mode 100644
index 0000000..85e6777
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame1/Button.qml
@@ -0,0 +1,27 @@
+//![0]
+import Qt 4.6
+
+Rectangle {
+ id: container
+
+ signal clicked
+ property string text: "Button"
+
+ color: activePalette.button; smooth: true
+ width: txtItem.width + 20; height: txtItem.height + 6
+ border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8;
+
+ gradient: Gradient {
+ GradientStop {
+ id: topGrad; position: 0.0
+ color: if (mr.pressed) { activePalette.dark } else { activePalette.light } }
+ GradientStop { position: 1.0; color: activePalette.button }
+ }
+
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: container.clicked() }
+
+ Text {
+ id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+ }
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame1/pics/background.png b/examples/declarative/tutorials/samegame/samegame1/pics/background.png
new file mode 100644
index 0000000..3734a27
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame1/pics/background.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame1/pics/redStone.png b/examples/declarative/tutorials/samegame/samegame1/pics/redStone.png
new file mode 100644
index 0000000..36b09a2
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame1/pics/redStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame1/samegame.qml b/examples/declarative/tutorials/samegame/samegame1/samegame.qml
new file mode 100644
index 0000000..c2d3939
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame1/samegame.qml
@@ -0,0 +1,40 @@
+//![0]
+import Qt 4.6
+
+Rectangle {
+ id: screen
+ width: 490; height: 720
+
+ SystemPalette { id: activePalette }
+
+ Item {
+ width: parent.width; anchors.top: parent.top; anchors.bottom: toolbar.top
+
+ Image {
+ id: background
+ anchors.fill: parent; source: "pics/background.png"
+ fillMode: Image.PreserveAspectCrop
+ }
+ }
+
+ Rectangle {
+ id: toolbar
+ color: activePalette.window
+ height: 32; width: parent.width
+ anchors.bottom: screen.bottom
+
+ Button {
+ id: btnA; text: "New Game"; onClicked: console.log("Implement me!");
+ anchors.left: parent.left; anchors.leftMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Text {
+ id: score
+ text: "Score: Who knows?"; font.bold: true
+ anchors.right: parent.right; anchors.rightMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame2/Block.qml b/examples/declarative/tutorials/samegame/samegame2/Block.qml
new file mode 100644
index 0000000..228ac4e
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame2/Block.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+Item {
+ id:block
+
+ Image { id: img
+ source: "pics/redStone.png";
+ anchors.fill: parent
+ }
+}
diff --git a/examples/declarative/tutorials/samegame/samegame2/Button.qml b/examples/declarative/tutorials/samegame/samegame2/Button.qml
new file mode 100644
index 0000000..63cd555
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame2/Button.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+
+ signal clicked
+ property string text: "Button"
+
+ color: activePalette.button; smooth: true
+ width: txtItem.width + 20; height: txtItem.height + 6
+ border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8;
+
+ gradient: Gradient {
+ GradientStop {
+ id: topGrad; position: 0.0
+ color: if (mr.pressed) { activePalette.dark } else { activePalette.light } }
+ GradientStop { position: 1.0; color: activePalette.button }
+ }
+
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: container.clicked() }
+
+ Text {
+ id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+ }
+}
diff --git a/examples/declarative/tutorials/samegame/samegame2/pics/background.png b/examples/declarative/tutorials/samegame/samegame2/pics/background.png
new file mode 100644
index 0000000..3734a27
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame2/pics/background.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame2/pics/redStone.png b/examples/declarative/tutorials/samegame/samegame2/pics/redStone.png
new file mode 100644
index 0000000..36b09a2
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame2/pics/redStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame2/samegame.js b/examples/declarative/tutorials/samegame/samegame2/samegame.js
new file mode 100644
index 0000000..2c02c61
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame2/samegame.js
@@ -0,0 +1,61 @@
+//![0]
+//Note that X/Y referred to here are in game coordinates
+var maxX = 10;//Nums are for tileSize 40
+var maxY = 15;
+var tileSize = 40;
+var maxIndex = maxX*maxY;
+var board = new Array(maxIndex);
+var tileSrc = "Block.qml";
+var component;
+
+//Index function used instead of a 2D array
+function index(xIdx,yIdx) {
+ return xIdx + (yIdx * maxX);
+}
+
+function initBoard()
+{
+ //Calculate board size
+ maxX = Math.floor(background.width/tileSize);
+ maxY = Math.floor(background.height/tileSize);
+ maxIndex = maxY*maxX;
+
+ //Initialize Board
+ board = new Array(maxIndex);
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ for(var yIdx=0; yIdx<maxY; yIdx++){
+ board[index(xIdx,yIdx)] = null;
+ createBlock(xIdx,yIdx);
+ }
+ }
+}
+
+function createBlock(xIdx,yIdx){
+ if(component==null)
+ component = createComponent(tileSrc);
+
+ // Note that we don't wait for the component to become ready. This will
+ // only work if the block QML is a local file. Otherwise the component will
+ // not be ready immediately. There is a statusChanged signal on the
+ // component you could use if you want to wait to load remote files.
+ if(component.isReady){
+ var dynamicObject = component.createObject();
+ if(dynamicObject == null){
+ print("error creating block");
+ print(component.errorsString());
+ return false;
+ }
+ dynamicObject.parent = background;
+ dynamicObject.x = xIdx*tileSize;
+ dynamicObject.y = yIdx*tileSize;
+ dynamicObject.width = tileSize;
+ dynamicObject.height = tileSize;
+ board[index(xIdx,yIdx)] = dynamicObject;
+ }else{//isError or isLoading
+ print("error loading block component");
+ print(component.errorsString());
+ return false;
+ }
+ return true;
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame2/samegame.qml b/examples/declarative/tutorials/samegame/samegame2/samegame.qml
new file mode 100644
index 0000000..8d837da
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame2/samegame.qml
@@ -0,0 +1,43 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen
+ width: 490; height: 720
+
+ SystemPalette { id: activePalette }
+//![2]
+ Script { source: "samegame.js" }
+//![2]
+
+ Item {
+ width: parent.width; anchors.top: parent.top; anchors.bottom: toolbar.top
+
+ Image {
+ id: background
+ anchors.fill: parent; source: "pics/background.png"
+ fillMode: Image.PreserveAspectCrop
+ }
+ }
+
+ Rectangle {
+ id: toolbar
+ color: activePalette.window
+ height: 32; width: parent.width
+ anchors.bottom: screen.bottom
+
+//![1]
+ Button {
+ id: btnA; text: "New Game"; onClicked: initBoard();
+ anchors.left: parent.left; anchors.leftMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+//![1]
+
+ Text {
+ id: score
+ text: "Score: Who knows?"; font.bold: true
+ anchors.right: parent.right; anchors.rightMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/samegame/samegame3/Block.qml b/examples/declarative/tutorials/samegame/samegame3/Block.qml
new file mode 100644
index 0000000..30a8d3a
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/Block.qml
@@ -0,0 +1,21 @@
+//![0]
+import Qt 4.6
+
+Item {
+ id:block
+ property int type: 0
+
+ Image { id: img
+ source: {
+ if(type == 0){
+ "pics/redStone.png";
+ } else if(type == 1) {
+ "pics/blueStone.png";
+ } else {
+ "pics/greenStone.png";
+ }
+ }
+ anchors.fill: parent
+ }
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame3/Button.qml b/examples/declarative/tutorials/samegame/samegame3/Button.qml
new file mode 100644
index 0000000..63cd555
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/Button.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+
+ signal clicked
+ property string text: "Button"
+
+ color: activePalette.button; smooth: true
+ width: txtItem.width + 20; height: txtItem.height + 6
+ border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8;
+
+ gradient: Gradient {
+ GradientStop {
+ id: topGrad; position: 0.0
+ color: if (mr.pressed) { activePalette.dark } else { activePalette.light } }
+ GradientStop { position: 1.0; color: activePalette.button }
+ }
+
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: container.clicked() }
+
+ Text {
+ id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+ }
+}
diff --git a/examples/declarative/tutorials/samegame/samegame3/Dialog.qml b/examples/declarative/tutorials/samegame/samegame3/Dialog.qml
new file mode 100644
index 0000000..96dc246
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/Dialog.qml
@@ -0,0 +1,23 @@
+//![0]
+import Qt 4.6
+
+Rectangle {
+ id: page
+ function forceClose() {
+ page.closed();
+ page.opacity = 0;
+ }
+ function show(txt) {
+ myText.text = txt;
+ page.opacity = 1;
+ }
+ signal closed();
+ color: "white"; border.width: 1; width: myText.width + 20; height: 60;
+ opacity: 0
+ opacity: Behavior {
+ NumberAnimation { duration: 1000 }
+ }
+ Text { id: myText; anchors.centerIn: parent; text: "Hello World!" }
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: forceClose(); }
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame3/pics/background.png b/examples/declarative/tutorials/samegame/samegame3/pics/background.png
new file mode 100644
index 0000000..3734a27
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/pics/background.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame3/pics/blueStone.png b/examples/declarative/tutorials/samegame/samegame3/pics/blueStone.png
new file mode 100644
index 0000000..20e43c7
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/pics/blueStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame3/pics/greenStone.png b/examples/declarative/tutorials/samegame/samegame3/pics/greenStone.png
new file mode 100644
index 0000000..b568a19
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/pics/greenStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame3/pics/redStone.png b/examples/declarative/tutorials/samegame/samegame3/pics/redStone.png
new file mode 100644
index 0000000..36b09a2
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/pics/redStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame3/samegame.js b/examples/declarative/tutorials/samegame/samegame3/samegame.js
new file mode 100644
index 0000000..38efb3b
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/samegame.js
@@ -0,0 +1,189 @@
+/* This script file handles the game logic */
+//Note that X/Y referred to here are in game coordinates
+var maxX = 10;//Nums are for tileSize 40
+var maxY = 15;
+var maxIndex = maxX*maxY;
+var board = new Array(maxIndex);
+var tileSrc = "Block.qml";
+var component;
+
+//Index function used instead of a 2D array
+function index(xIdx,yIdx) {
+ return xIdx + (yIdx * maxX);
+}
+
+function initBoard()
+{
+ for(var i = 0; i<maxIndex; i++){
+ //Delete old blocks
+ if(board[i] != null)
+ board[i].destroy();
+ }
+
+ //Calculate board size
+ maxX = Math.floor(gameCanvas.width/gameCanvas.tileSize);
+ maxY = Math.floor(gameCanvas.height/gameCanvas.tileSize);
+ maxIndex = maxY*maxX;
+
+ //Close dialogs
+ dialog.forceClose();
+
+ //Initialize Board
+ board = new Array(maxIndex);
+ gameCanvas.score = 0;
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ for(var yIdx=0; yIdx<maxY; yIdx++){
+ board[index(xIdx,yIdx)] = null;
+ createBlock(xIdx,yIdx);
+ }
+ }
+}
+
+function createBlock(xIdx,yIdx){
+ if(component==null)
+ component = createComponent(tileSrc);
+
+ // Note that we don't wait for the component to become ready. This will
+ // only work if the block QML is a local file. Otherwise the component will
+ // not be ready immediately. There is a statusChanged signal on the
+ // component you could use if you want to wait to load remote files.
+ if(component.isReady){
+ var dynamicObject = component.createObject();
+ if(dynamicObject == null){
+ print("error creating block");
+ print(component.errorsString());
+ return false;
+ }
+ dynamicObject.type = Math.floor(Math.random() * 3);
+ dynamicObject.parent = gameCanvas;
+ dynamicObject.x = xIdx*gameCanvas.tileSize;
+ dynamicObject.y = yIdx*gameCanvas.tileSize;
+ dynamicObject.width = gameCanvas.tileSize;
+ dynamicObject.height = gameCanvas.tileSize;
+ board[index(xIdx,yIdx)] = dynamicObject;
+ }else{//isError or isLoading
+ print("error loading block component");
+ print(component.errorsString());
+ return false;
+ }
+ return true;
+}
+
+var fillFound;//Set after a floodFill call to the number of tiles found
+var floodBoard;//Set to 1 if the floodFill reaches off that node
+//NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope
+//![1]
+function handleClick(x,y)
+{
+ var xIdx = Math.floor(x/gameCanvas.tileSize);
+ var yIdx = Math.floor(y/gameCanvas.tileSize);
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return;
+ if(board[index(xIdx, yIdx)] == null)
+ return;
+ //If it's a valid tile, remove it and all connected (does nothing if it's not connected)
+ floodFill(xIdx,yIdx, -1);
+ if(fillFound <= 0)
+ return;
+ gameCanvas.score += (fillFound - 1) * (fillFound - 1);
+ shuffleDown();
+ victoryCheck();
+}
+//![1]
+
+function floodFill(xIdx,yIdx,type)
+{
+ if(board[index(xIdx, yIdx)] == null)
+ return;
+ var first = false;
+ if(type == -1){
+ first = true;
+ type = board[index(xIdx,yIdx)].type;
+
+ //Flood fill initialization
+ fillFound = 0;
+ floodBoard = new Array(maxIndex);
+ }
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return;
+ if(floodBoard[index(xIdx, yIdx)] == 1 || (!first && type != board[index(xIdx,yIdx)].type))
+ return;
+ floodBoard[index(xIdx, yIdx)] = 1;
+ floodFill(xIdx+1,yIdx,type);
+ floodFill(xIdx-1,yIdx,type);
+ floodFill(xIdx,yIdx+1,type);
+ floodFill(xIdx,yIdx-1,type);
+ if(first==true && fillFound == 0)
+ return;//Can't remove single tiles
+ board[index(xIdx,yIdx)].opacity = 0;
+ board[index(xIdx,yIdx)] = null;
+ fillFound += 1;
+}
+
+function shuffleDown()
+{
+ //Fall down
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ var fallDist = 0;
+ for(var yIdx=maxY-1; yIdx>=0; yIdx--){
+ if(board[index(xIdx,yIdx)] == null){
+ fallDist += 1;
+ }else{
+ if(fallDist > 0){
+ var obj = board[index(xIdx,yIdx)];
+ obj.y += fallDist * gameCanvas.tileSize;
+ board[index(xIdx,yIdx+fallDist)] = obj;
+ board[index(xIdx,yIdx)] = null;
+ }
+ }
+ }
+ }
+ //Fall to the left
+ var fallDist = 0;
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ if(board[index(xIdx, maxY - 1)] == null){
+ fallDist += 1;
+ }else{
+ if(fallDist > 0){
+ for(var yIdx=0; yIdx<maxY; yIdx++){
+ var obj = board[index(xIdx,yIdx)];
+ if(obj == null)
+ continue;
+ obj.x -= fallDist * gameCanvas.tileSize;
+ board[index(xIdx-fallDist,yIdx)] = obj;
+ board[index(xIdx,yIdx)] = null;
+ }
+ }
+ }
+ }
+}
+
+//![2]
+function victoryCheck()
+{
+ //awards bonuses for no tiles left
+ var deservesBonus = true;
+ for(var xIdx=maxX-1; xIdx>=0; xIdx--)
+ if(board[index(xIdx, maxY - 1)] != null)
+ deservesBonus = false;
+ if(deservesBonus)
+ gameCanvas.score += 500;
+ //Checks for game over
+ if(deservesBonus || !(floodMoveCheck(0,maxY-1, -1)))
+ dialog.show("Game Over. Your score is " + gameCanvas.score);
+}
+//![2]
+
+//only floods up and right, to see if it can find adjacent same-typed tiles
+function floodMoveCheck(xIdx, yIdx, type)
+{
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return false;
+ if(board[index(xIdx, yIdx)] == null)
+ return false;
+ var myType = board[index(xIdx, yIdx)].type;
+ if(type == myType)
+ return true;
+ return floodMoveCheck(xIdx + 1, yIdx, myType) ||
+ floodMoveCheck(xIdx, yIdx - 1, board[index(xIdx,yIdx)].type);
+}
diff --git a/examples/declarative/tutorials/samegame/samegame3/samegame.qml b/examples/declarative/tutorials/samegame/samegame3/samegame.qml
new file mode 100644
index 0000000..8bdb428
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame3/samegame.qml
@@ -0,0 +1,62 @@
+//![0]
+import Qt 4.6
+
+Rectangle {
+ id: screen
+ width: 490; height: 720
+
+ SystemPalette { id: activePalette }
+ Script { source: "samegame.js" }
+
+ Item {
+ width: parent.width; anchors.top: parent.top; anchors.bottom: toolbar.top
+
+ Image {
+ id: background
+ anchors.fill: parent; source: "pics/background.png"
+ fillMode: Image.PreserveAspectCrop
+ }
+
+//![1]
+ Item {
+ id: gameCanvas
+ property int score: 0
+ property int tileSize: 40
+
+ z: 20; anchors.centerIn: parent
+ width: parent.width - (parent.width % tileSize);
+ height: parent.height - (parent.height % tileSize);
+
+ MouseRegion {
+ id: gameMR
+ anchors.fill: parent; onClicked: handleClick(mouse.x,mouse.y);
+ }
+ }
+//![1]
+ }
+
+//![2]
+ Dialog { id: dialog; anchors.centerIn: parent; z: 21 }
+//![2]
+
+ Rectangle {
+ id: toolbar
+ color: activePalette.window
+ height: 32; width: parent.width
+ anchors.bottom: screen.bottom
+
+ Button {
+ id: btnA; text: "New Game"; onClicked: initBoard();
+ anchors.left: parent.left; anchors.leftMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Text {
+ id: score
+ text: "Score: " + gameCanvas.score; font.bold: true
+ anchors.right: parent.right; anchors.rightMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+}
+//![0]
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/BoomBlock.qml b/examples/declarative/tutorials/samegame/samegame4/content/BoomBlock.qml
new file mode 100644
index 0000000..2eb2ceb
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/BoomBlock.qml
@@ -0,0 +1,63 @@
+import Qt 4.6
+
+Item { id:block
+ property int type: 0
+ property bool dying: false
+ //![1]
+ property bool spawned: false
+ property int targetX: 0
+ property int targetY: 0
+
+ x: SpringFollow { enabled: spawned; source: targetX; spring: 2; damping: 0.2 }
+ y: SpringFollow { source: targetY; spring: 2; damping: 0.2 }
+ //![1]
+
+ //![2]
+ Image { id: img
+ source: {
+ if(type == 0){
+ "pics/redStone.png";
+ } else if(type == 1) {
+ "pics/blueStone.png";
+ } else {
+ "pics/greenStone.png";
+ }
+ }
+ opacity: 0
+ opacity: Behavior { NumberAnimation { matchProperties:"opacity"; duration: 200 } }
+ anchors.fill: parent
+ }
+ //![2]
+
+ //![3]
+ Particles { id: particles
+ width:1; height:1; anchors.centerIn: parent;
+ emissionRate: 0;
+ lifeSpan: 700; lifeSpanDeviation: 600;
+ angle: 0; angleDeviation: 360;
+ velocity: 100; velocityDeviation:30;
+ source: {
+ if(type == 0){
+ "pics/redStar.png";
+ } else if (type == 1) {
+ "pics/blueStar.png";
+ } else {
+ "pics/greenStar.png";
+ }
+ }
+ }
+ //![3]
+
+ //![4]
+ states: [
+ State{ name: "AliveState"; when: spawned == true && dying == false
+ PropertyChanges { target: img; opacity: 1 }
+ },
+ State{ name: "DeathState"; when: dying == true
+ StateChangeScript { script: particles.burst(50); }
+ PropertyChanges { target: img; opacity: 0 }
+ StateChangeScript { script: block.destroy(1000); }
+ }
+ ]
+ //![4]
+}
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/Button.qml b/examples/declarative/tutorials/samegame/samegame4/content/Button.qml
new file mode 100644
index 0000000..63cd555
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/Button.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+
+ signal clicked
+ property string text: "Button"
+
+ color: activePalette.button; smooth: true
+ width: txtItem.width + 20; height: txtItem.height + 6
+ border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8;
+
+ gradient: Gradient {
+ GradientStop {
+ id: topGrad; position: 0.0
+ color: if (mr.pressed) { activePalette.dark } else { activePalette.light } }
+ GradientStop { position: 1.0; color: activePalette.button }
+ }
+
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: container.clicked() }
+
+ Text {
+ id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+ }
+}
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml b/examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml
new file mode 100644
index 0000000..3371d53
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ function forceClose() {
+ page.closed();
+ page.opacity = 0;
+ }
+ function show(txt) {
+ myText.text = txt;
+ page.opacity = 1;
+ }
+ signal closed();
+ color: "white"; border.width: 1; width: myText.width + 20; height: 60;
+ opacity: 0
+ opacity: Behavior {
+ NumberAnimation { duration: 1000 }
+ }
+ Text { id: myText; anchors.centerIn: parent; text: "Hello World!" }
+ MouseRegion { id: mr; anchors.fill: parent; onClicked: forceClose(); }
+}
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/background.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/background.png
new file mode 100644
index 0000000..3734a27
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/background.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/blueStar.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/blueStar.png
new file mode 100644
index 0000000..ff9588f
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/blueStar.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/blueStone.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/blueStone.png
new file mode 100644
index 0000000..20e43c7
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/blueStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/greenStar.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/greenStar.png
new file mode 100644
index 0000000..cd06854
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/greenStar.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/greenStone.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/greenStone.png
new file mode 100644
index 0000000..b568a19
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/greenStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/redStar.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/redStar.png
new file mode 100644
index 0000000..0a4dffe
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/redStar.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/redStone.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/redStone.png
new file mode 100644
index 0000000..36b09a2
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/redStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/star.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/star.png
new file mode 100644
index 0000000..defbde5
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/star.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/pics/yellowStone.png b/examples/declarative/tutorials/samegame/samegame4/content/pics/yellowStone.png
new file mode 100644
index 0000000..b1ce762
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/pics/yellowStone.png
Binary files differ
diff --git a/examples/declarative/tutorials/samegame/samegame4/content/samegame.js b/examples/declarative/tutorials/samegame/samegame4/content/samegame.js
new file mode 100755
index 0000000..2a0d718
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/content/samegame.js
@@ -0,0 +1,249 @@
+/* This script file handles the game logic */
+//Note that X/Y referred to here are in game coordinates
+var maxX = 10;//Nums are for gameCanvas.tileSize 40
+var maxY = 15;
+var maxIndex = maxX*maxY;
+var board = new Array(maxIndex);
+var tileSrc = "content/BoomBlock.qml";
+//var scoresURL = "http://qtfx-nokia.trolltech.com.au/samegame/scores.php";
+var scoresURL = "";
+var timer;
+var component = createComponent(tileSrc);
+
+//Index function used instead of a 2D array
+function index(xIdx,yIdx) {
+ return xIdx + (yIdx * maxX);
+}
+
+function timeStr(msecs) {
+ var secs = Math.floor(msecs/1000);
+ var m = Math.floor(secs/60);
+ var ret = "" + m + "m " + (secs%60) + "s";
+ return ret;
+}
+
+function getTileSize()
+{
+ return tileSize;
+}
+
+function initBoard()
+{
+ for(var i = 0; i<maxIndex; i++){
+ //Delete old blocks
+ if(board[i] != null)
+ board[i].destroy();
+ }
+
+ //Calculate board size
+ maxX = Math.floor(gameCanvas.width/gameCanvas.tileSize);
+ maxY = Math.floor(gameCanvas.height/gameCanvas.tileSize);
+ maxIndex = maxY*maxX;
+
+ //Close dialogs
+ scoreName.forceClose();
+ dialog.forceClose();
+
+ var a = new Date();
+ //Initialize Board
+ board = new Array(maxIndex);
+ gameCanvas.score = 0;
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ for(var yIdx=0; yIdx<maxY; yIdx++){
+ board[index(xIdx,yIdx)] = null;
+ createBlock(xIdx,yIdx);
+ }
+ }
+ timer = new Date();
+
+ print(timer.valueOf() - a.valueOf());
+}
+
+var fillFound;//Set after a floodFill call to the number of tiles found
+var floodBoard;//Set to 1 if the floodFill reaches off that node
+//NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope
+function handleClick(x,y)
+{
+ var xIdx = Math.floor(x/gameCanvas.tileSize);
+ var yIdx = Math.floor(y/gameCanvas.tileSize);
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return;
+ if(board[index(xIdx, yIdx)] == null)
+ return;
+ //If it's a valid tile, remove it and all connected (does nothing if it's not connected)
+ floodFill(xIdx,yIdx, -1);
+ if(fillFound <= 0)
+ return;
+ gameCanvas.score += (fillFound - 1) * (fillFound - 1);
+ shuffleDown();
+ victoryCheck();
+}
+
+function floodFill(xIdx,yIdx,type)
+{
+ if(board[index(xIdx, yIdx)] == null)
+ return;
+ var first = false;
+ if(type == -1){
+ first = true;
+ type = board[index(xIdx,yIdx)].type;
+
+ //Flood fill initialization
+ fillFound = 0;
+ floodBoard = new Array(maxIndex);
+ }
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return;
+ if(floodBoard[index(xIdx, yIdx)] == 1 || (!first && type != board[index(xIdx,yIdx)].type))
+ return;
+ floodBoard[index(xIdx, yIdx)] = 1;
+ floodFill(xIdx+1,yIdx,type);
+ floodFill(xIdx-1,yIdx,type);
+ floodFill(xIdx,yIdx+1,type);
+ floodFill(xIdx,yIdx-1,type);
+ if(first==true && fillFound == 0)
+ return;//Can't remove single tiles
+ board[index(xIdx,yIdx)].dying = true;
+ board[index(xIdx,yIdx)] = null;
+ fillFound += 1;
+}
+
+function shuffleDown()
+{
+ //Fall down
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ var fallDist = 0;
+ for(var yIdx=maxY-1; yIdx>=0; yIdx--){
+ if(board[index(xIdx,yIdx)] == null){
+ fallDist += 1;
+ }else{
+ if(fallDist > 0){
+ var obj = board[index(xIdx,yIdx)];
+ obj.targetY += fallDist * gameCanvas.tileSize;
+ board[index(xIdx,yIdx+fallDist)] = obj;
+ board[index(xIdx,yIdx)] = null;
+ }
+ }
+ }
+ }
+ //Fall to the left
+ fallDist = 0;
+ for(xIdx=0; xIdx<maxX; xIdx++){
+ if(board[index(xIdx, maxY - 1)] == null){
+ fallDist += 1;
+ }else{
+ if(fallDist > 0){
+ for(yIdx=0; yIdx<maxY; yIdx++){
+ obj = board[index(xIdx,yIdx)];
+ if(obj == null)
+ continue;
+ obj.targetX -= fallDist * gameCanvas.tileSize;
+ board[index(xIdx-fallDist,yIdx)] = obj;
+ board[index(xIdx,yIdx)] = null;
+ }
+ }
+ }
+ }
+}
+
+function victoryCheck()
+{
+ //awards bonuses for no tiles left
+ var deservesBonus = true;
+ for(var xIdx=maxX-1; xIdx>=0; xIdx--)
+ if(board[index(xIdx, maxY - 1)] != null)
+ deservesBonus = false;
+ if(deservesBonus)
+ gameCanvas.score += 500;
+ //Checks for game over
+ if(deservesBonus || !(floodMoveCheck(0,maxY-1, -1))){
+ timer = new Date() - timer;
+ scoreName.show("You won! Please enter your name: ");
+ //dialog.show("Game Over. Your score is " + gameCanvas.score);
+ }
+}
+
+//only floods up and right, to see if it can find adjacent same-typed tiles
+function floodMoveCheck(xIdx, yIdx, type)
+{
+ if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
+ return false;
+ if(board[index(xIdx, yIdx)] == null)
+ return false;
+ var myType = board[index(xIdx, yIdx)].type;
+ if(type == myType)
+ return true;
+ return floodMoveCheck(xIdx + 1, yIdx, myType) ||
+ floodMoveCheck(xIdx, yIdx - 1, board[index(xIdx,yIdx)].type);
+}
+
+function createBlock(xIdx,yIdx){
+ // Note that we don't wait for the component to become ready. This will
+ // only work if the block QML is a local file. Otherwise the component will
+ // not be ready immediately. There is a statusChanged signal on the
+ // component you could use if you want to wait to load remote files.
+ if(component.isReady){
+ var dynamicObject = component.createObject();
+ if(dynamicObject == null){
+ print("error creating block");
+ print(component.errorsString());
+ return false;
+ }
+ dynamicObject.type = Math.floor(Math.random() * 3);
+ dynamicObject.parent = gameCanvas;
+ dynamicObject.x = xIdx*gameCanvas.tileSize;
+ dynamicObject.targetX = xIdx*gameCanvas.tileSize;
+ dynamicObject.targetY = yIdx*gameCanvas.tileSize;
+ dynamicObject.width = gameCanvas.tileSize;
+ dynamicObject.height = gameCanvas.tileSize;
+ dynamicObject.spawned = true;
+ board[index(xIdx,yIdx)] = dynamicObject;
+ }else{//isError or isLoading
+ print("error loading block component");
+ print(component.errorsString());
+ return false;
+ }
+ return true;
+}
+
+//![2]
+function saveHighScore(name) {
+ if(scoresURL!="")
+ sendHighScore(name);
+ //OfflineStorage
+ var db = openDatabaseSync("SameGameScores", "1.0", "Local SameGame High Scores",100);
+ var dataStr = "INSERT INTO Scores VALUES(?, ?, ?, ?)";
+ var data = [name, gameCanvas.score, maxX+"x"+maxY ,Math.floor(timer/1000)];
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(name TEXT, score NUMBER, gridSize TEXT, time NUMBER)');
+ tx.executeSql(dataStr, data);
+
+ var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "12x17" ORDER BY score desc LIMIT 10');
+ var r = "\nHIGH SCORES for a standard sized grid\n\n"
+ for(var i = 0; i < rs.rows.length; i++){
+ r += (i+1)+". " + rs.rows.item(i).name +' got '
+ + rs.rows.item(i).score + ' points in '
+ + rs.rows.item(i).time + ' seconds.\n';
+ }
+ dialog.show(r);
+ }
+ );
+}
+//![2]
+
+//![1]
+function sendHighScore(name) {
+ var postman = new XMLHttpRequest()
+ var postData = "name="+name+"&score="+gameCanvas.score
+ +"&gridSize="+maxX+"x"+maxY +"&time="+Math.floor(timer/1000);
+ postman.open("POST", scoresURL, true);
+ postman.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ postman.onreadystatechange = function() {
+ if (postman.readyState == postman.DONE) {
+ dialog.show("Your score has been uploaded.");
+ }
+ }
+ postman.send(postData);
+}
+//![1]
diff --git a/examples/declarative/tutorials/samegame/samegame4/highscores/README b/examples/declarative/tutorials/samegame/samegame4/highscores/README
new file mode 100644
index 0000000..eaa00fa
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/highscores/README
@@ -0,0 +1 @@
+The SameGame example can interface with a simple PHP script to store XML high score data on a remote server. We do not have a publically accessible server available for this use, but if you have access to a PHP capable webserver you can copy the files (score_data.xml, score.php, score_style.xsl) to it and alter the highscore_server variable at the top of the samegame.js file to point to it.
diff --git a/examples/declarative/tutorials/samegame/samegame4/highscores/score_data.xml b/examples/declarative/tutorials/samegame/samegame4/highscores/score_data.xml
new file mode 100755
index 0000000..c3fd90d
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/highscores/score_data.xml
@@ -0,0 +1,2 @@
+<record><score>1000000</score><name>Alan the Tester</name><gridSize>0x0</gridSize><seconds>0</seconds></record>
+<record><score>6213</score><name>Alan</name><gridSize>12x17</gridSize><seconds>51</seconds></record>
diff --git a/examples/declarative/tutorials/samegame/samegame4/highscores/score_style.xsl b/examples/declarative/tutorials/samegame/samegame4/highscores/score_style.xsl
new file mode 100755
index 0000000..670354c
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/highscores/score_style.xsl
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="/">
+ <html>
+ <head><title>SameGame High Scores</title></head>
+ <body>
+ <h2>SameGame High Scores</h2>
+ <table border="1">
+ <tr bgcolor="lightsteelblue">
+ <th>Name</th>
+ <th>Score</th>
+ <th>Grid Size</th>
+ <th>Time, s</th>
+ </tr>
+ <xsl:for-each select="records/record">
+ <xsl:sort select="score" data-type="number" order="descending"/>
+ <tr>
+ <td><xsl:value-of select="name"/></td>
+ <td><xsl:value-of select="score"/></td>
+ <td><xsl:value-of select="gridSize"/></td>
+ <td><xsl:value-of select="seconds"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/examples/declarative/tutorials/samegame/samegame4/highscores/scores.php b/examples/declarative/tutorials/samegame/samegame4/highscores/scores.php
new file mode 100755
index 0000000..3cceb2d
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/highscores/scores.php
@@ -0,0 +1,34 @@
+<?php
+ $score = $_POST["score"];
+ echo "<html>";
+ echo "<head><title>SameGame High Scores</title></head><body>";
+ if($score > 0){#Sending in a new high score
+ $name = $_POST["name"];
+ $grid = $_POST["gridSize"];
+ $time = $_POST["time"];
+ if($name == "")
+ $name = "Anonymous";
+ //if($grid != "10x10"){
+ //Need a standard, so as to reject others?
+ //}
+ $file = fopen("score_data.xml", "a"); #It's XML. Happy?
+ $ret = fwrite($file, "<record><score>". $score . "</score><name>"
+ . $name . "</name><gridSize>" . $grid . "</gridSize><seconds>"
+ . $time . "</seconds></record>\n");
+ echo "Your score has been recorded. Thanks for playing!";
+ if($ret == False)
+ echo "<br/> There was an error though, so don't expect to see that score again.";
+ }else{#Read high score list
+ #Now uses XSLT to display. So just print the file. With XML cruft added.
+ #Note that firefox at least won't apply the XSLT on a php file. So redirecting
+ $file = fopen("scores.xml", "w");
+ $ret = fwrite($file, '<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n"
+ . '<?xml-stylesheet type="text/xsl" href="score_style.xsl"?>' . "\n"
+ . "<records>\n" . file_get_contents("score_data.xml") . "</records>\n");
+ if($ret == False)
+ echo "There was an internal error. Sorry.";
+ else
+ echo '<script type="text/javascript">window.location.replace("scores.xml")</script>';
+ }
+ echo "</body></html>";
+?>
diff --git a/examples/declarative/tutorials/samegame/samegame4/samegame.qml b/examples/declarative/tutorials/samegame/samegame4/samegame.qml
new file mode 100644
index 0000000..19b929f
--- /dev/null
+++ b/examples/declarative/tutorials/samegame/samegame4/samegame.qml
@@ -0,0 +1,77 @@
+import Qt 4.6
+import "content"
+
+Rectangle {
+ id: screen
+ width: 490; height: 720
+
+ SystemPalette { id: activePalette }
+
+ Item {
+ width: parent.width; anchors.top: parent.top; anchors.bottom: toolBar.top
+
+ Image {
+ id: background
+ anchors.fill: parent; source: "content/pics/background.png"
+ fillMode: Image.PreserveAspectCrop
+ }
+
+ Item {
+ id: gameCanvas
+ property int score: 0
+ property int tileSize: 40
+
+ Script { source: "content/samegame.js" }
+
+ z: 20; anchors.centerIn: parent
+ width: parent.width - (parent.width % getTileSize());
+ height: parent.height - (parent.height % getTileSize());
+
+ MouseRegion {
+ id: gameMR
+ anchors.fill: parent; onClicked: handleClick(mouse.x,mouse.y);
+ }
+ }
+ }
+
+ Dialog { id: dialog; anchors.centerIn: parent; z: 21 }
+ Dialog {
+ id: scoreName; anchors.centerIn: parent; z: 22;
+ Text {
+ id: spacer
+ opacity: 0
+ text: " You won! Please enter your name:"
+ }
+ TextInput {
+ id: editor
+ onAccepted: {
+ if(scoreName.opacity==1&&editor.text!="")
+ saveHighScore(editor.text);
+ scoreName.forceClose();
+ }
+ anchors.verticalCenter: parent.verticalCenter
+ width: 72; focus: true
+ anchors.left: spacer.right
+ }
+ }
+
+ Rectangle {
+ id: toolBar
+ color: activePalette.window
+ height: 32; width: parent.width
+ anchors.bottom: screen.bottom
+
+ Button {
+ id: btnA; text: "New Game"; onClicked: {initBoard();}
+ anchors.left: parent.left; anchors.leftMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Text {
+ id: score
+ text: "Score: " + gameCanvas.score; font.bold: true
+ anchors.right: parent.right; anchors.rightMargin: 3
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+}
diff --git a/examples/declarative/tvtennis/click.wav b/examples/declarative/tvtennis/click.wav
new file mode 100644
index 0000000..26c46f8
--- /dev/null
+++ b/examples/declarative/tvtennis/click.wav
Binary files differ
diff --git a/examples/declarative/tvtennis/paddle.wav b/examples/declarative/tvtennis/paddle.wav
new file mode 100644
index 0000000..604e0e5
--- /dev/null
+++ b/examples/declarative/tvtennis/paddle.wav
Binary files differ
diff --git a/examples/declarative/tvtennis/tvtennis.qml b/examples/declarative/tvtennis/tvtennis.qml
new file mode 100644
index 0000000..4bd5319
--- /dev/null
+++ b/examples/declarative/tvtennis/tvtennis.qml
@@ -0,0 +1,74 @@
+import Qt 4.6
+
+Rectangle {
+ id: page
+ width: 640; height: 480
+ color: "Black"
+
+ // Make a ball to bounce
+ Rectangle {
+ // Add a property for the target y coordinate
+ property int targetY : page.height - 10
+ property var direction : "right"
+
+ id: ball
+ color: "Lime"
+ x: 20; width: 20; height: 20; z: 1
+
+ // Move the ball to the right and back to the left repeatedly
+ x: SequentialAnimation {
+ repeat: true
+ NumberAnimation { to: page.width - 40; duration: 2000 }
+ ScriptAction { script: Qt.playSound('paddle.wav') }
+ PropertyAction { target: ball; property: "direction"; value: "left" }
+ NumberAnimation { to: 20; duration: 2000 }
+ ScriptAction { script: Qt.playSound('paddle.wav') }
+ PropertyAction { target: ball; property: "direction"; value: "right" }
+ }
+
+ // Make y follow the target y coordinate, with a velocity of 200
+ y: SpringFollow { source: ball.targetY; velocity: 200 }
+
+ // Detect the ball hitting the top or bottom of the view and bounce it
+ onYChanged: {
+ if (y <= 0) {
+ Qt.playSound('click.wav');
+ targetY = page.height - 20;
+ } else if (y >= page.height - 20) {
+ Qt.playSound('click.wav');
+ targetY = 0;
+ }
+ }
+ }
+
+ // Place bats to the left and right of the view, following the y
+ // coordinates of the ball.
+ Rectangle {
+ id: leftBat
+ color: "Lime"
+ x: 2; width: 20; height: 90
+ y: SpringFollow {
+ source: ball.y - 45; velocity: 300
+ enabled: ball.direction == 'left'
+ }
+ }
+ Rectangle {
+ id: rightBat
+ color: "Lime"
+ x: page.width - 22; width: 20; height: 90
+ y: SpringFollow {
+ source: ball.y-45; velocity: 300
+ enabled: ball.direction == 'right'
+ }
+ }
+
+ // The rest, to make it look realistic, if neither ever scores...
+ Rectangle { color: "Lime"; x: page.width/2-80; y: 0; width: 40; height: 60 }
+ Rectangle { color: "Black"; x: page.width/2-70; y: 10; width: 20; height: 40 }
+ Rectangle { color: "Lime"; x: page.width/2+40; y: 0; width: 40; height: 60 }
+ Rectangle { color: "Black"; x: page.width/2+50; y: 10; width: 20; height: 40 }
+ Repeater {
+ model: page.height / 20
+ Rectangle { color: "Lime"; x: page.width/2-5; y: index * 20; width: 10; height: 10 }
+ }
+}
diff --git a/examples/declarative/velocity/Day.qml b/examples/declarative/velocity/Day.qml
new file mode 100644
index 0000000..3a7ffa9
--- /dev/null
+++ b/examples/declarative/velocity/Day.qml
@@ -0,0 +1,78 @@
+import Qt 4.6
+
+Rectangle {
+ property alias day: dayText.text
+ property var stickies
+
+ id: page
+ width: 400; height: 500; radius: 7
+ border.color: "black"
+
+ Image { x: 10; y: 10; source: "cork.jpg" }
+
+ Text {
+ id: dayText; x: 20; y: 20
+ height: 40; width: 370
+ font.pointSize: 14; font.bold: true
+ style: Text.Outline; styleColor: "#dedede"
+ }
+
+ Repeater {
+ model: page.stickies
+
+ Item {
+ id: stickyPage
+ x: Math.random() * 200 + 100
+ y: Math.random() * 300 + 50
+ rotation: SpringFollow {
+ source: -flickable.horizontalVelocity / 100
+ spring: 2.0; damping: 0.1
+ }
+
+ Item {
+ id: sticky
+ scale: 0.5
+ Image {
+ id: stickyImage; source: "sticky.png"
+ smooth: true; y: -20; x: 8 + -width * 0.6 / 2; scale: 0.6
+ }
+
+ TextEdit {
+ id: myText; smooth: true; font.pointSize: 28
+ readOnly: false; x: -104; y: 36; wrap: true
+ rotation: -8; text: noteText; width: 195; height: 172
+ }
+
+ Item {
+ y: -20
+ x: stickyImage.x
+ width: stickyImage.width * stickyImage.scale
+ height: stickyImage.height * stickyImage.scale
+ MouseRegion {
+ id: mouse
+ onClicked: { myText.focus = true }
+ anchors.fill: parent
+ drag.target: stickyPage; drag.axis: "XandYAxis"; drag.minimumY: 0; drag.maximumY: 500
+ drag.minimumX: 0; drag.maximumX: 400
+ }
+ }
+ }
+
+ Image {
+ source: "tack.png"
+ x: -width / 2; y: -height * 0.7 / 2; scale: 0.7
+ }
+
+ states: State {
+ name: "pressed"
+ when: mouse.pressed
+ PropertyChanges { target: sticky; rotation: 8; scale: 1 }
+ PropertyChanges { target: page; z: 8 }
+ }
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "rotation,scale"; duration: 200 }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/velocity/cork.jpg b/examples/declarative/velocity/cork.jpg
new file mode 100644
index 0000000..d4d706c
--- /dev/null
+++ b/examples/declarative/velocity/cork.jpg
Binary files differ
diff --git a/examples/declarative/velocity/sticky.png b/examples/declarative/velocity/sticky.png
new file mode 100644
index 0000000..73df3cd
--- /dev/null
+++ b/examples/declarative/velocity/sticky.png
Binary files differ
diff --git a/examples/declarative/velocity/tack.png b/examples/declarative/velocity/tack.png
new file mode 100644
index 0000000..cef2d1c
--- /dev/null
+++ b/examples/declarative/velocity/tack.png
Binary files differ
diff --git a/examples/declarative/velocity/velocity.qml b/examples/declarative/velocity/velocity.qml
new file mode 100644
index 0000000..50d69d8
--- /dev/null
+++ b/examples/declarative/velocity/velocity.qml
@@ -0,0 +1,108 @@
+import Qt 4.6
+
+Rectangle {
+ color: "lightSteelBlue"
+ width: 800; height: 600
+
+ ListModel {
+ id: list
+ ListElement {
+ name: "Sunday"
+ dayColor: "#808080"
+ notes: [
+ ListElement {
+ noteText: "Lunch"
+ },
+ ListElement {
+ noteText: "Party"
+ }
+ ]
+ }
+ ListElement {
+ name: "Monday"
+ dayColor: "blue"
+ notes: [
+ ListElement {
+ noteText: "Pickup kids"
+ },
+ ListElement {
+ noteText: "Checkout kinetic"
+ },
+ ListElement {
+ noteText: "Read email"
+ }
+ ]
+ }
+ ListElement {
+ name: "Tuesday"
+ dayColor: "yellow"
+ notes: [
+ ListElement {
+ noteText: "Walk dog"
+ },
+ ListElement {
+ noteText: "Buy newspaper"
+ }
+ ]
+ }
+ ListElement {
+ name: "Wednesday"
+ dayColor: "purple"
+ notes: [
+ ListElement {
+ noteText: "Cook dinner"
+ },
+ ListElement {
+ noteText: "Eat dinner"
+ }
+ ]
+ }
+ ListElement {
+ name: "Thursday"
+ dayColor: "blue"
+ notes: [
+ ListElement {
+ noteText: "5:30pm Meeting"
+ },
+ ListElement {
+ noteText: "Weed garden"
+ }
+ ]
+ }
+ ListElement {
+ name: "Friday"
+ dayColor: "green"
+ notes: [
+ ListElement {
+ noteText: "Still work"
+ },
+ ListElement {
+ noteText: "Drink"
+ }
+ ]
+ }
+ ListElement {
+ name: "Saturday"
+ dayColor: "orange"
+ notes: [
+ ListElement {
+ noteText: "Drink"
+ },
+ ListElement {
+ noteText: "Drink"
+ }
+ ]
+ }
+ }
+ Flickable {
+ id: flickable
+ anchors.fill: parent; viewportWidth: lay.width
+ Row {
+ id: lay
+ Repeater {
+ model: list
+ Component { Day { day: name; color: dayColor; stickies: notes } }
+ }
+ }
+ }
+}
diff --git a/examples/declarative/webview/autosize.qml b/examples/declarative/webview/autosize.qml
new file mode 100644
index 0000000..1614906
--- /dev/null
+++ b/examples/declarative/webview/autosize.qml
@@ -0,0 +1,60 @@
+import Qt 4.6
+
+// The WebView size is determined by the width, height,
+// preferredWidth, and preferredHeight matchProperties.
+Rectangle {
+ id: rect
+ color: "white"
+ width: 200
+ height: layout.height
+ Column {
+ id: layout
+ spacing: 2
+ WebView {
+ html: "No width defined."
+ Rectangle { color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ width: rect.width
+ html: "The width is full."
+ Rectangle {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ width: rect.width/2
+ html: "The width is half."
+ Rectangle {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ preferredWidth: rect.width/2
+ html: "The preferredWidth is half."
+ Rectangle {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ preferredWidth: rect.width/2
+ html: "The_preferredWidth_is_half."
+ Rectangle {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ WebView {
+ width: rect.width/2
+ html: "The_width_is_half."
+ Rectangle {
+ color: "#10000000"
+ anchors.fill: parent
+ }
+ }
+ }
+}
diff --git a/examples/declarative/webview/content/FieldText.qml b/examples/declarative/webview/content/FieldText.qml
new file mode 100644
index 0000000..6b1d271
--- /dev/null
+++ b/examples/declarative/webview/content/FieldText.qml
@@ -0,0 +1,161 @@
+import Qt 4.6
+
+Item {
+ id: fieldText
+ height: 30
+ property string text: ""
+ property string label: ""
+ property bool mouseGrabbed: false
+ signal confirmed
+ signal cancelled
+ signal startEdit
+
+ Script {
+
+ function edit() {
+ if (!mouseGrabbed) {
+ fieldText.startEdit();
+ fieldText.state='editing';
+ mouseGrabbed=true;
+ }
+ }
+
+ function confirm() {
+ fieldText.state='';
+ fieldText.text = textEdit.text;
+ mouseGrabbed=false;
+ fieldText.confirmed();
+ }
+
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ mouseGrabbed=false;
+ fieldText.cancelled();
+ }
+
+ }
+
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/cancel.png"
+ opacity: 0
+ }
+
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/ok.png"
+ opacity: 0
+ }
+
+ TextInput {
+ id: textEdit
+ text: fieldText.text
+ focus: false
+ anchors.left: parent.left
+ anchors.leftMargin: 0
+ anchors.right: parent.right
+ anchors.rightMargin: 0
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ font.bold: true
+ readOnly: true
+ onAccepted: confirm()
+ Keys.onEscapePressed: reset()
+ }
+
+ Text {
+ id: textLabel
+ x: 5
+ width: parent.width-10
+ anchors.verticalCenter: parent.verticalCenter
+ horizontalAlignment: Text.AlignHCenter
+ color: fieldText.state == "editing" ? "#505050" : "#AAAAAA"
+ font.italic: true
+ font.bold: true
+ text: label
+ opacity: textEdit.text == '' ? 1 : 0
+ opacity: Behavior {
+ NumberAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+
+ MouseRegion {
+ anchors.fill: cancelIcon
+ onClicked: { reset() }
+ }
+
+ MouseRegion {
+ anchors.fill: confirmIcon
+ onClicked: { confirm() }
+ }
+
+ MouseRegion {
+ id: editRegion
+ anchors.fill: textEdit
+ onClicked: { edit() }
+ }
+
+ states: [
+ State {
+ name: "editing"
+ PropertyChanges {
+ target: confirmIcon
+ opacity: 1
+ }
+ PropertyChanges {
+ target: cancelIcon
+ opacity: 1
+ }
+ PropertyChanges {
+ target: textEdit
+ color: "black"
+ readOnly: false
+ focus: true
+ selectionStart: 0
+ selectionEnd: -1
+ }
+ PropertyChanges {
+ target: editRegion
+ opacity: 0
+ }
+ PropertyChanges {
+ target: textEdit.anchors
+ leftMargin: 34
+ }
+ PropertyChanges {
+ target: textEdit.anchors
+ rightMargin: 34
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: ""
+ to: "*"
+ reversible: true
+ NumberAnimation {
+ matchProperties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ property: "color"
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/webview/content/Mapping/Map.qml b/examples/declarative/webview/content/Mapping/Map.qml
new file mode 100644
index 0000000..aae6b5d
--- /dev/null
+++ b/examples/declarative/webview/content/Mapping/Map.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+Item {
+ id: page
+ property real latitude: -34.397
+ property real longitude: 150.644
+ property string address: ""
+ WebView {
+ id: map
+ anchors.fill: parent
+ url: "map.html"
+ javaScriptWindowObjects: QtObject {
+ WebView.windowObjectName: "qml"
+ property real lat: page.latitude
+ property real lng: page.longitude
+ property string address: page.address
+ onAddressChanged: {map.evaluateJavaScript("goToAddress()")}
+ }
+ }
+}
diff --git a/examples/declarative/webview/content/Mapping/map.html b/examples/declarative/webview/content/Mapping/map.html
new file mode 100755
index 0000000..8afa21c
--- /dev/null
+++ b/examples/declarative/webview/content/Mapping/map.html
@@ -0,0 +1,47 @@
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
+<script type="text/javascript">
+ var geocoder
+ var map
+ function goToLatLng(latlng,bounds) {
+ if (map) {
+ map.setCenter(latlng)
+ map.fitBounds(bounds)
+ } else {
+ var myOptions = {
+ zoom: 8,
+ center: latlng,
+ mapTypeId: google.maps.MapTypeId.ROADMAP
+ };
+ map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
+ }
+ }
+ function initialize() {
+ geocoder = new google.maps.Geocoder();
+ if (window.qml.address) {
+ goToAddress()
+ } else {
+ goToLatLng(new google.maps.LatLng(window.qml.lat,window.qml.lng));
+ }
+ }
+ function goToAddress() {
+ if (geocoder) {
+ var req = {
+ address: window.qml.address,
+ }
+ if (map)
+ req.bounds = map.getBounds()
+ geocoder.geocode(req, function(results, status) {
+ if (status == google.maps.GeocoderStatus.OK)
+ goToLatLng(results[0].geometry.location,results[0].geometry.bounds);
+ });
+ }
+ }
+</script>
+</head>
+<body onload="initialize()" leftmargin="0px" topmargin="0px" marginwidth="0px" marginheight="0px">
+ <div id="map_canvas" style="width:100%; height:100%"></div>
+</body>
+</html>
diff --git a/examples/declarative/webview/content/SpinSquare.qml b/examples/declarative/webview/content/SpinSquare.qml
new file mode 100644
index 0000000..466c99e
--- /dev/null
+++ b/examples/declarative/webview/content/SpinSquare.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Item {
+ property var period : 250
+ property var color : "black"
+ id: root
+
+ Item {
+ x: root.width/2
+ y: root.height/2
+ Rectangle {
+ color: root.color
+ x: -width/2
+ y: -height/2
+ width: root.width
+ height: width
+ }
+ rotation: NumberAnimation {
+ from: 0
+ to: 360
+ repeat: true
+ duration: root.period
+ }
+ }
+}
diff --git a/examples/declarative/webview/content/pics/cancel.png b/examples/declarative/webview/content/pics/cancel.png
new file mode 100644
index 0000000..ecc9533
--- /dev/null
+++ b/examples/declarative/webview/content/pics/cancel.png
Binary files differ
diff --git a/examples/declarative/webview/content/pics/ok.png b/examples/declarative/webview/content/pics/ok.png
new file mode 100644
index 0000000..5795f04
--- /dev/null
+++ b/examples/declarative/webview/content/pics/ok.png
Binary files differ
diff --git a/examples/declarative/webview/evalandattach.html b/examples/declarative/webview/evalandattach.html
new file mode 100644
index 0000000..c0992bb
--- /dev/null
+++ b/examples/declarative/webview/evalandattach.html
@@ -0,0 +1,31 @@
+<body bgcolor=gray onload="ftext.confirmed.connect (ftext_confirmed); ">
+ <script>
+ do_it = function () {var oPressed = document.getElementById('pressed');
+ oPressed.innerHTML = 'MouseRegion in QML clicked!';};
+ ftext_confirmed = function () { statusText1.text = ftext.text; var oT = document.getElementById('htmlTextInput'); oT.value = ftext.text }
+ </script>
+ <table border=1>
+ <tr>
+ <td>&nbsp</td>
+ <td id='pressed'></td>
+ </tr>
+ <tr>
+ <td><label for='htmlTextInput'>Type something:</label></td>
+ <td><input type='text' name='htmlTextInput' size='25' id='htmlTextInput'
+ onfocus="statusText2.text = 'Focus in html text input.'"></td>
+ </tr>
+ <tr>
+ <td><label for='htmlButton'>&nbsp;</label></td>
+ <td>
+ <input type='button' id='htmlButton' value='Push'
+ onclick="var oText = document.getElementById('htmlTextInput'); statusText1.text = oText.value; ftext.text = oText.value" />
+ </tr>
+ </table>
+ <p>
+ Below a qml(QFxItem) object inside webkit:
+ </p>
+ <object data=content/FieldText.qml TYPE=application/x-qt-plugin id="ftext_id" text="" label="Cool:" width="200"
+ objectname="ftext">
+ </object>
+</body>
+
diff --git a/examples/declarative/webview/evalandattach.qml b/examples/declarative/webview/evalandattach.qml
new file mode 100644
index 0000000..1b211c9
--- /dev/null
+++ b/examples/declarative/webview/evalandattach.qml
@@ -0,0 +1,54 @@
+import Qt 4.6
+
+Item {
+ height: 640
+ width: 360
+ Text {
+ id: teksti
+ text: webView.statusText1
+ anchors.top: parent.top
+ height: 30
+ anchors.left: parent.left
+ width: parent.width/2
+ }
+
+ Text {
+ id: teksti2
+ text: webView.statusText2
+ anchors.top: parent.top
+ height: 30
+ anchors.left: teksti.right
+ anchors.right: parent.right
+ }
+
+ MouseRegion {
+ anchors.fill: teksti
+ onClicked: { webView.evaluateJavaScript ("do_it()") }
+ }
+
+ WebView {
+ id: webView
+ property alias statusText1: txt.text
+ property alias statusText2: txt2.text
+ anchors.top: teksti.bottom
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ focus: true
+ settings.pluginsEnabled: true
+ javaScriptWindowObjects: [
+ QtObject {
+ id: txt
+ WebView.windowObjectName: "statusText1"
+ property string text: "Click me!"
+ },
+ QtObject {
+ id: txt2
+ WebView.windowObjectName: "statusText2"
+ property string text: ""
+ }
+ ]
+ url: "evalandattach.html"
+ }
+
+}
diff --git a/examples/declarative/webview/googleMaps.qml b/examples/declarative/webview/googleMaps.qml
new file mode 100644
index 0000000..b5b13bb
--- /dev/null
+++ b/examples/declarative/webview/googleMaps.qml
@@ -0,0 +1,31 @@
+// This example demonstrates how Web services such as Google Maps can be
+// abstracted as QML types. Here we have a "Mapping" module with a "Map"
+// type. The Map type has an address property. Setting that property moves
+// the map. The underlying implementation uses WebView and the Google Maps
+// API, but users from QML don't need to understand the implementation in
+// order to create a Map.
+
+import Qt 4.6
+import "content/Mapping"
+
+Map {
+ id: map
+ width: 300
+ height: 300
+ address: "Paris"
+ Rectangle {
+ color: "white"
+ width: input.width + 20
+ height: input.height + 4
+ radius: 5
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 5
+ x: 70
+ TextInput {
+ id: input
+ text: map.address
+ anchors.centerIn: parent
+ Keys.onReturnPressed: map.address = input.text
+ }
+ }
+}
diff --git a/examples/declarative/webview/inline-html.qml b/examples/declarative/webview/inline-html.qml
new file mode 100644
index 0000000..23b4555
--- /dev/null
+++ b/examples/declarative/webview/inline-html.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+// Inline HTML with loose formatting can be
+// set on the html property.
+WebView {
+ html:"\
+ <body bgcolor=white>\
+ <table border=1>\
+ <tr><th><th>One<th>Two<th>Three\
+ <tr><th>1<td>X<td>1<td>X\
+ <tr><th>2<td>0<td>X<td>0\
+ <tr><th>3<td>X<td>1<td>X\
+ </table>"
+}
diff --git a/examples/declarative/webview/newwindows.html b/examples/declarative/webview/newwindows.html
new file mode 100644
index 0000000..f169599
--- /dev/null
+++ b/examples/declarative/webview/newwindows.html
@@ -0,0 +1,3 @@
+<h1>Multiple windows...</h1>
+
+<a target="_blank" href="newwindows.html">Popup!</a>
diff --git a/examples/declarative/webview/newwindows.qml b/examples/declarative/webview/newwindows.qml
new file mode 100644
index 0000000..5dd4cd5
--- /dev/null
+++ b/examples/declarative/webview/newwindows.qml
@@ -0,0 +1,30 @@
+// Demonstrates opening new WebViews from HTML
+//
+// Note that to open windows from JavaScript, you will need to
+// allow it on WebView with settings.javascriptCanOpenWindows: true
+
+import Qt 4.6
+
+Grid {
+ columns: 3
+ id: pages
+ height: 300; width: 600
+
+ Component {
+ id: webViewPage
+ Rectangle {
+ width: webView.width
+ height: webView.height
+ border.color: "gray"
+
+ WebView {
+ id: webView
+ newWindowComponent: webViewPage
+ newWindowParent: pages
+ url: "newwindows.html"
+ }
+ }
+ }
+
+ Loader { sourceComponent: webViewPage }
+}
diff --git a/examples/declarative/webview/qml-in-html.qml b/examples/declarative/webview/qml-in-html.qml
new file mode 100644
index 0000000..a2f2f2a
--- /dev/null
+++ b/examples/declarative/webview/qml-in-html.qml
@@ -0,0 +1,32 @@
+import Qt 4.6
+
+// The WebView supports QML data through the HTML OBJECT tag
+Rectangle {
+ color:"blue"
+ Flickable {
+ width: parent.width
+ height: parent.height/2
+ viewportWidth: web.width*web.scale
+ viewportHeight: web.height*web.scale
+ WebView {
+ id: web
+ width: 250
+ height: 420
+ zoomFactor: 0.75
+ smoothCache: true
+ settings.pluginsEnabled: true
+ html: "<html>\
+ <body bgcolor=white>\
+ These are QML plugins, shown in a QML WebView via HTML OBJECT tags, all scaled to 75%\
+ and placed in a Flickable area...\
+ <table border=1>\
+ <tr><th>Duration <th>Color <th>Plugin\
+ <tr><td>500 <td>red <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=500 color=red />\
+ <tr><td>2000 <td>blue <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=2000 color=blue />\
+ <tr><td>1000 <td>green <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=1000 color=green />\
+ </table>\
+ </body>\
+ </html>"
+ }
+ }
+}
diff --git a/examples/declarative/webview/transparent.qml b/examples/declarative/webview/transparent.qml
new file mode 100644
index 0000000..9332f3e
--- /dev/null
+++ b/examples/declarative/webview/transparent.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+// The WebView background is transparent
+// if the HTML does not specify a background
+Rectangle {
+ color: "green"
+ width: web.width
+ height: web.height
+ WebView {
+ id: web
+ html: "Hello <b>World!</b>"
+ }
+}
diff --git a/examples/declarative/workerscript/workerscript.js b/examples/declarative/workerscript/workerscript.js
new file mode 100644
index 0000000..f76471f
--- /dev/null
+++ b/examples/declarative/workerscript/workerscript.js
@@ -0,0 +1,15 @@
+var lastx = 0;
+var lasty = 0;
+
+WorkerScript.onMessage = function(message) {
+ var ydiff = message.y - lasty;
+ var xdiff = message.x - lastx;
+
+ var total = Math.sqrt(ydiff * ydiff + xdiff * xdiff);
+
+ lastx = message.x;
+ lasty = message.y;
+
+ WorkerScript.sendMessage( {xmove: xdiff, ymove: ydiff, move: total} );
+}
+
diff --git a/examples/declarative/workerscript/workerscript.qml b/examples/declarative/workerscript/workerscript.qml
new file mode 100644
index 0000000..e36d4d4
--- /dev/null
+++ b/examples/declarative/workerscript/workerscript.qml
@@ -0,0 +1,47 @@
+import Qt 4.6
+
+Rectangle {
+ width: 480; height: 320;
+
+ WorkerScript {
+ id: myWorker
+ source: "workerscript.js"
+
+ onMessage: {
+ print("Moved " + messageObject.xmove + " along the X axis.");
+ print("Moved " + messageObject.ymove + " along the Y axis.");
+ print("Moved " + messageObject.move + " pixels.");
+ }
+ }
+
+ Rectangle {
+ width: 200; height: 200
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ color: "red"
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: myWorker.sendMessage( { rectangle: "red", x: mouse.x, y: mouse.y } );
+ }
+ }
+
+ Rectangle {
+ width: 200; height: 200
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ color: "blue"
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: myWorker.sendMessage( { rectangle: "blue", x: mouse.x, y: mouse.y } );
+ }
+ }
+
+ Text {
+ text: "Click a Rectangle!"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 50
+ }
+}
diff --git a/examples/declarative/xmldata/daringfireball.qml b/examples/declarative/xmldata/daringfireball.qml
new file mode 100644
index 0000000..456f309
--- /dev/null
+++ b/examples/declarative/xmldata/daringfireball.qml
@@ -0,0 +1,45 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 600; height: 600
+
+ XmlListModel {
+ id: feedModel
+ source: "http://daringfireball.net/index.xml"
+ query: "/feed/entry"
+ namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';"
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "tagline"; query: "author/name/string()" }
+ XmlRole { name: "content"; query: "content/string()" }
+ }
+
+ Component {
+ id: feedDelegate
+ Item {
+ height: childrenRect.height + 20
+ Text {
+ id: titleText
+ x: 10
+ text: title; font.bold: true
+ }
+ Text {
+ text: 'by ' + tagline
+ anchors.left: titleText.right; anchors.leftMargin: 10
+ font.italic: true
+ }
+ Text {
+ x: 10
+ text: content
+ anchors.top: titleText.bottom
+ width: 580; wrap: true
+ onLinkActivated: { console.log('link clicked: ' + link) }
+ }
+ }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: feedModel; delegate: feedDelegate
+ }
+}
diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml
new file mode 100644
index 0000000..bd14516
--- /dev/null
+++ b/examples/declarative/xmldata/yahoonews.qml
@@ -0,0 +1,79 @@
+import Qt 4.6
+
+Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0; color: "black" }
+ GradientStop { position: 1.0; color: "#AAAAAA" }
+ }
+ width: 600; height: 600
+
+ XmlListModel {
+ id: feedModel
+ source: "http://rss.news.yahoo.com/rss/oceania"
+ query: "/rss/channel/item"
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "link"; query: "link/string()" }
+ XmlRole { name: "description"; query: "description/string()" }
+ }
+
+ Component {
+ id: feedDelegate
+ Item {
+ id: delegate
+ height: wrapper.height + 10
+
+ MouseRegion {
+ anchors.fill: wrapper
+ onPressed: delegate.ListView.view.currentIndex = index;
+ onClicked: if (wrapper.state == 'Details') wrapper.state = ''; else wrapper.state = 'Details';
+ }
+
+ Rectangle {
+ id: wrapper
+ y: 5; height: titleText.height + 10; width: 580
+ color: "#F0F0F0"; radius: 5
+ Text {
+ id: titleText
+ x: 10; y: 5
+ text: '<a href=\'' + link + '\'>' + title + '</a>'
+ font.bold: true; font.family: "Helvetica"; font.pointSize: 14
+ onLinkActivated: { console.log('link clicked: ' + link) }
+ }
+
+ Text {
+ x: 10
+ id: descriptionText
+ text: description
+ width: 560
+ wrap: true
+ font.family: "Helvetica"
+ anchors.top: titleText.bottom
+ anchors.topMargin: 5
+ opacity: 0
+ }
+
+ states: State {
+ name: "Details"
+ PropertyChanges { target: wrapper; height: childrenRect.height + 10 }
+ PropertyChanges { target: descriptionText; opacity: 1 }
+ }
+
+ transitions: Transition {
+ from: "*"; to: "Details"; reversible: true
+ SequentialAnimation {
+ NumberAnimation { duration: 200; matchProperties: "height"; easing: "easeOutQuad" }
+ NumberAnimation { duration: 200; matchProperties: "opacity" }
+ }
+ }
+ }
+ }
+ }
+
+ ListView {
+ id: list
+ x: 10; y: 10
+ width: parent.width - 20; height: parent.height - 20
+ model: feedModel
+ delegate: feedDelegate
+ }
+}
diff --git a/examples/declarative/xmlhttprequest/test.qml b/examples/declarative/xmlhttprequest/test.qml
new file mode 100644
index 0000000..18e328b
--- /dev/null
+++ b/examples/declarative/xmlhttprequest/test.qml
@@ -0,0 +1,36 @@
+import Qt 4.6
+
+Rectangle {
+ width: 800; height: 600
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: {
+
+ var doc = new XMLHttpRequest();
+ doc.onreadystatechange = function() {
+ if (doc.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ console.log("Headers -->");
+ console.log(doc.getAllResponseHeaders ());
+ console.log("Last modified -->");
+ console.log(doc.getResponseHeader ("Last-Modified"));
+ }
+ else if (doc.readyState == XMLHttpRequest.DONE) {
+
+ var a = doc.responseXML.documentElement;
+ for (var ii = 0; ii < a.childNodes.length; ++ii) {
+ console.log(a.childNodes[ii].nodeName);
+ }
+ console.log("Headers -->");
+ console.log(doc.getAllResponseHeaders ());
+ console.log("Last modified -->");
+ console.log(doc.getResponseHeader ("Last-Modified"));
+
+ }
+ }
+
+ doc.open("GET", "test.xml");
+ doc.send();
+ }
+ }
+}
diff --git a/examples/declarative/xmlhttprequest/test.xml b/examples/declarative/xmlhttprequest/test.xml
new file mode 100644
index 0000000..8b7f1e1
--- /dev/null
+++ b/examples/declarative/xmlhttprequest/test.xml
@@ -0,0 +1,5 @@
+<data>
+ <element1 />
+ <element2 />
+</data>
+
diff --git a/examples/draganddrop/draggabletext/dragwidget.cpp b/examples/draganddrop/draggabletext/dragwidget.cpp
index 0ada3ac..1fd40be 100644
--- a/examples/draganddrop/draggabletext/dragwidget.cpp
+++ b/examples/draganddrop/draggabletext/dragwidget.cpp
@@ -82,7 +82,7 @@ DragWidget::DragWidget(QWidget *parent)
void DragWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasText()) {
- if (children().contains(event->source())) {
+ if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
diff --git a/examples/examples.pro b/examples/examples.pro
index 3678cc0..8941eae 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -45,7 +45,6 @@ contains(QT_CONFIG, multimedia) {
contains(QT_CONFIG, script): SUBDIRS += script
contains(QT_CONFIG, phonon):!static: SUBDIRS += phonon
-contains(QT_CONFIG, webkit): SUBDIRS += webkit
embedded:SUBDIRS += qws
!wince*:!symbian: {
!contains(QT_EDITION, Console):contains(QT_BUILD_PARTS, tools):SUBDIRS += designer
diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp
index 8cc9948..fbf4dc4 100644
--- a/examples/multimedia/audioinput/audioinput.cpp
+++ b/examples/multimedia/audioinput/audioinput.cpp
@@ -213,6 +213,9 @@ InputTest::InputTest()
if(format.sampleSize() != 16) {
qWarning()<<"audio device doesn't support 16 bit samples, example cannot run";
+ audioInput = 0;
+ button->setDisabled(true);
+ button2->setDisabled(true);
return;
}
diff --git a/examples/multimedia/audiooutput/audiooutput.cpp b/examples/multimedia/audiooutput/audiooutput.cpp
index 0c57f4d..b44accd 100644
--- a/examples/multimedia/audiooutput/audiooutput.cpp
+++ b/examples/multimedia/audiooutput/audiooutput.cpp
@@ -179,6 +179,9 @@ AudioTest::AudioTest()
if(settings.sampleSize() != 16) {
qWarning()<<"audio device doesn't support 16 bit samples, example cannot run";
+ button->setDisabled(true);
+ button2->setDisabled(true);
+ audioOutput = 0;
return;
}
diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf
index 9df48f5..aab766d 100644
--- a/mkspecs/common/symbian/symbian.conf
+++ b/mkspecs/common/symbian/symbian.conf
@@ -75,21 +75,23 @@ QMAKE_LIBS_COMPAT =
QMAKE_LIBS_QT_ENTRY = -llibcrt0.lib
QMAKE_LIBS_S60 = -lavkon
-contains(QMAKE_HOST.os, "Windows"):!isEmpty(QMAKE_SH) | unix {
+!contains(QMAKE_HOST.os, "Windows")|!isEmpty(QMAKE_SH) {
QMAKE_COPY = cp
QMAKE_COPY_DIR = cp -r
QMAKE_MOVE = mv
QMAKE_DEL_FILE = rm -f
QMAKE_MKDIR = mkdir
QMAKE_DEL_DIR = rmdir
+ QMAKE_DEL_TREE = rmdir /s /q
QMAKE_CHK_DIR_EXISTS = test -d
} else {
QMAKE_COPY = copy /y
QMAKE_COPY_DIR = xcopy /s /q /y /i
QMAKE_MOVE = move
- QMAKE_DEL_FILE = del
+ QMAKE_DEL_FILE = del 2> NUL
QMAKE_MKDIR = mkdir
QMAKE_DEL_DIR = rmdir
+ QMAKE_DEL_TREE = rm -rf
QMAKE_CHK_DIR_EXISTS = if not exist
}
@@ -154,3 +156,19 @@ exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.0.sis
MMP_RULES -= PAGED
}
}
+
+QMAKE_CXXFLAGS_FAST_VFP.ARMCC = --fpmode fast
+# [TODO] QMAKE_CXXFLAGS_FAST_VFP.GCCE =
+
+symbian {
+ armfpu = $$find(MMP_RULES, "ARMFPU")
+ !isEmpty(armfpu) {
+ vfpv2 = $$find(MMP_RULES, "vfpv2")
+ !isEmpty(vfpv2) {
+ # we will respect fpu setting obtained from configure, but,
+ # if vfpv2 or softvfp+vfpv2 used we want to force RunFast VFP mode
+ QMAKE_CXXFLAGS.ARMCC += $${QMAKE_CXXFLAGS_FAST_VFP.ARMCC}
+ # [TODO] QMAKE_CXXFLAGS.GCCE += $${QMAKE_CXXFLAGS_FAST_VFP.GCCE}
+ }
+ }
+} \ No newline at end of file
diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf
index 42ce1bc..e4b7dae 100644
--- a/mkspecs/features/moc.prf
+++ b/mkspecs/features/moc.prf
@@ -97,7 +97,7 @@ equals(MOC_DIR, .) {
}
#auto depend on moc
-unix:!no_mocdepend {
+unix:!symbian:!no_mocdepend {
moc_source.depends += $$first(QMAKE_MOC)
moc_header.depends += $$first(QMAKE_MOC)
!contains(TARGET, moc) { #auto build moc
diff --git a/mkspecs/features/qttest_p4.prf b/mkspecs/features/qttest_p4.prf
index 525e7b2..e0b22f2 100644
--- a/mkspecs/features/qttest_p4.prf
+++ b/mkspecs/features/qttest_p4.prf
@@ -13,23 +13,19 @@ symbian:{
# prefix test binary with tst_
!contains(TARGET, ^tst_.*):TARGET = $$join(TARGET,,"tst_")
-########################################################################
-# Use install rule to run test application.
-# This lets you do 'make install' on a test to both build and run it,
-# and lets you easily build and run all tests from the parent directory.
-# ----------------------------------------------------------------------
-runme.files =
-runme.path = .
-!isEmpty(DESTDIR): runme.commands = cd ./$(DESTDIR) &&
-macx: runme.commands += ./$(QMAKE_TARGET).app/Contents/MacOS/$(QMAKE_TARGET)
-else:unix: runme.commands += ./$(QMAKE_TARGET)
+check.files =
+check.path = .
+!isEmpty(DESTDIR): check.commands = cd ./$(DESTDIR) &&
+macx: check.commands += ./$(QMAKE_TARGET).app/Contents/MacOS/$(QMAKE_TARGET)
+else:unix: check.commands += ./$(QMAKE_TARGET)
else:win32: {
- CONFIG(debug, debug|release):runme.commands += debug\\$(QMAKE_TARGET)
- else:runme.commands += release\\$(QMAKE_TARGET)
+ CONFIG(debug, debug|release):check.commands += debug\\$(QMAKE_TARGET)
+ else:check.commands += release\\$(QMAKE_TARGET)
}
-embedded: runme.commands += -qws
-INSTALLS += runme
+embedded: check.commands += -qws
+QMAKE_EXTRA_TARGETS += check
-########################################################################
+target.path += $$[QT_INSTALL_PREFIX]/tests/qt4
+INSTALLS += target
diff --git a/mkspecs/features/symbian/def_files.prf b/mkspecs/features/symbian/def_files.prf
index c29d4ec..48d91aa 100644
--- a/mkspecs/features/symbian/def_files.prf
+++ b/mkspecs/features/symbian/def_files.prf
@@ -3,24 +3,32 @@
CONFIG -= def_files_disabled
-!isEmpty(defFilePath) {
- defBlock = \
- "$${LITERAL_HASH}ifdef WINSCW" \
- "DEFFILE $$defFilePath/bwins/$${TARGET}.def" \
- "$${LITERAL_HASH}elif defined EABI" \
- "DEFFILE $$defFilePath/eabi/$${TARGET}.def" \
- "$${LITERAL_HASH}endif"
-
- MMP_RULES += defBlock
-} else {
- # If defFilePath is not defined, then put the folders containing the DEF files at the
- # same level as the .pro (and generated MMP) file(s)
- defBlock = \
- "$${LITERAL_HASH}ifdef WINSCW" \
- "DEFFILE ./bwins/$${TARGET}.def" \
- "$${LITERAL_HASH}elif defined EABI" \
- "DEFFILE ./eabi/$${TARGET}.def" \
- "$${LITERAL_HASH}endif"
-
- MMP_RULES += defBlock
+# Firstly, if the MMP_RULES already contain a defBlock variable, don't generate another one
+# (this bit is slightly magic, because it depends upon everyone creating their DEFFILE statements
+# in a defBlock variable; but otherwise we have to expand MMP_RULES then scan for the DEFFILE keyword)
+!contains(MMP_RULES, defBlock) {
+ # Apps are executables on Symbian, so don't have exports, and therefore don't have DEF files
+ # Plugins use standard DEF files, which qmake generates, so shouldn't be using these DEFFILE
+ # statements - they use the qmake generated statements instead
+ # Static libraries obviously don't have DEF files, as they don't take part in dynamic linkage
+ !contains(TEMPLATE, app):!contains(CONFIG, plugin):!contains(CONFIG, staticlib): {
+ !isEmpty(defFilePath) {
+ defBlock = \
+ "$${LITERAL_HASH}ifdef WINSCW" \
+ "DEFFILE $$defFilePath/bwins/$${TARGET}.def" \
+ "$${LITERAL_HASH}elif defined EABI" \
+ "DEFFILE $$defFilePath/eabi/$${TARGET}.def" \
+ "$${LITERAL_HASH}endif"
+ } else {
+ # If defFilePath is not defined, then put the folders containing the DEF files at the
+ # same level as the .pro (and generated MMP) file(s)
+ defBlock = \
+ "$${LITERAL_HASH}ifdef WINSCW" \
+ "DEFFILE ./bwins/$${TARGET}.def" \
+ "$${LITERAL_HASH}elif defined EABI" \
+ "DEFFILE ./eabi/$${TARGET}.def" \
+ "$${LITERAL_HASH}endif"
+ }
+ MMP_RULES += defBlock
+ }
}
diff --git a/mkspecs/features/symbian/def_files_disabled.prf b/mkspecs/features/symbian/def_files_disabled.prf
index d5c9505..557c5e3 100644
--- a/mkspecs/features/symbian/def_files_disabled.prf
+++ b/mkspecs/features/symbian/def_files_disabled.prf
@@ -2,6 +2,12 @@
CONFIG -= def_files
-# with EXPORTUNFROZEN enabled, new exports are included in the dll without
-# needing to run abld/sbs freeze
-MMP_RULES += EXPORTUNFROZEN
+# See def_files.prf for reasoning on the slight nastiness of this
+!contains(MMP_RULES, defBlock) {
+ # See def_files.prf for reasoning for excluding target types and configs below
+ !contains(TEMPLATE, app):!contains(CONFIG, plugin):!contains(CONFIG, staticlib): {
+ # with EXPORTUNFROZEN enabled, new exports are included in the dll and dso/lib without
+ # needing to run abld/sbs freeze
+ MMP_RULES += EXPORTUNFROZEN
+ }
+}
diff --git a/mkspecs/linux-g++-x11egl/qmake.conf b/mkspecs/linux-g++-x11egl/qmake.conf
new file mode 100644
index 0000000..593f120
--- /dev/null
+++ b/mkspecs/linux-g++-x11egl/qmake.conf
@@ -0,0 +1,30 @@
+#
+# qmake configuration for linux-g++
+#
+
+MAKEFILE_GENERATOR = UNIX
+TEMPLATE = app
+CONFIG += qt warn_on release incremental link_prl
+QT += core gui
+QMAKE_INCREMENTAL_STYLE = sublib
+
+include(../common/g++.conf)
+include(../common/linux.conf)
+load(qt_config)
+
+QMAKE_INCDIR_EGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
+QMAKE_LIBDIR_EGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+QMAKE_LIBS_EGL = -lGLESv2 -lEGL
+
+QMAKE_INCDIR_OPENGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
+QMAKE_INCDIR_OPENGL_QT = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
+
+QMAKE_LIBDIR_OPENGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+QMAKE_LIBDIR_OPENGL_QT = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+
+QMAKE_LIBS_OPENGL = -lGLESv2 -lEGL
+QMAKE_LIBS += -Wl,-rpath=$(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+
+QMAKE_LIBS_OPENGL_QT = -lGLESv2 -lEGL
+
+QMAKE_RPATH = -Wl,-rpath,
diff --git a/mkspecs/linux-g++-x11egl/qplatformdefs.h b/mkspecs/linux-g++-x11egl/qplatformdefs.h
new file mode 100644
index 0000000..1430916
--- /dev/null
+++ b/mkspecs/linux-g++-x11egl/qplatformdefs.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMDEFS_H
+#define QPLATFORMDEFS_H
+
+// Get Qt defines/settings
+
+#include "qglobal.h"
+
+// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs
+
+// 1) need to reset default environment if _BSD_SOURCE is defined
+// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0
+// 3) it seems older glibc need this to include the X/Open stuff
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <unistd.h>
+
+
+// We are hot - unistd.h should have turned on the specific APIs we requested
+
+#include <features.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <dlfcn.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/ipc.h>
+#include <sys/time.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#ifndef QT_NO_IPV6IFNAME
+#include <net/if.h>
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_STATBUF struct stat64
+#define QT_STATBUF4TSTAT struct stat64
+#define QT_STAT ::stat64
+#define QT_FSTAT ::fstat64
+#define QT_LSTAT ::lstat64
+#define QT_OPEN ::open64
+#define QT_TRUNCATE ::truncate64
+#define QT_FTRUNCATE ::ftruncate64
+#define QT_LSEEK ::lseek64
+#else
+#define QT_STATBUF struct stat
+#define QT_STATBUF4TSTAT struct stat
+#define QT_STAT ::stat
+#define QT_FSTAT ::fstat
+#define QT_LSTAT ::lstat
+#define QT_OPEN ::open
+#define QT_TRUNCATE ::truncate
+#define QT_FTRUNCATE ::ftruncate
+#define QT_LSEEK ::lseek
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_FOPEN ::fopen64
+#define QT_FSEEK ::fseeko64
+#define QT_FTELL ::ftello64
+#define QT_FGETPOS ::fgetpos64
+#define QT_FSETPOS ::fsetpos64
+#define QT_FPOS_T fpos64_t
+#define QT_OFF_T off64_t
+#else
+#define QT_FOPEN ::fopen
+#define QT_FSEEK ::fseek
+#define QT_FTELL ::ftell
+#define QT_FGETPOS ::fgetpos
+#define QT_FSETPOS ::fsetpos
+#define QT_FPOS_T fpos_t
+#define QT_OFF_T long
+#endif
+
+#define QT_STAT_REG S_IFREG
+#define QT_STAT_DIR S_IFDIR
+#define QT_STAT_MASK S_IFMT
+#define QT_STAT_LNK S_IFLNK
+#define QT_SOCKET_CONNECT ::connect
+#define QT_SOCKET_BIND ::bind
+#define QT_FILENO fileno
+#define QT_CLOSE ::close
+#define QT_READ ::read
+#define QT_WRITE ::write
+#define QT_ACCESS ::access
+#define QT_GETCWD ::getcwd
+#define QT_CHDIR ::chdir
+#define QT_MKDIR ::mkdir
+#define QT_RMDIR ::rmdir
+#define QT_OPEN_LARGEFILE O_LARGEFILE
+#define QT_OPEN_RDONLY O_RDONLY
+#define QT_OPEN_WRONLY O_WRONLY
+#define QT_OPEN_RDWR O_RDWR
+#define QT_OPEN_CREAT O_CREAT
+#define QT_OPEN_TRUNC O_TRUNC
+#define QT_OPEN_APPEND O_APPEND
+
+#define QT_SIGNAL_RETTYPE void
+#define QT_SIGNAL_ARGS int
+#define QT_SIGNAL_IGNORE SIG_IGN
+
+#if defined(__GLIBC__) && (__GLIBC__ >= 2)
+#define QT_SOCKLEN_T socklen_t
+#else
+#define QT_SOCKLEN_T int
+#endif
+
+#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
+#define QT_SNPRINTF ::snprintf
+#define QT_VSNPRINTF ::vsnprintf
+#endif
+
+
+#endif // QPLATFORMDEFS_H
diff --git a/mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf b/mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf
new file mode 100644
index 0000000..3611421
--- /dev/null
+++ b/mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf
@@ -0,0 +1,20 @@
+#
+# qmake configuration for building with arm-none-linux-gnueabi-g++
+#
+
+include(../../common/g++.conf)
+include(../../common/linux.conf)
+include(../../common/qws.conf)
+
+# modifications to g++.conf
+QMAKE_CC = arm-none-linux-gnueabi-gcc
+QMAKE_CXX = arm-none-linux-gnueabi-g++
+QMAKE_LINK = arm-none-linux-gnueabi-g++
+QMAKE_LINK_SHLIB = arm-none-linux-gnueabi-g++
+
+# modifications to linux.conf
+QMAKE_AR = arm-none-linux-gnueabi-ar cqs
+QMAKE_OBJCOPY = arm-none-linux-gnueabi-objcopy
+QMAKE_STRIP = arm-none-linux-gnueabi-strip
+
+load(qt_config)
diff --git a/mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h b/mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h
new file mode 100644
index 0000000..60e0f5e
--- /dev/null
+++ b/mkspecs/qws/linux-arm-gnueabi-g++/qplatformdefs.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../linux-g++/qplatformdefs.h"
diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf
index 78c947d..fcc7691 100644
--- a/mkspecs/win32-icc/qmake.conf
+++ b/mkspecs/win32-icc/qmake.conf
@@ -4,7 +4,7 @@
# Written for Intel C++
#
-MAKEFILE_GENERATOR = MSVC
+MAKEFILE_GENERATOR = MSVC.NET
TEMPLATE = app
CONFIG += qt warn_on release incremental flat link_prl copy_dir_files debug_and_release debug_and_release_target
QT += core gui
diff --git a/mkspecs/win32-msvc.net/qmake.conf b/mkspecs/win32-msvc.net/qmake.conf
deleted file mode 100644
index 89fa00d..0000000
--- a/mkspecs/win32-msvc.net/qmake.conf
+++ /dev/null
@@ -1,89 +0,0 @@
-#
-# qmake configuration for win32-msvc.net (used by 2002 & 2003 before, but now deprecated. Use win32-msvc2002 or win32-msvc2003 instead)
-#
-# Written for Microsoft C++.NET
-#
-!build_pass:message("The mkspec/win32-msvc.net is now deprecated, use win32-msvc2002 or win32-msvc2003")
-
-MAKEFILE_GENERATOR = MSVC.NET
-TEMPLATE = app
-CONFIG += qt warn_on release incremental flat link_prl precompile_header autogen_precompile_source copy_dir_files debug_and_release debug_and_release_target
-QT += core gui
-DEFINES += UNICODE WIN32 QT_LARGEFILE_SUPPORT
-QMAKE_COMPILER_DEFINES += _MSC_VER=1300 WIN32
-
-QMAKE_CC = cl
-QMAKE_LEX = flex
-QMAKE_LEXFLAGS =
-QMAKE_YACC = byacc
-QMAKE_YACCFLAGS = -d
-QMAKE_CFLAGS = -nologo -Zm300
-QMAKE_CFLAGS_WARN_ON = -W3
-QMAKE_CFLAGS_WARN_OFF = -W0
-QMAKE_CFLAGS_RELEASE = -O2 -MD
-QMAKE_CFLAGS_DEBUG = -Zi -MDd
-QMAKE_CFLAGS_YACC =
-
-QMAKE_CXX = $$QMAKE_CC
-QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
-QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -w34100 -w34189
-QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
-QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
-QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
-QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
-QMAKE_CXXFLAGS_STL_ON = -EHsc
-QMAKE_CXXFLAGS_STL_OFF =
-QMAKE_CXXFLAGS_RTTI_ON = -GR
-QMAKE_CXXFLAGS_RTTI_OFF =
-QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHsc
-QMAKE_CXXFLAGS_EXCEPTIONS_OFF =
-
-QMAKE_INCDIR =
-QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS]
-QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS]
-
-QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$obj $src
-QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
-QMAKE_RUN_CC_IMP_BATCH = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ @<<
-QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$obj $src
-QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
-QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<<
-
-QMAKE_LINK = link
-QMAKE_LFLAGS = /NOLOGO
-QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO
-QMAKE_LFLAGS_DEBUG = /DEBUG
-QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE
-QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS
-QMAKE_LFLAGS_DLL = /DLL
-
-QMAKE_LIBS_CORE = kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib ws2_32.lib
-QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib winspool.lib ws2_32.lib ole32.lib user32.lib advapi32.lib
-QMAKE_LIBS_NETWORK = ws2_32.lib
-QMAKE_LIBS_OPENGL = opengl32.lib glu32.lib gdi32.lib user32.lib
-QMAKE_LIBS_COMPAT = advapi32.lib shell32.lib comdlg32.lib user32.lib gdi32.lib ws2_32.lib
-
-QMAKE_LIBS_QT_ENTRY = -lqtmain
-
-QMAKE_MOC = $$[QT_INSTALL_BINS]\moc.exe
-QMAKE_UIC = $$[QT_INSTALL_BINS]\uic.exe
-QMAKE_IDC = $$[QT_INSTALL_BINS]\idc.exe
-
-QMAKE_IDL = midl
-QMAKE_LIB = lib /NOLOGO
-QMAKE_RC = rc
-
-QMAKE_ZIP = zip -r -9
-
-QMAKE_COPY = copy /y
-QMAKE_COPY_DIR = xcopy /s /q /y /i
-QMAKE_MOVE = move
-QMAKE_DEL_FILE = del
-QMAKE_DEL_DIR = rmdir
-QMAKE_CHK_DIR_EXISTS = if not exist
-QMAKE_MKDIR = mkdir
-
-VCPROJ_EXTENSION = .vcproj
-VCSOLUTION_EXTENSION = .sln
-VCPROJ_KEYWORD = Qt4VSv1.0
-load(qt_config)
diff --git a/mkspecs/win32-msvc.net/qplatformdefs.h b/mkspecs/win32-msvc.net/qplatformdefs.h
deleted file mode 100644
index 05584c9..0000000
--- a/mkspecs/win32-msvc.net/qplatformdefs.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPLATFORMDEFS_H
-#define QPLATFORMDEFS_H
-
-#ifdef UNICODE
-#ifndef _UNICODE
-#define _UNICODE
-#endif
-#endif
-
-// Get Qt defines/settings
-
-#include "qglobal.h"
-
-#define _POSIX_
-#include <limits.h>
-#undef _POSIX_
-
-#include <tchar.h>
-#include <io.h>
-#include <direct.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <windows.h>
-
-#define Q_FS_FAT
-#ifdef QT_LARGEFILE_SUPPORT
-#define QT_STATBUF struct _stati64 // non-ANSI defs
-#define QT_STATBUF4TSTAT struct _stati64 // non-ANSI defs
-#define QT_STAT ::_stati64
-#define QT_FSTAT ::_fstati64
-#else
-#define QT_STATBUF struct _stat // non-ANSI defs
-#define QT_STATBUF4TSTAT struct _stat // non-ANSI defs
-#define QT_STAT ::_stat
-#define QT_FSTAT ::_fstat
-#endif
-#define QT_STAT_REG _S_IFREG
-#define QT_STAT_DIR _S_IFDIR
-#define QT_STAT_MASK _S_IFMT
-#if defined(_S_IFLNK)
-# define QT_STAT_LNK _S_IFLNK
-#endif
-#define QT_FILENO _fileno
-#define QT_OPEN ::_open
-#define QT_CLOSE ::_close
-#ifdef QT_LARGEFILE_SUPPORT
-#define QT_LSEEK ::_lseeki64
-#define QT_TSTAT ::_tstati64
-#else
-#define QT_LSEEK ::_lseek
-#define QT_TSTAT ::_tstat
-#endif
-#define QT_READ ::_read
-#define QT_WRITE ::_write
-#define QT_ACCESS ::_access
-#define QT_GETCWD ::_getcwd
-#define QT_CHDIR ::_chdir
-#define QT_MKDIR ::_mkdir
-#define QT_RMDIR ::_rmdir
-#define QT_OPEN_LARGEFILE 0
-#define QT_OPEN_RDONLY _O_RDONLY
-#define QT_OPEN_WRONLY _O_WRONLY
-#define QT_OPEN_RDWR _O_RDWR
-#define QT_OPEN_CREAT _O_CREAT
-#define QT_OPEN_TRUNC _O_TRUNC
-#define QT_OPEN_APPEND _O_APPEND
-#if defined(O_TEXT)
-# define QT_OPEN_TEXT _O_TEXT
-# define QT_OPEN_BINARY _O_BINARY
-#endif
-
-#include "../common/c89/qplatformdefs.h"
-
-#ifdef QT_LARGEFILE_SUPPORT
-#undef QT_FTELL
-#undef QT_OFF_T
-
-// 64-bit versions of fseek/ftell not always available. E.g., when linking
-// dynamically to CRT (/MT)
-#define QT_FTELL (QT_OFF_T)::ftell
-#define QT_OFF_T __int64
-#endif
-
-#define QT_SIGNAL_ARGS int
-
-#define QT_VSNPRINTF ::_vsnprintf
-#define QT_SNPRINTF ::_snprintf
-
-# define F_OK 0
-# define X_OK 1
-# define W_OK 2
-# define R_OK 4
-
-typedef int mode_t;
-
-#endif // QPLATFORMDEFS_H
diff --git a/mkspecs/win32-msvc/features/incremental.prf b/mkspecs/win32-msvc/features/incremental.prf
deleted file mode 100644
index 67596ca..0000000
--- a/mkspecs/win32-msvc/features/incremental.prf
+++ /dev/null
@@ -1,2 +0,0 @@
-CONFIG -= incremental_off
-QMAKE_LFLAGS_DEBUG += /incremental:yes
diff --git a/mkspecs/win32-msvc/features/incremental_off.prf b/mkspecs/win32-msvc/features/incremental_off.prf
deleted file mode 100644
index 9b6d19e..0000000
--- a/mkspecs/win32-msvc/features/incremental_off.prf
+++ /dev/null
@@ -1,2 +0,0 @@
-CONFIG -= incremental
-QMAKE_LFLAGS += /incremental:no
diff --git a/mkspecs/win32-msvc/qmake.conf b/mkspecs/win32-msvc/qmake.conf
deleted file mode 100644
index 64ab84a..0000000
--- a/mkspecs/win32-msvc/qmake.conf
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# qmake configuration for win32-msvc
-#
-# Written for Microsoft C++
-#
-
-MAKEFILE_GENERATOR = MSVC
-TEMPLATE = app
-CONFIG += qt warn_on release incremental flat link_prl precompile_header copy_dir_files no_delete_multiple_files debug_and_release debug_and_release_target
-QT += core gui
-DEFINES += UNICODE QT_LARGEFILE_SUPPORT
-QMAKE_COMPILER_DEFINES += _MSC_VER=1200 WIN32
-
-QMAKE_CC = cl
-QMAKE_LEX = flex
-QMAKE_LEXFLAGS =
-QMAKE_YACC = byacc
-QMAKE_YACCFLAGS = -d
-QMAKE_CFLAGS = -nologo -Zm200
-QMAKE_CFLAGS_WARN_ON = -W3
-QMAKE_CFLAGS_WARN_OFF = -W0
-QMAKE_CFLAGS_RELEASE = -O1 -MD
-QMAKE_CFLAGS_DEBUG = -Zi -MDd
-QMAKE_CFLAGS_YACC =
-
-QMAKE_CXX = $$QMAKE_CC
-QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
-QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
-QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
-QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
-QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
-QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
-QMAKE_CXXFLAGS_STL_ON = -GX
-QMAKE_CXXFLAGS_STL_OFF =
-QMAKE_CXXFLAGS_RTTI_ON = -GR
-QMAKE_CXXFLAGS_RTTI_OFF =
-QMAKE_CXXFLAGS_EXCEPTIONS_ON = -GX
-QMAKE_CXXFLAGS_EXCEPTIONS_OFF =
-
-QMAKE_INCDIR =
-QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS]
-QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS]
-
-QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$obj $src
-QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
-QMAKE_RUN_CC_IMP_BATCH = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ @<<
-QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$obj $src
-QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
-QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<<
-
-QMAKE_LINK = link
-QMAKE_LFLAGS = /NOLOGO
-QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO
-QMAKE_LFLAGS_DEBUG = /DEBUG
-QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:console
-QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:windows
-QMAKE_LFLAGS_DLL = /DLL
-
-QMAKE_LIBS =
-QMAKE_LIBS_CORE = kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib ws2_32.lib
-QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib winspool.lib ws2_32.lib ole32.lib user32.lib advapi32.lib
-QMAKE_LIBS_NETWORK = ws2_32.lib
-QMAKE_LIBS_OPENGL = opengl32.lib glu32.lib gdi32.lib user32.lib delayimp.lib
-QMAKE_LIBS_COMPAT = advapi32.lib shell32.lib comdlg32.lib user32.lib gdi32.lib ws2_32.lib
-QMAKE_LIBS_QT_ENTRY = -lqtmain
-
-QMAKE_MOC = $$[QT_INSTALL_BINS]\moc.exe
-QMAKE_UIC = $$[QT_INSTALL_BINS]\uic.exe
-QMAKE_IDC = $$[QT_INSTALL_BINS]\idc.exe
-
-QMAKE_IDL = midl
-QMAKE_LIB = lib /NOLOGO
-QMAKE_RC = rc
-
-QMAKE_ZIP = zip -r -9
-
-QMAKE_COPY = copy /y
-QMAKE_COPY_DIR = xcopy /s /q /y /i
-QMAKE_MOVE = move
-QMAKE_DEL_FILE = del
-QMAKE_DEL_DIR = rmdir
-QMAKE_CHK_DIR_EXISTS = if not exist
-QMAKE_MKDIR = mkdir
-
-DSP_EXTENSION = .dsp
-load(qt_config)
diff --git a/mkspecs/win32-msvc/qplatformdefs.h b/mkspecs/win32-msvc/qplatformdefs.h
deleted file mode 100644
index abb5894..0000000
--- a/mkspecs/win32-msvc/qplatformdefs.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPLATFORMDEFS_H
-#define QPLATFORMDEFS_H
-
-#ifdef UNICODE
-#ifndef _UNICODE
-#define _UNICODE
-#endif
-#endif
-
-// Get Qt defines/settings
-
-#include "qglobal.h"
-
-#define _POSIX_
-#include <limits.h>
-#undef _POSIX_
-
-#include <tchar.h>
-#include <io.h>
-#include <direct.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <windows.h>
-
-#define Q_FS_FAT
-#ifdef QT_LARGEFILE_SUPPORT
-#define QT_STATBUF struct _stati64 // non-ANSI defs
-#define QT_STATBUF4TSTAT struct _stati64 // non-ANSI defs
-#define QT_STAT ::_stati64
-#define QT_FSTAT ::_fstati64
-#else
-#define QT_STATBUF struct _stat // non-ANSI defs
-#define QT_STATBUF4TSTAT struct _stat // non-ANSI defs
-#define QT_STAT ::_stat
-#define QT_FSTAT ::_fstat
-#endif
-#define QT_STAT_REG _S_IFREG
-#define QT_STAT_DIR _S_IFDIR
-#define QT_STAT_MASK _S_IFMT
-#if defined(_S_IFLNK)
-# define QT_STAT_LNK _S_IFLNK
-#endif
-#define QT_FILENO _fileno
-#define QT_OPEN ::_open
-#define QT_CLOSE ::_close
-#ifdef QT_LARGEFILE_SUPPORT
-#define QT_LSEEK ::_lseeki64
-#define QT_TSTAT ::_tstati64
-#else
-#define QT_LSEEK ::_lseek
-#define QT_TSTAT ::_tstat
-#endif
-#define QT_READ ::_read
-#define QT_WRITE ::_write
-#define QT_ACCESS ::_access
-#define QT_GETCWD ::_getcwd
-#define QT_CHDIR ::_chdir
-#define QT_MKDIR ::_mkdir
-#define QT_RMDIR ::_rmdir
-#define QT_OPEN_LARGEFILE 0
-#define QT_OPEN_RDONLY _O_RDONLY
-#define QT_OPEN_WRONLY _O_WRONLY
-#define QT_OPEN_RDWR _O_RDWR
-#define QT_OPEN_CREAT _O_CREAT
-#define QT_OPEN_TRUNC _O_TRUNC
-#define QT_OPEN_APPEND _O_APPEND
-#if defined(O_TEXT)
-# define QT_OPEN_TEXT _O_TEXT
-# define QT_OPEN_BINARY _O_BINARY
-#endif
-
-#include "../common/c89/qplatformdefs.h"
-
-#ifdef QT_LARGEFILE_SUPPORT
-#undef QT_OFF_T
-#define QT_OFF_T __int64
-#endif
-
-#define QT_SIGNAL_ARGS int
-
-#if defined(_MSC_VER) && _MSC_VER < 1400
-# define QT_VSNPRINTF ::_vsnprintf
-#endif
-#define QT_SNPRINTF ::_snprintf
-
-# define F_OK 0
-# define X_OK 1
-# define W_OK 2
-# define R_OK 4
-
-typedef int mode_t;
-
-
-#endif // QPLATFORMDEFS_H
diff --git a/mkspecs/win32-msvc2002/qmake.conf b/mkspecs/win32-msvc2002/qmake.conf
deleted file mode 100644
index 13fbfb0..0000000
--- a/mkspecs/win32-msvc2002/qmake.conf
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# qmake configuration for win32-msvc2002
-#
-# Written for Microsoft C++.NET
-#
-
-MAKEFILE_GENERATOR = MSVC.NET
-TEMPLATE = app
-CONFIG += qt warn_on release incremental flat link_prl precompile_header autogen_precompile_source copy_dir_files debug_and_release debug_and_release_target
-QT += core gui
-DEFINES += UNICODE WIN32 QT_LARGEFILE_SUPPORT
-QMAKE_COMPILER_DEFINES += _MSC_VER=1300 WIN32
-
-QMAKE_CC = cl
-QMAKE_LEX = flex
-QMAKE_LEXFLAGS =
-QMAKE_YACC = byacc
-QMAKE_YACCFLAGS = -d
-QMAKE_CFLAGS = -nologo -Zm300
-QMAKE_CFLAGS_WARN_ON = -W3
-QMAKE_CFLAGS_WARN_OFF = -W0
-QMAKE_CFLAGS_RELEASE = -O2 -MD
-QMAKE_CFLAGS_DEBUG = -Zi -MDd
-QMAKE_CFLAGS_YACC =
-
-QMAKE_CXX = $$QMAKE_CC
-QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
-QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -w34100 -w34189
-QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
-QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
-QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
-QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
-QMAKE_CXXFLAGS_STL_ON = -EHsc
-QMAKE_CXXFLAGS_STL_OFF =
-QMAKE_CXXFLAGS_RTTI_ON = -GR
-QMAKE_CXXFLAGS_RTTI_OFF =
-QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHsc
-QMAKE_CXXFLAGS_EXCEPTIONS_OFF =
-
-QMAKE_INCDIR =
-QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS]
-QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS]
-
-QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$obj $src
-QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
-QMAKE_RUN_CC_IMP_BATCH = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ @<<
-QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$obj $src
-QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
-QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<<
-
-QMAKE_LINK = link
-QMAKE_LFLAGS = /NOLOGO
-QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO
-QMAKE_LFLAGS_DEBUG = /DEBUG
-QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE
-QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS
-QMAKE_LFLAGS_DLL = /DLL
-
-QMAKE_LIBS_CORE = kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib ws2_32.lib
-QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib winspool.lib ws2_32.lib ole32.lib user32.lib advapi32.lib
-QMAKE_LIBS_NETWORK = ws2_32.lib
-QMAKE_LIBS_OPENGL = opengl32.lib glu32.lib gdi32.lib user32.lib
-QMAKE_LIBS_COMPAT = advapi32.lib shell32.lib comdlg32.lib user32.lib gdi32.lib ws2_32.lib
-
-QMAKE_LIBS_QT_ENTRY = -lqtmain
-
-QMAKE_MOC = $$[QT_INSTALL_BINS]\moc.exe
-QMAKE_UIC = $$[QT_INSTALL_BINS]\uic.exe
-QMAKE_IDC = $$[QT_INSTALL_BINS]\idc.exe
-
-QMAKE_IDL = midl
-QMAKE_LIB = lib /NOLOGO
-QMAKE_RC = rc
-
-QMAKE_ZIP = zip -r -9
-
-QMAKE_COPY = copy /y
-QMAKE_COPY_DIR = xcopy /s /q /y /i
-QMAKE_MOVE = move
-QMAKE_DEL_FILE = del
-QMAKE_DEL_DIR = rmdir
-QMAKE_CHK_DIR_EXISTS = if not exist
-QMAKE_MKDIR = mkdir
-
-VCPROJ_EXTENSION = .vcproj
-VCSOLUTION_EXTENSION = .sln
-VCPROJ_KEYWORD = Qt4VSv1.0
-load(qt_config)
diff --git a/mkspecs/win32-msvc2002/qplatformdefs.h b/mkspecs/win32-msvc2002/qplatformdefs.h
deleted file mode 100644
index 6d71abf..0000000
--- a/mkspecs/win32-msvc2002/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../win32-msvc.net/qplatformdefs.h"
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index fcf43c8..5e3190d 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -9,7 +9,7 @@ LFLAGS = @QMAKE_LFLAGS@
OBJS=project.o property.o main.o makefile.o unixmake2.o unixmake.o \
mingw_make.o option.o winmakefile.o projectgenerator.o \
meta.o makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \
- borland_bmake.o msvc_dsp.o msvc_vcproj.o msvc_nmake.o msvc_objectmodel.o \
+ borland_bmake.o msvc_vcproj.o msvc_nmake.o msvc_objectmodel.o \
symmake.o initprojectdeploy_symbian.o symmake_abld.o symmake_sbsv2.o
#qt code
@@ -266,9 +266,6 @@ msvc_nmake.o: generators/win32/msvc_nmake.cpp
pbuilder_pbx.o: generators/mac/pbuilder_pbx.cpp
$(CXX) -c -o $@ $(CXXFLAGS) generators/mac/pbuilder_pbx.cpp
-msvc_dsp.o: generators/win32/msvc_dsp.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_dsp.cpp
-
symmake.o: generators/symbian/symmake.cpp
$(CXX) -c -o $@ $(CXXFLAGS) generators/symbian/symmake.cpp
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index e6bbcd5..1f3092a 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -73,7 +73,7 @@ ADDCLEAN = qmake.tds
OBJS = project.obj main.obj makefile.obj unixmake.obj unixmake2.obj mingw_make.obj \
option.obj winmakefile.obj projectgenerator.obj property.obj meta.obj \
makefiledeps.obj metamakefile.obj xmloutput.obj pbuilder_pbx.obj \
- borland_bmake.obj msvc_nmake.obj msvc_dsp.obj msvc_vcproj.obj \
+ borland_bmake.obj msvc_nmake.obj msvc_vcproj.obj \
msvc_objectmodel.obj symmake.obj initprojectdeploy_symbian.obj \
symmake_abld.obj symmake_sbsv2.obj
@@ -191,7 +191,6 @@ clean::
-del xmloutput.obj
-del borland_bmake.obj
-del msvc_nmake.obj
- -del msvc_dsp.obj
-del msvc_vcproj.obj
-del msvc_objectmodel.obj
-del symmake.obj
@@ -376,9 +375,6 @@ mingw_make.obj: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp
msvc_nmake.obj: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp
$(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp
-msvc_dsp.obj: $(SOURCE_PATH)/qmake/generators/win32/msvc_dsp.cpp
- $(CXX) $(CXXFLAGS) generators/win32/msvc_dsp.cpp
-
msvc_vcproj.obj: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp
$(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp
diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++
index ade379b..41a1d8c 100644
--- a/qmake/Makefile.win32-g++
+++ b/qmake/Makefile.win32-g++
@@ -36,7 +36,7 @@ ADDCLEAN =
OBJS = project.o main.o makefile.o unixmake.o unixmake2.o mingw_make.o \
option.o winmakefile.o projectgenerator.o property.o meta.o \
makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \
- borland_bmake.o msvc_nmake.o msvc_dsp.o msvc_vcproj.o \
+ borland_bmake.o msvc_nmake.o msvc_vcproj.o \
msvc_objectmodel.o symmake.o initprojectdeploy_symbian.o \
symmake_abld.o symmake_sbsv2.o
@@ -257,9 +257,6 @@ mingw_make.o: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp
msvc_nmake.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp
$(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp
-msvc_dsp.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_dsp.cpp
- $(CXX) $(CXXFLAGS) generators/win32/msvc_dsp.cpp
-
msvc_vcproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp
$(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp
diff --git a/qmake/Makefile.win32-g++-sh b/qmake/Makefile.win32-g++-sh
index 8d2723c..0b08320 100644
--- a/qmake/Makefile.win32-g++-sh
+++ b/qmake/Makefile.win32-g++-sh
@@ -36,7 +36,7 @@ ADDCLEAN =
OBJS = project.o main.o makefile.o unixmake.o unixmake2.o mingw_make.o \
option.o winmakefile.o projectgenerator.o property.o meta.o \
makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \
- borland_bmake.o msvc_nmake.o msvc_dsp.o msvc_vcproj.o \
+ borland_bmake.o msvc_nmake.o msvc_vcproj.o \
msvc_objectmodel.o symmake.o initprojectdeploy_symbian.o \
symmake_abld.o symmake_sbsv2.o
@@ -256,9 +256,6 @@ mingw_make.o: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp
msvc_nmake.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp
$(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp
-msvc_dsp.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_dsp.cpp
- $(CXX) $(CXXFLAGS) generators/win32/msvc_dsp.cpp
-
msvc_vcproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp
$(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index b0a8011..ec712a0 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -65,12 +65,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef Q_OS_WIN32
-#define NO_STDERR "2> NUL"
-#else
-#define NO_STDERR "2>/dev/null"
-#endif
-
QT_BEGIN_NAMESPACE
// Well, Windows doesn't have this, so here's the macro
@@ -1814,8 +1808,6 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
tmp_clean = tmp_out;
if(tmp_clean.indexOf("${QMAKE_") == -1) {
t << "\n\t" << "-$(DEL_FILE) " << tmp_clean;
- if (isForSymbian())
- t << " " << NO_STDERR; // Eliminate unnecessary warnings
wrote_clean = true;
}
if(!wrote_clean_cmds || !wrote_clean) {
@@ -1843,12 +1835,8 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
cleans.append(files);
}
}
- if(!cleans.isEmpty()) {
- if (isForSymbian())
- t << valGlue(cleans, "\n\t" + del_statement, " " NO_STDERR "\n\t" + del_statement, " " NO_STDERR);
- else
- t << valGlue(cleans, "\n\t" + del_statement, "\n\t" + del_statement, "");
- }
+ if(!cleans.isEmpty())
+ t << valGlue(cleans, "\n\t" + del_statement, "\n\t" + del_statement, "");
if(!wrote_clean_cmds) {
for(QStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
t << "\n\t" << replaceExtraCompilerVariables(tmp_clean_cmds, (*input),
@@ -2164,9 +2152,7 @@ QString MakefileGenerator::buildArgs(const QString &outdir)
ret += " -nodependheuristics";
if(!Option::mkfile::qmakespec_commandline.isEmpty())
ret += " -spec " + specdir(outdir);
- if(Option::target_mode == Option::TARG_MAC9_MODE)
- ret += " -mac9";
- else if(Option::target_mode == Option::TARG_MACX_MODE)
+ if(Option::target_mode == Option::TARG_MACX_MODE)
ret += " -macx";
else if(Option::target_mode == Option::TARG_UNIX_MODE)
ret += " -unix";
@@ -2681,8 +2667,6 @@ MakefileGenerator::writeMakeQmake(QTextStream &t)
if(!specdir().isEmpty()) {
if(exists(Option::fixPathToLocalOS(specdir()+QDir::separator()+"qmake.conf")))
t << escapeDependencyPath(specdir() + Option::dir_sep + "qmake.conf") << " ";
- else if(exists(Option::fixPathToLocalOS(specdir()+QDir::separator()+"tmake.conf")))
- t << escapeDependencyPath(specdir() + Option::dir_sep + "tmake.conf") << " ";
}
const QStringList &included = project->values("QMAKE_INTERNAL_INCLUDED_FILES");
t << escapeDependencyPaths(included).join(" \\\n\t\t") << "\n\t"
diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp
index 4151193..f48491c 100644
--- a/qmake/generators/metamakefile.cpp
+++ b/qmake/generators/metamakefile.cpp
@@ -432,7 +432,6 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "pbuilder_pbx.h"
#include "msvc_nmake.h"
#include "borland_bmake.h"
-#include "msvc_dsp.h"
#include "msvc_vcproj.h"
#include "symmake_abld.h"
#include "symmake_sbsv2.h"
@@ -458,15 +457,8 @@ MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO)
mkfile = new MingwMakefileGenerator;
} else if(gen == "PROJECTBUILDER" || gen == "XCODE") {
mkfile = new ProjectBuilderMakefileGenerator;
- } else if(gen == "MSVC") {
- // Visual Studio =< v6.0
- if(proj->first("TEMPLATE").indexOf(QRegExp("^vc.*")) != -1)
- mkfile = new DspMakefileGenerator;
- else
- mkfile = new NmakeMakefileGenerator;
} else if(gen == "MSVC.NET") {
- // Visual Studio >= v7.0
- if(proj->first("TEMPLATE").indexOf(QRegExp("^vc.*")) != -1 || proj->first("TEMPLATE").indexOf(QRegExp("^ce.*")) != -1)
+ if(proj->first("TEMPLATE").indexOf(QRegExp("^vc.*")) != -1)
mkfile = new VcprojGenerator;
else
mkfile = new NmakeMakefileGenerator;
diff --git a/qmake/generators/symbian/initprojectdeploy_symbian.cpp b/qmake/generators/symbian/initprojectdeploy_symbian.cpp
index 7ccce00..7279a4c 100644
--- a/qmake/generators/symbian/initprojectdeploy_symbian.cpp
+++ b/qmake/generators/symbian/initprojectdeploy_symbian.cpp
@@ -207,7 +207,7 @@ QString generate_uid(const QString& target)
return tmp;
}
- unsigned long hash = 5381;
+ quint32 hash = 5381;
int c;
for (int i = 0; i < target.size(); ++i) {
diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp
index 13c4fd4..69668ab 100644
--- a/qmake/generators/symbian/symmake.cpp
+++ b/qmake/generators/symbian/symmake.cpp
@@ -94,7 +94,11 @@
#define MMP_END_RESOURCE "END"
#define SIS_TARGET "sis"
+#define INSTALLER_SIS_TARGET "installer_sis"
+#define ROM_STUB_SIS_TARGET "stub_sis"
#define OK_SIS_TARGET "ok_sis"
+#define OK_INSTALLER_SIS_TARGET "ok_installer_sis"
+#define OK_ROM_STUB_SIS_TARGET "ok_stub_sis"
#define FAIL_SIS_NOPKG_TARGET "fail_sis_nopkg"
#define FAIL_SIS_NOCACHE_TARGET "fail_sis_nocache"
@@ -299,12 +303,26 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
}
generatedFiles << pkgFile.fileName();
+ QTextStream t(&pkgFile);
+
+ QString installerSisHeader = project->values("DEPLOYMENT.installer_header").join("\n");
+ if (installerSisHeader.isEmpty())
+ installerSisHeader = "0xA000D7CE"; // Use default self-signable UID if not defined
+
+ QString wrapperStreamBuffer;
+ QTextStream tw(&wrapperStreamBuffer);
+
+ QString dateStr = QDateTime::currentDateTime().toString(Qt::ISODate);
// Header info
- QTextStream t(&pkgFile);
- t << QString("; %1 generated by qmake at %2").arg(pkgFilename).arg(QDateTime::currentDateTime().toString(Qt::ISODate)) << endl;
- t << "; This file is generated by qmake and should not be modified by the user" << endl;
- t << ";" << endl << endl;
+ QString wrapperPkgFilename = QString("%1_installer.%2")
+ .arg(fixedTarget)
+ .arg("pkg");
+ QString headerComment = "; %1 generated by qmake at %2\n"
+ "; This file is generated by qmake and should not be modified by the user\n"
+ ";\n\n";
+ t << headerComment.arg(pkgFilename).arg(dateStr);
+ tw << headerComment.arg(wrapperPkgFilename).arg(dateStr);
// Construct QStringList from pkg_prerules since we need search it before printed to file
QStringList rawPkgPreRules;
@@ -327,8 +345,9 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
if (!containsStartWithItem('&', rawPkgPreRules)) {
// language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS)
- t << "; Language" << endl;
- t << "&EN" << endl << endl;
+ QString languageCode = "; Language\n&EN\n\n";
+ t << languageCode;
+ tw << languageCode;
} else {
// In case user defines langs, he must take care also about SIS header
if (!containsStartWithItem('#', rawPkgPreRules))
@@ -337,34 +356,51 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
// name of application, UID and version
QString applicationVersion = project->first("VERSION").isEmpty() ? "1,0,0" : project->first("VERSION").replace('.', ',');
+ QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n";
+ QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET")));
+ visualTarget = removePathSeparators(visualTarget);
+ QString wrapperTarget = visualTarget + " installer";
- if (!containsStartWithItem('#', rawPkgPreRules)) {
- QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET")));
- visualTarget = removePathSeparators(visualTarget);
+ if (installerSisHeader.startsWith("0x", Qt::CaseInsensitive)) {
+ tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion);
+ } else {
+ tw << installerSisHeader << endl;
+ }
- t << "; SIS header: name, uid, version" << endl;
- t << QString("#{\"%1\"},(%2),%3").arg(visualTarget).arg(uid3).arg(applicationVersion) << endl << endl;
+ if (!containsStartWithItem('#', rawPkgPreRules)) {
+ t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion);
}
// Localized vendor name
+ QString vendorName;
if (!containsStartWithItem('%', rawPkgPreRules)) {
- t << "; Localised Vendor name" << endl;
- t << "%{\"Vendor\"}" << endl << endl;
+ vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n";
}
// Unique vendor name
if (!containsStartWithItem(':', rawPkgPreRules)) {
- t << "; Unique Vendor name" << endl;
- t << ":\"Vendor\"" << endl << endl;
+ vendorName += "; Unique Vendor name\n:\"Vendor\"\n\n";
}
+ t << vendorName;
+ tw << vendorName;
+
// PKG pre-rules - these are added before actual file installations i.e. SIS package body
if (rawPkgPreRules.size()) {
- t << "; Manual PKG pre-rules from PRO files" << endl;
+ QString comment = "\n; Manual PKG pre-rules from PRO files\n";
+ t << comment;
+ tw << comment;
+
foreach(QString item, rawPkgPreRules) {
+ // Only regular pkg file should have package dependencies or pkg header if that is
+ // defined using prerules.
+ if (!item.startsWith("(") && !item.startsWith("#")) {
+ tw << item << endl;
+ }
t << item << endl;
}
t << endl;
+ tw << endl;
}
// Begin Manufacturer block
@@ -387,7 +423,6 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
QString epocReleasePath = QString("%1epoc32/release/$(PLATFORM)/$(TARGET)")
.arg(epocRoot());
-
if (targetType == TypeExe) {
// deploy .exe file
t << "; Executable and default resource files" << endl;
@@ -476,6 +511,30 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
<< " - \"\", FILETEXT, TEXTEXIT" << endl
<< "ENDIF ; MANUFACTURER" << endl;
}
+
+ // Write wrapper pkg
+ if (!installerSisHeader.isEmpty()) {
+ QFile wrapperPkgFile(wrapperPkgFilename);
+ if (!wrapperPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ PRINT_FILE_CREATE_ERROR(wrapperPkgFilename);
+ return;
+ }
+
+ generatedFiles << wrapperPkgFile.fileName();
+ QTextStream twf(&wrapperPkgFile);
+
+ twf << wrapperStreamBuffer << endl;
+
+ // Wrapped files deployment
+ QString currentPath = qmake_getpwd();
+ QString sisName = QString("%1.sis").arg(fixedTarget);
+ twf << "\"" << currentPath << "/" << sisName << "\" - \"c:\\adm\\" << sisName << "\"" << endl;
+
+ QString bootStrapPath = QLibraryInfo::location(QLibraryInfo::PrefixPath);
+ bootStrapPath.append("/smartinstaller.sis");
+ QFileInfo fi(fileInfo(bootStrapPath));
+ twf << "@\"" << fi.absoluteFilePath() << "\",(0x2002CCCD)" << endl;
+ }
}
bool SymbianMakefileGenerator::containsStartWithItem(const QChar &c, const QStringList& src)
@@ -1833,7 +1892,7 @@ void SymbianMakefileGenerator::writeSisTargets(QTextStream &t)
t << endl;
t << SIS_TARGET ":" << endl;
- QString siscommand = QString("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \
+ QString siscommand = QString::fromLatin1("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \
"$(MAKE) -s -f $(MAKEFILE) %4," \
"$(if $(QT_SIS_TARGET),$(MAKE) -s -f $(MAKEFILE) %4," \
"$(MAKE) -s -f $(MAKEFILE) %5))," \
@@ -1849,15 +1908,65 @@ void SymbianMakefileGenerator::writeSisTargets(QTextStream &t)
t << OK_SIS_TARGET ":" << endl;
- QString pkgcommand = QString("\tcreatepackage" SCRIPT_EXT " $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \
+ QString pkgcommand = QString::fromLatin1("\tcreatepackage" SCRIPT_EXT " $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \
"$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)")
.arg(fixedTarget)
.arg("pkg");
t << pkgcommand << endl;
t << endl;
+ QString sisName = fixedTarget;
+ sisName += ".sis";
+
+ t << sisName << ":" << endl;
+ t << "\t$(MAKE) -s -f $(MAKEFILE) " SIS_TARGET << endl << endl;
+
+ t << ROM_STUB_SIS_TARGET ":" << endl;
+ QString stubsiscommand = QString::fromLatin1("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \
+ "$(MAKE) -s -f $(MAKEFILE) %4," \
+ "$(if $(QT_SIS_TARGET),$(MAKE) -s -f $(MAKEFILE) %4," \
+ "$(MAKE) -s -f $(MAKEFILE) %5))," \
+ "$(MAKE) -s -f $(MAKEFILE) %6)")
+ .arg(fixedTarget)
+ .arg("pkg")
+ .arg(MAKE_CACHE_NAME)
+ .arg(OK_ROM_STUB_SIS_TARGET)
+ .arg(FAIL_SIS_NOCACHE_TARGET)
+ .arg(FAIL_SIS_NOPKG_TARGET);
+ t << stubsiscommand << endl;
+ t << endl;
+
+ t << OK_ROM_STUB_SIS_TARGET ":" << endl;
+
+ QString stubpkgcommand = QString::fromLatin1("\tcreatepackage.bat -s $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \
+ "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)")
+ .arg(fixedTarget)
+ .arg("pkg");
+ t << stubpkgcommand << endl;
+ t << endl;
+
+ t << INSTALLER_SIS_TARGET ": " << sisName << endl;
+ siscommand = QString::fromLatin1("\t$(if $(wildcard %1_installer.%2)," \
+ "$(MAKE) -s -f $(MAKEFILE) %3," \
+ "$(MAKE) -s -f $(MAKEFILE) %4)")
+ .arg(fixedTarget)
+ .arg("pkg")
+ .arg(OK_INSTALLER_SIS_TARGET)
+ .arg(FAIL_SIS_NOPKG_TARGET);
+ t << siscommand << endl;
+ t << endl;
+
+ t << OK_INSTALLER_SIS_TARGET ": " << endl;
+
+ pkgcommand = QString::fromLatin1("\tcreatepackage.bat $(QT_SIS_OPTIONS) %1_installer.%2 - " \
+ "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)")
+ .arg(fixedTarget)
+ .arg("pkg");
+ t << pkgcommand << endl;
+ t << endl;
+
t << FAIL_SIS_NOPKG_TARGET ":" << endl;
- t << "\t$(error PKG file does not exist, 'SIS' target is only supported for executables or projects with DEPLOYMENT statement)" << endl;
+ t << "\t$(error PKG file does not exist, '" SIS_TARGET "' and '" INSTALLER_SIS_TARGET "' target are only supported for executables or projects with DEPLOYMENT statement)" << endl;
t << endl;
t << FAIL_SIS_NOCACHE_TARGET ":" << endl;
diff --git a/qmake/generators/symbian/symmake_abld.cpp b/qmake/generators/symbian/symmake_abld.cpp
index 26dd3fd..a3a504f 100644
--- a/qmake/generators/symbian/symmake_abld.cpp
+++ b/qmake/generators/symbian/symmake_abld.cpp
@@ -303,19 +303,16 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool
// generate command lines like this ...
// -@ if NOT EXIST ".\somedir" mkdir ".\somedir"
QStringList dirsToClean;
+ QString dirExists = var("QMAKE_CHK_DIR_EXISTS");
+ QString mkdir = var("QMAKE_MKDIR");
for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
QStringList values = it.value();
for (int i = 0; i < values.size(); ++i) {
if (values.at(i).endsWith("/" QT_EXTRA_INCLUDE_DIR)) {
QString fixedValue(QDir::toNativeSeparators(values.at(i)));
dirsToClean << fixedValue;
-#ifdef Q_OS_WIN32
- t << "\t-@ if NOT EXIST \"" << fixedValue << "\" mkdir \""
- << fixedValue << "\"" << endl;
-#else
- t << "\t-@ if test ! -d \"" << fixedValue << "\"; then mkdir \""
- << fixedValue << "\"" << "; fi" <<endl;
-#endif
+ t << "\t-@ " << dirExists << " \"" << fixedValue << "\" "
+ << mkdir << " \"" << fixedValue << "\"" << endl;
}
}
}
@@ -324,11 +321,7 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool
// Note: EXTENSION_CLEAN will get called many times when doing reallyclean
// This is why the "2> NUL" gets appended to generated clean targets in makefile.cpp.
t << EXTENSION_CLEAN ": " COMPILER_CLEAN_TARGET << endl;
-#ifdef Q_OS_WIN32
- generateCleanCommands(t, dirsToClean, var("QMAKE_DEL_DIR"), " /S /Q ", "", "");
-#else
- generateCleanCommands(t, dirsToClean, "rm", " -rf ", "", "");
-#endif
+ generateCleanCommands(t, dirsToClean, var("QMAKE_DEL_TREE"), "", "", "");
t << endl;
t << PRE_TARGETDEPS_TARGET ":"
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index f51c046..b2f0db1 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -778,10 +778,8 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
uninst.append("-$(DEL_FILE) \"" + dst_targ + "\"");
if(!links.isEmpty()) {
for(int i = 0; i < links.size(); ++i) {
- if(Option::target_mode == Option::TARG_WIN_MODE ||
- Option::target_mode == Option::TARG_MAC9_MODE) {
- } else if(Option::target_mode == Option::TARG_UNIX_MODE ||
- Option::target_mode == Option::TARG_MACX_MODE) {
+ if(Option::target_mode == Option::TARG_UNIX_MODE ||
+ Option::target_mode == Option::TARG_MACX_MODE) {
QString link = Option::fixPathToTargetOS(destdir + links[i], false);
int lslash = link.lastIndexOf(Option::dir_sep);
if(lslash != -1)
diff --git a/qmake/generators/win32/msvc_dsp.cpp b/qmake/generators/win32/msvc_dsp.cpp
deleted file mode 100644
index 9c8dd1d..0000000
--- a/qmake/generators/win32/msvc_dsp.cpp
+++ /dev/null
@@ -1,1207 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the qmake application of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "msvc_dsp.h"
-#include "option.h"
-
-#include <qdir.h>
-#include <qset.h>
-
-#include <stdlib.h>
-
-QT_BEGIN_NAMESPACE
-
-DspMakefileGenerator::DspMakefileGenerator() : Win32MakefileGenerator(), init_flag(false)
-{
-}
-
-bool DspMakefileGenerator::writeMakefile(QTextStream &t)
-{
- if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
- /* for now just dump, I need to generated an empty dsp or something.. */
- fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
- var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData());
- return true;
- }
-
- // Generate workspace file
- if(project->first("TEMPLATE") == "vcsubdirs") {
- if (!project->isActiveConfig("build_pass")) {
- debug_msg(1, "Generator: MSVC: Writing workspave file");
- writeSubDirs(t);
- } else {
- debug_msg(1, "Generator: MSVC: Not writing workspace file for build_pass configs");
- }
- return true;
- } else if (project->first("TEMPLATE") == "vcapp" || project->first("TEMPLATE") == "vclib") {
- if(!project->isActiveConfig("build_pass"))
- return writeDspParts(t);
- return true;
- }
- return project->isActiveConfig("build_pass");
-}
-
-bool DspMakefileGenerator::hasBuiltinCompiler(const QString &filename) const
-{
- for (int i = 0; i < Option::cpp_ext.count(); ++i)
- if (filename.endsWith(Option::cpp_ext.at(i)))
- return true;
- for (int i = 0; i < Option::c_ext.count(); ++i)
- if (filename.endsWith(Option::c_ext.at(i)))
- return true;
- return false;
-}
-
-QString DspMakefileGenerator::replaceExtraCompilerVariables(const QString &var, const QStringList &in, const QStringList &out)
-{
- QString ret = MakefileGenerator::replaceExtraCompilerVariables(var, in, out);
- ret.replace("$(DEFINES)", varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") +
- varGlue("DEFINES"," -D"," -D",""));
-
- QString incpath = this->var("MSVCDSP_INCPATH");
- incpath.replace("/I", "-I");
- ret.replace("$(INCPATH)", incpath);
- return ret;
-}
-
-
-// if config is part of a multibuild thenthe gule (this) has the correct MSVCDSP_PROJECT
-QString DspMakefileGenerator::configName(DspMakefileGenerator * config)
-{
- return var("MSVCDSP_PROJECT") + config->var("MSVCDSP_CONFIG_NAME");
-}
-
-bool DspMakefileGenerator::writeDspHeader(QTextStream &t)
-{
- DspMakefileGenerator * config = this;
- if (mergedProjects.count())
- config = mergedProjects.at(0);
-
- t << "# Microsoft Developer Studio Project File - Name=\"" << var("MSVCDSP_PROJECT") << "\" - Package Owner=<4>" << endl;
- t << "# Microsoft Developer Studio Generated Build File, Format Version 6.00" << endl;
- t << "# ** DO NOT EDIT **" << endl;
- t << endl;
- t << "# TARGTYPE \"Win32 (x86) " << var("MSVCDSP_TARGETTYPE") << "\" " << var("MSVCDSP_DSPTYPE") << endl;
- t << endl;
- t << "CFG=\"" << configName(config) << "\"" << endl;
- t << "!MESSAGE This is not a valid makefile. To build this project using NMAKE," << endl;
- t << "!MESSAGE use the Export Makefile command and run" << endl;
- t << "!MESSAGE " << endl;
- t << "!MESSAGE NMAKE /f " << escapeFilePath(var("TARGET")) << ".mak." << endl;
- t << "!MESSAGE " << endl;
- t << "!MESSAGE You can specify a configuration when running NMAKE" << endl;
- t << "!MESSAGE by defining the macro CFG on the command line. For example:" << endl;
- t << "!MESSAGE " << endl;
- t << "!MESSAGE NMAKE /f " << escapeFilePath(var("TARGET")) << ".mak CFG=\"" << configName(config) << "\"" << endl;
- t << "!MESSAGE " << endl;
- t << "!MESSAGE Possible choices for configuration are:" << endl;
- t << "!MESSAGE " << endl;
- if (mergedProjects.count()) {
- for (int i = 0; i < mergedProjects.count(); ++i) {
- DspMakefileGenerator * config = mergedProjects.at(i);
- t << "!MESSAGE \"" << configName(config) << "\" (based on \"Win32 (x86) " << config->var("MSVCDSP_TARGETTYPE") << "\")" << endl;
- }
- } else {
- t << "!MESSAGE \"" << configName(config) << "\" (based on \"Win32 (x86) " << config->var("MSVCDSP_TARGETTYPE") << "\")" << endl;
- }
- t << "!MESSAGE " << endl;
- t << endl;
- t << "# Begin Project" << endl;
- t << "# PROP AllowPerConfigDependencies 0" << endl;
- t << "# PROP Scc_ProjName \"\"" << endl;
- t << "# PROP Scc_LocalPath \"\"" << endl;
- t << "CPP=" << config->var("QMAKE_CC") << endl;
- t << "MTL=" << config->var("QMAKE_IDL") << endl;
- t << "RSC=" << config->var("QMAKE_RC") << endl;
- t << "BSC32=bscmake.exe" << endl;
-
- return true;
-}
-
-
-bool DspMakefileGenerator::writeDspParts(QTextStream &t)
-{
- //bool staticLibTarget = var("MSVCDSP_DSPTYPE") == "0x0104";
-
- writeDspHeader(t);
- writeDspConfig(t, this);
- t << endl;
- t << "# Begin Target" << endl;
- t << endl;
- t << "# Name \"" << configName(this) << "\"" << endl;
- t << endl;
-
-
- QStringList listNames = QString("SOURCES|DEF_FILE").split("|");
- QStringList allListNames = listNames;
- writeFileGroup(t, listNames, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
- listNames = QStringList("HEADERS");
- allListNames += listNames;
- writeFileGroup(t, QStringList("HEADERS"), "Header Files", "h;hpp;hxx;hm;inl");
- listNames = QString("FORMS|INTERFACES|FORMS3").split("|");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Form Files", "ui");
- listNames = QStringList("IMAGES");
- allListNames += listNames;
- writeFileGroup(t, QStringList("IMAGES"), "Image Files", "");
- listNames = QString("RC_FILE|RESOURCES").split("|");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Resources", "rc;qrc");
- listNames = QStringList("TRANSLATIONS");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Translations", "ts;xlf");
- listNames = QStringList("LEXSOURCES");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Lexables", "l");
- listNames = QStringList("YACCSOURCES");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Yaccables", "y");
- listNames = QStringList("TYPELIBS");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Type Libraries", "tlb;olb");
-
- if (!project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
- const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
- for (QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
- const QStringList &inputs = project->values((*it)+".input");
- for (QStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) {
- if (!allListNames.contains((*input)) && *input != "UIC3_HEADERS")
- writeFileGroup(t, QStringList((*input)), (*input) + " Files", "");
- }
- }
- }
-
- project->values("SWAPPED_BUILD_STEPS") = swappedBuildSteps.keys();
-
- writeFileGroup(t, QString("GENERATED_SOURCES|GENERATED_FILES|SWAPPED_BUILD_STEPS").split("|"), "Generated", "");
-
- t << "# End Target" << endl;
- t << "# End Project" << endl;
- return true;
-}
-
-void
-DspMakefileGenerator::init()
-{
- if(init_flag)
- return;
- QStringList::Iterator it;
- init_flag = true;
-
- platform = "Win32";
- if(!project->values("QMAKE_PLATFORM").isEmpty())
- platform = varGlue("QMAKE_PLATFORM", "", " ", "");
-
- // this should probably not be here, but I'm using it to wrap the .t files
- if(project->first("TEMPLATE") == "vcapp")
- project->values("QMAKE_APP_FLAG").append("1");
- else if(project->first("TEMPLATE") == "vclib")
- project->values("QMAKE_LIB_FLAG").append("1");
-
- if(project->values("QMAKESPEC").isEmpty())
- project->values("QMAKESPEC").append(qgetenv("QMAKESPEC"));
-
- project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
- processVars();
-
- if(!project->values("VERSION").isEmpty()) {
- QString version = project->values("VERSION").first();
- int firstDot = version.indexOf(".");
- QString major = version.left(firstDot);
- QString minor = version.right(version.length() - firstDot - 1);
- minor.replace(".", "");
- project->values("MSVCDSP_LFLAGS").append("/VERSION:" + major + "." + minor);
- }
-
- QString msvcdsp_project;
- if(!project->isEmpty("TARGET")) {
- project->values("TARGET") = unescapeFilePaths(project->values("TARGET"));
- msvcdsp_project = project->first("TARGET");
- }
-
- MakefileGenerator::init();
-
- if(msvcdsp_project.isEmpty())
- msvcdsp_project = Option::output.fileName();
-
- msvcdsp_project = msvcdsp_project.right(msvcdsp_project.length() - msvcdsp_project.lastIndexOf("\\") - 1);
- int dotFind = msvcdsp_project.lastIndexOf(".");
- if(dotFind != -1)
- msvcdsp_project = msvcdsp_project.left(dotFind);
- msvcdsp_project.replace("-", "");
-
- project->values("MSVCDSP_PROJECT").append(msvcdsp_project);
-
- QStringList &proj = project->values("MSVCDSP_PROJECT");
-
- for(QStringList::Iterator it = proj.begin(); it != proj.end(); ++it)
- (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), "");
-
- if(!project->values("QMAKE_APP_FLAG").isEmpty()) {
- if(project->isActiveConfig("console")) {
- project->values("MSVCDSP_TARGETTYPE").append("Console Application");
- project->values("MSVCDSP_DSPTYPE").append("0x0103");
- project->values("MSVCDSP_DEFINES").append(" /D \"_CONSOLE\" ");
- } else {
- project->values("MSVCDSP_TARGETTYPE").append("Application");
- project->values("MSVCDSP_DSPTYPE").append("0x0101");
- project->values("MSVCDSP_DEFINES").append(" /D \"_WINDOWS\" ");
- }
- } else {
- if(project->isActiveConfig("dll")) {
- project->values("MSVCDSP_TARGETTYPE").append("Dynamic-Link Library");
- project->values("MSVCDSP_DSPTYPE").append("0x0102");
- project->values("MSVCDSP_DEFINES").append(" /D \"_USRDLL\" ");
- } else {
- project->values("MSVCDSP_TARGETTYPE").append("Static Library");
- project->values("MSVCDSP_DSPTYPE").append("0x0104");
- project->values("MSVCDSP_DEFINES").append(" /D \"_LIB\" ");
- }
- }
-
- project->values("MSVCDSP_LFLAGS") += project->values("QMAKE_LFLAGS");
-
- if(!project->values("QMAKE_LIBDIR").isEmpty())
- project->values("MSVCDSP_LFLAGS").append(valGlue(
- escapeFilePaths(project->values("QMAKE_LIBDIR")),
- "/LIBPATH:"," /LIBPATH:",""));
-
- project->values("MSVCDSP_DEFINES").append(varGlue("DEFINES","/D ","" " /D ",""));
- project->values("MSVCDSP_DEFINES").append(varGlue("PRL_EXPORT_DEFINES","/D ","" " /D ",""));
- project->values("MSVCDSP_DEFINES").append(" /D \"WIN32\" ");
-
- QStringList &libs = project->values("QMAKE_LIBS");
- for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) {
- project->values("MSVCDSP_LIBS").append(" " + escapeFilePath(*libit));
- }
-
- QStringList &incs = project->values("INCLUDEPATH");
- for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
- QString inc = (*incit);
- project->values("MSVCDSP_INCPATH").append("/I" + escapeFilePath(inc));
- }
- project->values("MSVCDSP_INCPATH").append("/I" + escapeFilePath(specdir()));
-
- QString dest;
- QString preLinkStep;
- QString postLinkStep;
- QString copyDllStep;
-
- if(!project->values("QMAKE_PRE_LINK").isEmpty())
- preLinkStep += var("QMAKE_PRE_LINK");
-
- if(!project->values("QMAKE_POST_LINK").isEmpty())
- postLinkStep += var("QMAKE_POST_LINK");
-
- // don't destroy the target, it is used by prl writer.
- if(!project->values("DESTDIR").isEmpty()) {
- dest = project->first("DESTDIR");
- project->values("DESTDIR").first() = dest;
- dest = project->values("TARGET").first() + project->first("TARGET_EXT");
- dest.prepend(project->first("DESTDIR"));
- Option::fixPathToTargetOS(dest);
- dest = escapeFilePath(dest);
-
- project->values("MSVCDSP_TARGET").append(
- QString("/out:") + dest);
- if(project->isActiveConfig("dll")) {
- QString imp = dest;
- imp.replace(".dll", ".lib");
- project->values("MSVCDSP_TARGET").append(QString(" /implib:") + escapeFilePath(imp));
- }
- }
-
- if(project->isActiveConfig("dll") && !project->values("DLLDESTDIR").isEmpty()) {
- QStringList dlldirs = project->values("DLLDESTDIR");
- if(dlldirs.count())
- copyDllStep += "\t";
- for(QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) {
- copyDllStep += "copy \"$(TargetPath)\" " + escapeFilePath(Option::fixPathToTargetOS(*dlldir)) + "\t";
- }
- }
-
- if(!preLinkStep.isEmpty()) {
- project->values("MSVCDSP_PRE_LINK").append(
- "# Begin Special Build Tool\n"
- "SOURCE=$(InputPath)\n"
- "PreLink_Desc=Post Build Step\n"
- "PreLink_Cmds=" + preLinkStep + "\n"
- "# End Special Build Tool\n");
- }
-
- if(!postLinkStep.isEmpty() || !copyDllStep.isEmpty()) {
- project->values("MSVCDSP_POST_LINK").append(
- "# Begin Special Build Tool\n"
- "SOURCE=$(InputPath)\n"
- "PostBuild_Desc=Post Build Step\n"
- "PostBuild_Cmds=" + postLinkStep + copyDllStep + "\n"
- "# End Special Build Tool\n");
- }
-
- QStringList &formList = project->values("FORMS");
- for(QStringList::ConstIterator hit = formList.begin(); hit != formList.end(); ++hit) {
- if(exists(*hit + ".h"))
- project->values("SOURCES").append(*hit + ".h");
- }
- QStringList &form3List = project->values("FORMS3");
- for(QStringList::ConstIterator hit = form3List.begin(); hit != form3List.end(); ++hit) {
- if(exists(*hit + ".h"))
- project->values("SOURCES").append(*hit + ".h");
- }
-
- project->values("QMAKE_INTERNAL_PRL_LIBS") << "MSVCDSP_LIBS";
-
- // Move some files around //### is this compat?
- if (!project->values("IMAGES").isEmpty()) {
- QString imageFactory(project->first("QMAKE_IMAGE_COLLECTION"));
- project->values("GENERATED_SOURCES") += imageFactory;
- project->values("SOURCES").removeAll(imageFactory);
- }
-
- // Setup PCH variables
- precompH = project->first("PRECOMPILED_HEADER");
- namePCH = fileInfo(precompH).fileName();
- usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
- if (usePCH) {
- // Created files
- precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext;
- precompPch = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch.pch";
-
- // Add PRECOMPILED_HEADER to HEADERS
- if (!project->values("HEADERS").contains(precompH))
- project->values("HEADERS") += precompH;
- // Add precompile compiler options
- project->values("PRECOMPILED_FLAGS") = QStringList("/Fp" + precompPch + " /Yu" + escapeFilePath(namePCH) + " /FI" + escapeFilePath(namePCH) + " ");
- // Return to variable pool
- project->values("PRECOMPILED_OBJECT") = QStringList(precompObj);
- project->values("PRECOMPILED_PCH") = QStringList(precompPch);
- }
-
- QString buildName;
- if (!var("BUILD_NAME").isEmpty())
- buildName = var("BUILD_NAME");
- else if (project->isActiveConfig("debug"))
- buildName = "Debug";
- else
- buildName = "Release";
-
- project->values("MSVCDSP_CONFIG_NAME") = QStringList(" - " + platform + " " + buildName);
-}
-
-void DspMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
-{
- if(var == "QMAKE_PRL_DEFINES") {
- QStringList &out = project->values("MSVCDSP_DEFINES");
- for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
- if(out.indexOf((*it)) == -1)
- out.append((" /D \"" + *it + "\""));
- }
- } else {
- MakefileGenerator::processPrlVariable(var, l);
- }
-}
-
-bool DspMakefileGenerator::openOutput(QFile &file, const QString &build) const
-{
- QString outdir;
- if(!file.fileName().isEmpty()) {
- if(QDir::isRelativePath(file.fileName()))
- file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run
- QFileInfo fi(fileInfo(file.fileName()));
- if(fi.isDir())
- outdir = file.fileName() + QDir::separator();
- }
-
- if(!outdir.isEmpty() || file.fileName().isEmpty()) {
- QString ext = project->first("DSP_EXTENSION");
- if(project->first("TEMPLATE") == "vcsubdirs") {
- if (!project->first("DSW_EXTENSION").isEmpty())
- ext = project->first("DSW_EXTENSION");
- else
- ext = ".dsw";
- }
- QString outputName = unescapeFilePath(project->first("QMAKE_DSP_PROJECT_NAME"));
- if (!project->first("MAKEFILE").isEmpty())
- outputName = unescapeFilePath(project->first("MAKEFILE"));
- if (outputName.isEmpty())
- outputName = unescapeFilePath(project->first("QMAKE_ORIG_TARGET"));
- file.setFileName(outdir + outputName + ext);
- }
-
- if(QDir::isRelativePath(file.fileName())) {
- QString ofile = Option::fixPathToLocalOS(file.fileName());
- int slashfind = ofile.lastIndexOf(Option::dir_sep);
- if(slashfind == -1) {
- ofile = ofile.replace(QRegExp("-"), "_");
- } else {
- int hypenfind = ofile.indexOf('-', slashfind);
- while (hypenfind != -1 && slashfind < hypenfind) {
- ofile = ofile.replace(hypenfind, 1, "_");
- hypenfind = ofile.indexOf('-', hypenfind + 1);
- }
- }
- file.setFileName(Option::fixPathToLocalOS(qmake_getpwd() + Option::dir_sep + ofile));
- }
- return Win32MakefileGenerator::openOutput(file, build);
-}
-
-bool DspMakefileGenerator::mergeBuildProject(MakefileGenerator *other)
-{
-
- mergedProjects.prepend(static_cast<DspMakefileGenerator*>(other));
- return true;
-}
-
-bool DspMakefileGenerator::writeProjectMakefile()
-{
- bool ret = true;
-
- QTextStream t(&Option::output);
- // Check if all requirements are fulfilled
- if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
- fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
- var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData());
- return true;
- }
-
- // Generate project file
- if(project->first("TEMPLATE") == "vcapp" ||
- project->first("TEMPLATE") == "vclib") {
- if (!mergedProjects.count()) {
- warn_msg(WarnLogic, "Generator: MSVC DSP: no single configuration created, cannot output project!");
- return false;
- }
- debug_msg(1, "Generator: MSVC 6: Writing project file");
-
- writeDspHeader(t);
- for (int i = 0; i < mergedProjects.count(); ++i) {
- DspMakefileGenerator* config = mergedProjects.at(i);
- t << endl;
- if (i == 0)
- t << "!IF";
- else
- t << "!ELSEIF";
- t << " \"$(CFG)\" == \"" << configName(config) << "\"" << endl;
- t << endl;
- writeDspConfig(t, config);
- }
- t << endl;
- t << "!ENDIF " << endl;
- t << endl;
- t << "# Begin Target" << endl;
- t << endl;
- for (int i = 0; i < mergedProjects.count(); ++i)
- t << "# Name \"" << configName(mergedProjects.at(i)) << "\"" << endl;
- t << endl;
-
- QMap< QString, QSet<QString> > files;
-
- // merge source files
- for (int i = 0; i < mergedProjects.count(); ++i) {
-
- DspMakefileGenerator* config = mergedProjects.at(i);
-
- files["DEF_FILE"] += config->project->values("DEF_FILE").toSet();
- files["SOURCES"] += config->project->values("SOURCES").toSet();
- files["HEADERS"] += config->project->values("HEADERS").toSet();
- files["INTERFACES"] += config->project->values("INTERFACES").toSet();
- files["FORMS"] += config->project->values("FORMS").toSet();
- files["FORMS"] += config->project->values("FORMS3").toSet();
- files["IMAGES"] += config->project->values("IMAGES").toSet();
- files["RC_FILE"] += config->project->values("RC_FILE").toSet();
- files["RESOURCES"] += config->project->values("RESOURCES").toSet();
- files["TRANSLATIONS"] += config->project->values("TRANSLATIONS").toSet();
- files["LEXSOURCES"] += config->project->values("LEXSOURCES").toSet();
- files["YACCSOURCES"] += config->project->values("YACCSOURCES").toSet();
- files["TYPELIBS"] += config->project->values("TYPELIBS").toSet();
-
- if (!config->project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
- const QStringList &quc = config->project->values("QMAKE_EXTRA_COMPILERS");
- for (QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
- const QStringList &inputs = project->values((*it)+".input");
- for (QStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) {
- if (*input != "UIC3_HEADERS")
- files[(*input)] += config->project->values((*input)).toSet();
- }
- }
- }
- }
-
- QStringList keys = files.keys();
- for (int k = 0; k < keys.size(); ++k)
- project->values(keys.at(k)) = QList<QString>::fromSet(files[keys.at(k)]);
-
- QStringList listNames = QString("SOURCES|DEF_FILE").split("|");
- QStringList allListNames = listNames;
- writeFileGroup(t, listNames, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
- listNames = QStringList("HEADERS");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Header Files", "h;hpp;hxx;hm;inl");
- listNames = QString("FORMS|INTERFACES|FORMS3").split("|");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Form Files", "ui");
- listNames = QStringList("IMAGES");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Image Files", "");
- listNames = QString("RC_FILE|RESOURCES").split("|");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Resources", "rc;qrc");
- listNames = QStringList("TRANSLATIONS");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Translations", "ts;xlf");
- listNames = QStringList("LEXSOURCES");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Lexables", "l");
- listNames = QStringList("YACCSOURCES");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Yaccables", "y");
- listNames = QStringList("TYPELIBS");
- allListNames += listNames;
- writeFileGroup(t, listNames, "Type Libraries", "tlb;olb");
-
- for (int l = 0; l < allListNames.size(); ++l)
- keys.removeAll(allListNames.at(l));
-
- for (int k = 0; k < keys.size(); ++k)
- writeFileGroup(t, QStringList(keys.at(k)), keys.at(k) + " Files", "");
-
- // done last as generated may have changed when creating build rules for the above
- for (int i = 0; i < mergedProjects.count(); ++i) {
-
- DspMakefileGenerator* config = mergedProjects.at(i);
-
- config->project->values("SWAPPED_BUILD_STEPS") = config->swappedBuildSteps.keys();
- files["SWAPPED_BUILD_STEPS"] += config->project->values("SWAPPED_BUILD_STEPS").toSet();
-
- files["GENERATED_SOURCES"] += config->project->values("GENERATED_SOURCES").toSet();
- files["GENERATED_FILES"] += config->project->values("GENERATED_FILES").toSet();
- }
-
- project->values("SWAPPED_BUILD_STEPS") = QList<QString>::fromSet(files["SWAPPED_BUILD_STEPS"]);
- project->values("GENERATED_SOURCES") = QList<QString>::fromSet(files["GENERATED_SOURCES"]);
- project->values("GENERATED_FILES") = QList<QString>::fromSet(files["GENERATED_FILES"]);
-
- writeFileGroup(t, QString("GENERATED_SOURCES|GENERATED_FILES|SWAPPED_BUILD_STEPS").split("|"), "Generated", "");
- t << endl;
- t << "# End Target" << endl;
- t << "# End Project" << endl;
- }else if(project->first("TEMPLATE") == "vcsubdirs") {
- ret = writeMakefile(t);
- }
-
- return ret;
-}
-
-const char _dswHeader60[] = "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
-const char _dswWarning[] = "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n";
-const char _dswDevider[] = "###############################################################################\n";
-const char _dswProjectName[] = "Project: \"%1\"=%2 - Package Owner=<4>\n"; // %1 = project name, %2 = project path
-const char _dswPackage5Start[] = "Package=<5>\n{{{\n";
-const char _dswPackage5Stop[] = "}}}\n";
-const char _dswPackage4Start[] = "Package=<4>\n{{{\n";
-const char _dswPackage4Stop[] = "}}}\n";
-const char _dswProjectDep[] = " Begin Project Dependency\n Project_Dep_Name %1\n End Project Dependency\n"; // %1 = project name
-const char _dswGlobal[] = "Global:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n";
-
-
-struct WorkspaceDepend {
- QString dspProjectFile, orig_target, target;
- QStringList dependencies;
-};
-
-void DspMakefileGenerator::writeSubDirs(QTextStream &t)
-{
- // Output headers
- t << _dswHeader60;
- t << _dswWarning;
- t << endl;
-
- QHash<QString, WorkspaceDepend*> workspace_depends;
- QList<WorkspaceDepend*> workspace_cleanup;
- QStringList subdirs = project->values("SUBDIRS");
- QString oldpwd = qmake_getpwd();
-
- // Make sure that all temp projects are configured
- // for release so that the depends are created
- // without the debug <lib>dxxx.lib name mangling
- QStringList old_after_vars = Option::after_user_vars;
- Option::after_user_vars.append("CONFIG+=release");
-
- for(int i = 0; i < subdirs.size(); ++i) {
- QString tmp = subdirs.at(i);
- if(!project->isEmpty(tmp + ".file")) {
- if(!project->isEmpty(tmp + ".subdir"))
- warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
- tmp.toLatin1().constData());
- tmp = project->first(tmp + ".file");
- } else if(!project->isEmpty(tmp + ".subdir")) {
- tmp = project->first(tmp + ".subdir");
- }
-
- QFileInfo fi(fileInfo(Option::fixPathToLocalOS(tmp, true)));
- if(fi.exists()) {
- if(fi.isDir()) {
- QString profile = tmp;
- if(!profile.endsWith(Option::dir_sep))
- profile += Option::dir_sep;
- profile += fi.baseName() + Option::pro_ext;
- subdirs.append(profile);
- } else {
- QMakeProject tmp_proj;
- QString dir = fi.path(), fn = fi.fileName();
- if(!dir.isEmpty()) {
- if(!qmake_setpwd(dir))
- fprintf(stderr, "Cannot find directory: %s\n", dir.toLatin1().constData());
- }
- if(tmp_proj.read(fn)) {
- // Check if all requirements are fulfilled
- if(!tmp_proj.variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {
- fprintf(stderr, "Project file(%s) not added to Workspace because all requirements not met:\n\t%s\n",
- fn.toLatin1().constData(), tmp_proj.values("QMAKE_FAILED_REQUIREMENTS").join(" ").toLatin1().constData());
- continue;
- }
- if(tmp_proj.first("TEMPLATE") == "vcsubdirs") {
- QStringList tmp_proj_subdirs = tmp_proj.variables()["SUBDIRS"];
- for(int x = 0; x < tmp_proj_subdirs.size(); ++x) {
- QString tmpdir = tmp_proj_subdirs.at(x);
- if(!tmp_proj.isEmpty(tmpdir + ".file")) {
- if(!tmp_proj.isEmpty(tmpdir + ".subdir"))
- warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
- tmpdir.toLatin1().constData());
- tmpdir = tmp_proj.first(tmpdir + ".file");
- } else if(!tmp_proj.isEmpty(tmpdir + ".subdir")) {
- tmpdir = tmp_proj.first(tmpdir + ".subdir");
- }
- subdirs += fileFixify(tmpdir);
- }
- } else if(tmp_proj.first("TEMPLATE") == "vcapp" || tmp_proj.first("TEMPLATE") == "vclib") {
- // Initialize a 'fake' project to get the correct variables
- // and to be able to extract all the dependencies
- DspMakefileGenerator tmp_dsp;
- tmp_dsp.setNoIO(true);
- tmp_dsp.setProjectFile(&tmp_proj);
- if(Option::debug_level) {
- QMap<QString, QStringList> &vars = tmp_proj.variables();
- for(QMap<QString, QStringList>::Iterator it = vars.begin();
- it != vars.end(); ++it) {
- if(it.key().left(1) != "." && !it.value().isEmpty())
- debug_msg(1, "%s: %s === %s", fn.toLatin1().constData(), it.key().toLatin1().constData(),
- it.value().join(" :: ").toLatin1().constData());
- }
- }
-
- // We assume project filename is [QMAKE_ORIG_TARGET].vcproj
- QString dsp = unescapeFilePath(tmp_dsp.project->first("MSVCDSP_PROJECT") + project->first("DSP_EXTENSION"));
-
- // If file doesn't exsist, then maybe the users configuration
- // doesn't allow it to be created. Skip to next...
- if(!exists(qmake_getpwd() + Option::dir_sep + dsp)) {
- warn_msg(WarnLogic, "Ignored (not found) '%s'", QString(qmake_getpwd() + Option::dir_sep + dsp).toLatin1().constData());
- goto nextfile; // # Dirty!
- }
-
- WorkspaceDepend *newDep = new WorkspaceDepend;
- newDep->dspProjectFile = fileFixify(dsp);
- newDep->orig_target = unescapeFilePath(tmp_proj.first("QMAKE_ORIG_TARGET"));
- newDep->target = tmp_proj.first("MSVCDSP_PROJECT").section(Option::dir_sep, -1) + tmp_proj.first("TARGET_EXT");
-
- // We want to store it as the .lib name.
- if(newDep->target.endsWith(".dll"))
- newDep->target = newDep->target.left(newDep->target.length()-3) + "lib";
-
- // All projects having mocable sourcefiles are dependent on moc.exe
- if(tmp_proj.variables()["CONFIG"].contains("moc"))
- newDep->dependencies << "moc.exe";
-
- // All extra compilers which has valid input are considered dependencies
- const QStringList &quc = tmp_proj.variables()["QMAKE_EXTRA_COMPILERS"];
- for(QStringList::ConstIterator it = quc.constBegin(); it != quc.constEnd(); ++it) {
- const QStringList &invar = tmp_proj.variables().value((*it) + ".input");
- for(QStringList::ConstIterator iit = invar.constBegin(); iit != invar.constEnd(); ++iit) {
- const QStringList fileList = tmp_proj.variables().value(*iit);
- if (!fileList.isEmpty()) {
- QString dep = tmp_proj.first((*it) + ".commands").section('/', -1).section('\\', -1);
- if (!newDep->dependencies.contains(dep))
- newDep->dependencies << dep;
- }
- }
- }
-
- // Add all unknown libs to the deps
- QStringList where("QMAKE_LIBS");
- if(!tmp_proj.isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- where = tmp_proj.variables()["QMAKE_INTERNAL_PRL_LIBS"];
-
- for(QStringList::iterator wit = where.begin();
- wit != where.end(); ++wit) {
- QStringList &l = tmp_proj.variables()[(*wit)];
- for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
- QString opt = (*it).trimmed();
- if(!opt.startsWith("/") && // Not a switch
- opt != newDep->target && // Not self
- opt != "opengl32.lib" && // We don't care about these libs
- opt != "glu32.lib" && // to make depgen alittle faster
- opt != "kernel32.lib" &&
- opt != "user32.lib" &&
- opt != "gdi32.lib" &&
- opt != "comdlg32.lib" &&
- opt != "advapi32.lib" &&
- opt != "shell32.lib" &&
- opt != "ole32.lib" &&
- opt != "oleaut32.lib" &&
- opt != "uuid.lib" &&
- opt != "imm32.lib" &&
- opt != "winmm.lib" &&
- opt != "wsock32.lib" &&
- opt != "ws2_32.lib" &&
- opt != "winspool.lib" &&
- opt != "delayimp.lib")
- {
- newDep->dependencies << opt.section(Option::dir_sep, -1);
- }
- }
- }
- workspace_cleanup.append(newDep);
- workspace_depends.insert(newDep->target, newDep);
-
- debug_msg(1, "Generator: MSVC: Added project (name:'%s' path:'%s' deps:'%s')",
- qPrintable(newDep->target) , qPrintable(newDep->dspProjectFile),
- qPrintable(newDep->dependencies.join(";")));
- }
- }
-nextfile:
- qmake_setpwd(oldpwd);
- }
- }
- }
-
- // Restore previous after_user_var options
- Option::after_user_vars = old_after_vars;
-
- // Output all projects
- QString dswProjectName = QLatin1String(_dswProjectName);
- QString dswProjectDep = QLatin1String(_dswProjectDep);
- for(QList<WorkspaceDepend*>::Iterator it = workspace_cleanup.begin(); it != workspace_cleanup.end(); ++it) {
- t << _dswDevider;
- t << endl;
- t << dswProjectName.arg((*it)->orig_target).arg((*it)->dspProjectFile);
- t << endl;
- t << _dswPackage5Start;
- t << _dswPackage5Stop;
- t << endl;
- t << _dswPackage4Start;
-
- // Output project dependencies
- for(QStringList::iterator dit = (*it)->dependencies.begin(); dit != (*it)->dependencies.end(); ++dit) {
- if(WorkspaceDepend *vc = workspace_depends[*dit])
- t << dswProjectDep.arg(vc->orig_target);
- }
-
- t << _dswPackage4Stop;
- }
-
- // Output global part
- t << _dswDevider << endl;
- t << _dswGlobal;
- t << _dswDevider;
- t << endl << endl;
-}
-
-class FolderGroup
-{
-public:
- QString name;
- QString filter;
- QMap<QString, FolderGroup *> subFolders;
- QMap<QString, QString> files;
-
- void insertStructured(const QString &file, const QString &fileListName)
- {
- QStringList path = QFileInfo(file).path().split("/");
- if (!path.isEmpty() && path.at(0) == ".")
- path.takeAt(0);
- FolderGroup *currentFolder = this;
- for (int i = 0; i < path.size(); i++) {
- if (currentFolder->subFolders.contains(path.at(i))) {
- currentFolder = currentFolder->subFolders.value(path.at(i));
- } else {
- FolderGroup *newFolder = new FolderGroup;
- newFolder->name = path.at(i);
- currentFolder->subFolders.insert(path.at(i), newFolder);
- currentFolder = newFolder;
- }
- }
- currentFolder->files.insert(file, fileListName);
- }
-
- void insertFlat(const QString &file, const QString &fileListName)
- {
- files.insert(file, fileListName);
- }
-
- ~FolderGroup()
- {
- qDeleteAll(subFolders.values());
- }
-};
-
-bool DspMakefileGenerator::writeFileGroup(QTextStream &t, const QStringList &listNames, const QString &group, const QString &filter)
-{
- FolderGroup root;
- root.name = group;
- root.filter = filter;
-
- for (int i = 0; i < listNames.count(); ++i) {
- QStringList list = project->values(listNames.at(i));
- for (int j = 0; j < list.count(); ++j) {
- const QString name = list.at(j);
- if (name.isEmpty())
- continue;
- if (project->isActiveConfig("flat"))
- root.insertFlat(name, listNames.at(i));
- else
- root.insertStructured(name, listNames.at(i));
- }
- }
-
- if (root.files.isEmpty() && root.subFolders.isEmpty())
- return true;
-
- writeSubFileGroup(t, &root);
-
- return true;
-}
-
-void DspMakefileGenerator::writeSubFileGroup(QTextStream &t, FolderGroup *folder)
-{
- t << "# Begin Group \"" << folder->name << "\"" << endl;
- t << "# PROP Default_Filter \"" << folder->filter << "\"" << endl;
- QMap<QString, FolderGroup *>::const_iterator folderIt = folder->subFolders.begin();
- while (folderIt != folder->subFolders.end()) {
- writeSubFileGroup(t, folderIt.value());
- ++folderIt;
- }
- QMap<QString, QString>::const_iterator it = folder->files.begin();
- while (it != folder->files.end()) {
- t << "# Begin Source File" << endl;
- t << "SOURCE=" << escapeFilePath(it.key()) << endl;
- writeBuildstepForFile(t, it.key(), it.value());
- t << "# End Source File" << endl;
- t << endl;
- ++it;
- }
- t << "# End Group" << endl;
- t << endl;
-}
-
-bool DspMakefileGenerator::writeBuildstepForFile(QTextStream &t, const QString &file, const QString &listName)
-{
-
- if (!mergedProjects.count()) {
- t << writeBuildstepForFileForConfig(file, listName, this);
- return true;
- }
-
- //only add special build rules when needed
-
- QStringList specialBuilds;
- int i = 0;
- for (i = 0; i < mergedProjects.count(); ++i)
- specialBuilds += writeBuildstepForFileForConfig(file, listName, mergedProjects.at(i));
-
- // no special build just return
- if (specialBuilds.join("").isEmpty())
- return true;
-
- for (i = 0; i < mergedProjects.count(); ++i) {
- if (i == 0)
- t << "!IF";
- else
- t << "!ELSEIF";
- t << " \"$(CFG)\" == \"" << configName(mergedProjects.at(i)) << "\"" << endl;
- t << endl;
- t << specialBuilds.at(i);
- t << endl;
- }
-
- t << "!ENDIF" << endl;
-
- return true;
-}
-
-bool DspMakefileGenerator::writeDspConfig(QTextStream &t, DspMakefileGenerator *config)
-{
-
- bool isDebug = config->project->isActiveConfig("debug");
- bool staticLibTarget = config->var("MSVCDSP_DSPTYPE") == "0x0104";
-
- QString outDir = Option::fixPathToTargetOS(config->project->first("DESTDIR"));
- while (outDir.endsWith(Option::dir_sep))
- outDir.chop(1);
- outDir = config->escapeFilePath(outDir);
-
- QString intDir = config->project->first("OBJECTS_DIR");
- while (intDir.endsWith(Option::dir_sep))
- intDir.chop(1);
- intDir = config->escapeFilePath(intDir);
-
- t << "# PROP BASE Use_MFC 0" << endl;
- t << "# PROP BASE Use_Debug_Libraries " << (isDebug ? "1" : "0") << endl;
- t << "# PROP BASE Output_Dir " << outDir << endl;
- t << "# PROP BASE Intermediate_Dir " << intDir << endl;
- t << "# PROP BASE Target_Dir \"\"" << endl;
- t << "# PROP Use_MFC 0" << endl;
- t << "# PROP Use_Debug_Libraries " << (isDebug ? "1" : "0") << endl;
-
- t << "# PROP Output_Dir " << outDir << endl;
- t << "# PROP Intermediate_Dir " << intDir << endl;
- if (config->project->isActiveConfig("dll") || config->project->isActiveConfig("plugin"))
- t << "# PROP Ignore_Export_Lib 1" << endl;
- t << "# PROP Target_Dir \"\"" << endl;
- t << "# ADD CPP " << config->var("MSVCDSP_INCPATH") << " /c /FD " << config->var("QMAKE_CXXFLAGS") << " " << config->var("MSVCDSP_DEFINES") << " " << config->var("PRECOMPILED_FLAGS") << endl;
- t << "# ADD MTL /nologo /mktyplib203 /win32 /D " << (isDebug ? "\"_DEBUG\"" : "\"NDEBUG\"") << endl;
- t << "# ADD RSC /l 0x409 /d " << (isDebug ? "\"_DEBUG\"" : "\"NDEBUG\"") << endl;
- t << "# ADD BSC32 /nologo" << endl;
- if (staticLibTarget) {
- t << "LIB32=" << config->var("QMAKE_LIB") << endl;
- t << "# ADD LIB32 " << config->var("MSVCDSP_TARGET") << " " << config->var("PRECOMPILED_OBJECT") << endl;
- } else {
- t << "LINK32=" << config->var("QMAKE_LINK") << endl;
- t << "# ADD LINK32 " << config->var("MSVCDSP_LFLAGS") << " " << config->var("MSVCDSP_LIBS") << " " << config->var("MSVCDSP_TARGET") << " " << config->var("PRECOMPILED_OBJECT") << endl;
- }
-
- if (!config->project->values("MSVCDSP_PRE_LINK").isEmpty())
- t << config->project->values("MSVCDSP_PRE_LINK").first();
-
- if (!config->project->values("MSVCDSP_POST_LINK").isEmpty())
- t << config->project->values("MSVCDSP_POST_LINK").first();
-
- return true;
-}
-
-QString DspMakefileGenerator::writeBuildstepForFileForConfig(const QString &file, const QString &listName, DspMakefileGenerator *config)
-{
- QString ret;
- QTextStream t(&ret);
-
- // exclude from build
- if (!config->project->values(listName).contains(file)) {
- t << "# PROP Exclude_From_Build 1" << endl;
- return ret;
- }
-
- if (config->usePCH) {
- bool c_file = false;
- for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
- if (file.endsWith(*it)) {
- c_file = true;
- break;
- }
- }
- if(c_file) {
- t << "# SUBTRACT CPP /FI" << config->escapeFilePath(config->namePCH) << " /Yu" << config->escapeFilePath(config->namePCH) << " /Fp" << endl;
- return ret;
- } else if (config->precompH.endsWith(file)) {
- // ### dependency list quickly becomes too long for VS to grok...
- t << "USERDEP_" << file << "=" << config->valGlue(config->escapeFilePaths(config->findDependencies(config->precompH)), "", "\t", "") << endl;
- t << endl;
- t << "# Begin Custom Build - Creating precompiled header from " << file << "..." << endl;
- t << "InputPath=.\\" << config->escapeFilePath(file) << endl << endl;
- t << config->precompPch + ": $(SOURCE) \"$(IntDir)\" \"$(OUTDIR)\"" << endl;
- t << "\t" << config->var("QMAKE_CC") << " /TP /W3 /FD /c /Yc /Fp" << config->precompPch << " /Fo" << config->precompObj << " /Fd\"$(IntDir)\\\\\" " << file << " ";
- t << config->var("MSVCDSP_INCPATH") << " " << config->var("MSVCDSP_DEFINES") << " " << config->var("QMAKE_CXXFLAGS") << endl;
- t << "# End Custom Build" << endl << endl;
- return ret;
- }
- }
-
- QString fileBase = QFileInfo(file).completeBaseName();
-
- bool hasBuiltin = config->hasBuiltinCompiler(file);
- BuildStep allSteps;
-
- if (!config->swappedBuildSteps.contains(file)) {
- QStringList compilers = config->project->values("QMAKE_EXTRA_COMPILERS");
- for (int i = 0; i < compilers.count(); ++i) {
- QString compiler = compilers.at(i);
- if (config->project->values(compiler + ".input").isEmpty())
- continue;
- QString input = config->project->values(compiler + ".input").first();
- QStringList inputList = config->project->values(input);
- if (!inputList.contains(file))
- continue;
-
- QStringList compilerCommands = config->project->values(compiler + ".commands");
- QStringList compilerOutput = config->project->values(compiler + ".output");
- if (compilerCommands.isEmpty() || compilerOutput.isEmpty())
- continue;
-
- QStringList compilerName = config->project->values(compiler + ".name");
- if (compilerName.isEmpty())
- compilerName << compiler;
- QStringList compilerDepends = config->project->values(compiler + ".depends");
- QString compilerDependsCommand = config->project->values(compiler + ".depend_command").join(" ");
- if (!compilerDependsCommand.isEmpty()) {
- if(!config->canExecute(compilerDependsCommand))
- compilerDependsCommand = QString();
- }
- QStringList compilerConfig = config->project->values(compiler + ".CONFIG");
-
- if (!config->verifyExtraCompiler(compiler, file))
- continue;
-
- bool combineAll = compilerConfig.contains("combine");
- if (combineAll && inputList.first() != file)
- continue;
-
- QString fileIn("$(InputPath)");
-
- if (combineAll && !inputList.isEmpty()) {
- fileIn = inputList.join(" ");
- compilerDepends += inputList;
- }
-
- QString fileOut = compilerOutput.first();
- QString fileOutBase = QFileInfo(fileOut).completeBaseName();
- fileOut.replace("${QMAKE_FILE_IN}", fileIn);
- fileOut.replace("${QMAKE_FILE_BASE}", fileBase);
- fileOut.replace("${QMAKE_FILE_OUT_BASE}", fileOutBase);
- fileOut.replace('/', '\\');
-
- BuildStep step;
- for (int i2 = 0; i2 < compilerDepends.count(); ++i2) {
- QString dependency = compilerDepends.at(i2);
- dependency.replace("${QMAKE_FILE_IN}", fileIn);
- dependency.replace("${QMAKE_FILE_BASE}", fileBase);
- dependency.replace("${QMAKE_FILE_OUT_BASE}", fileOutBase);
- dependency.replace('/', '\\');
- if (!step.deps.contains(dependency, Qt::CaseInsensitive))
- step.deps << dependency;
- }
- // depends command
- if (!compilerDependsCommand.isEmpty() && config->doDepends()) {
- char buff[256];
- QString dep_cmd = config->replaceExtraCompilerVariables(compilerDependsCommand, file,
- fileOut);
- dep_cmd = Option::fixPathToLocalOS(dep_cmd, true, false);
- if(config->canExecute(dep_cmd)) {
- if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) {
- QString indeps;
- while(!feof(proc)) {
- int read_in = (int)fread(buff, 1, 255, proc);
- if(!read_in)
- break;
- indeps += QByteArray(buff, read_in);
- }
- QT_PCLOSE(proc);
- if(!indeps.isEmpty())
- step.deps += config->fileFixify(indeps.replace('\n', ' ').simplified().split(' '));
- }
- }
- }
-
-
- QString mappedFile;
- if (hasBuiltin) {
- mappedFile = fileOut;
- fileOut = fileIn;
- fileIn = file;
- }
-
- step.buildStep += " \\\n\t";
- QString command(compilerCommands.join(" "));
- // Replace any newlines with proper line-continuance
- command.replace("\n", " \\\n\t");
- // Might be a macro, and not a valid filename, so the replaceExtraCompilerVariables() would eat it
- command.replace("${QMAKE_FILE_IN}", config->escapeFilePath(fileIn));
- command.replace("${QMAKE_FILE_BASE}", config->escapeFilePath(fileBase));
- command.replace("${QMAKE_FILE_OUT_BASE}", config->escapeFilePath(fileOutBase));
- command.replace("${QMAKE_FILE_OUT}", config->escapeFilePath(fileOut));
-
- command = config->replaceExtraCompilerVariables(command, fileIn, fileOut);
-
- step.buildName = compilerName.first();
- step.buildStep += command;
- step.buildOutputs += fileOut;
-
- if (hasBuiltin) {
- step.deps << fileIn;
- config->swappedBuildSteps[mappedFile] = step;
- } else {
- allSteps << step;
- }
- }
- } else {
- allSteps << config->swappedBuildSteps.value(file);
- }
-
- if (allSteps.buildStep.isEmpty())
- return ret;
-
- int i;
- QStringList dependencyList;
- // remove dependencies that are also output
- for (i = 0; i < 1; ++i) {
- QStringList buildOutput(allSteps.buildOutputs.at(i));
-
- for (int i2 = 0; i2 < allSteps.deps.count(); ++i2) {
- QString dependency = allSteps.deps.at(i2);
- if (!buildOutput.contains(dependency) && !dependencyList.contains(dependency))
- dependencyList << dependency;
- }
- }
- QString allDependencies = config->valGlue(dependencyList, "", "\t", "");
- t << "USERDEP_" << file << "=" << allDependencies << endl;
- t << "# PROP Ignore_Default_Tool 1" << endl;
- t << "# Begin Custom Build - Running " << allSteps.buildName << " on " << file << endl;
- t << "InputPath=" << file << endl;
- t << "BuildCmds= " << allSteps.buildStep << endl;
- for (i = 0; i < allSteps.buildOutputs.count(); ++i) {
- t << config->escapeFilePath(allSteps.buildOutputs.at(i))
- << " : $(SOURCE) $(INTDIR) $(OUTDIR)\n\t$(BuildCmds)\n";
- }
- t << endl;
- t << "# End Custom Build" << endl;
-
- return ret;
-}
-
-QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msvc_dsp.h b/qmake/generators/win32/msvc_dsp.h
deleted file mode 100644
index f3e2435..0000000
--- a/qmake/generators/win32/msvc_dsp.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the qmake application of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef MSVC_DSP_H
-#define MSVC_DSP_H
-
-#include "winmakefile.h"
-
-QT_BEGIN_NAMESPACE
-
-class FolderGroup;
-
-class DspMakefileGenerator : public Win32MakefileGenerator
-{
- bool init_flag;
- bool writeDspHeader(QTextStream &);
- bool writeDspParts(QTextStream &);
- bool writeFileGroup(QTextStream &t, const QStringList &listNames, const QString &group, const QString &filter);
- void writeSubFileGroup(QTextStream &t, FolderGroup *folder);
- bool writeBuildstepForFile(QTextStream &t, const QString &file, const QString &listName);
- static bool writeDspConfig(QTextStream &t, DspMakefileGenerator *config);
- static QString writeBuildstepForFileForConfig(const QString &file, const QString &listName, DspMakefileGenerator *config);
- QString configName(DspMakefileGenerator * config);
-
- bool writeMakefile(QTextStream &);
- bool writeProjectMakefile();
- void writeSubDirs(QTextStream &t);
- void init();
-
-public:
- DspMakefileGenerator();
- ~DspMakefileGenerator();
-
- bool openOutput(QFile &file, const QString &build) const;
- bool hasBuiltinCompiler(const QString &filename) const;
-
-protected:
- virtual bool doDepends() const { return false; } //never necesary
- virtual void processSources() { filterIncludedFiles("SOURCES"); filterIncludedFiles("GENERATED_SOURCES"); }
- virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &);
- inline QString replaceExtraCompilerVariables(const QString &val, const QString &in, const QString &out)
- { return MakefileGenerator::replaceExtraCompilerVariables(val, in, out); }
- virtual bool supportsMetaBuild() { return true; }
- virtual bool supportsMergedBuilds() { return true; }
- virtual bool mergeBuildProject(MakefileGenerator *other);
- virtual void processPrlVariable(const QString &, const QStringList &);
- virtual bool findLibraries();
-
- bool usePCH;
- QString precompH, namePCH,
- precompObj, precompPch;
-
- QString platform;
-
- struct BuildStep {
- BuildStep() {}
- BuildStep &operator<<(const BuildStep &other) {
- deps << other.deps;
- buildStep += other.buildStep;
- buildName += other.buildName;
- buildOutputs += other.buildOutputs;
- return *this;
- }
-
- QStringList deps;
- QString buildStep;
- QString buildName;
- QStringList buildOutputs;
- };
- QMap<QString, BuildStep> swappedBuildSteps;
-
- // Holds all configurations for glue (merged) project
- QList<DspMakefileGenerator*> mergedProjects;
-};
-
-inline DspMakefileGenerator::~DspMakefileGenerator()
-{ }
-
-inline bool DspMakefileGenerator::findLibraries()
-{ return Win32MakefileGenerator::findLibraries("MSVCDSP_LIBS"); }
-
-QT_END_NAMESPACE
-
-#endif // MSVC_DSP_H
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 47986f5..3536a02 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -1721,8 +1721,7 @@ QString VcprojGenerator::findTemplate(QString file)
!exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2002/" + file))) &&
!exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2003/" + file))) &&
!exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2005/" + file))) &&
- !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2008/" + file))) &&
- !exists((ret = (QString(qgetenv("HOME")) + "/.tmake/" + file))))
+ !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2008/" + file))))
return "";
debug_msg(1, "Generator: MSVC.NET: Found template \'%s\'", ret.toLatin1().constData());
return ret;
diff --git a/qmake/option.cpp b/qmake/option.cpp
index 5e06721..18f0541 100644
--- a/qmake/option.cpp
+++ b/qmake/option.cpp
@@ -250,8 +250,6 @@ Option::parseCommandLine(int argc, char **argv, int skip)
Option::user_template = argv[++x];
} else if(opt == "tp" || opt == "template_prefix") {
Option::user_template_prefix = argv[++x];
- } else if(opt == "mac9") {
- Option::target_mode = TARG_MAC9_MODE;
} else if(opt == "macx") {
Option::target_mode = TARG_MACX_MODE;
} else if(opt == "unix") {
@@ -532,10 +530,7 @@ Option::init(int argc, char **argv)
Option::obj_ext = ".obj";
Option::res_ext = ".res";
} else {
- if(Option::target_mode == Option::TARG_MAC9_MODE)
- Option::dir_sep = ":";
- else
- Option::dir_sep = "/";
+ Option::dir_sep = "/";
Option::obj_ext = ".o";
}
Option::qmake_abslocation = Option::fixPathToTargetOS(Option::qmake_abslocation);
diff --git a/qmake/option.h b/qmake/option.h
index fe9a4ef..514e442 100644
--- a/qmake/option.h
+++ b/qmake/option.h
@@ -150,7 +150,7 @@ struct Option
static int warn_level;
static bool recursive;
static QStringList before_user_vars, after_user_vars, user_configs, after_user_configs;
- enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE };
+ enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE };
static TARG_MODE target_mode;
static QString user_template, user_template_prefix;
static QStringList shellPath;
diff --git a/qmake/project.cpp b/qmake/project.cpp
index 4ce8ba4..8871152 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -183,9 +183,7 @@ static QString remove_quotes(const QString &arg)
static QString varMap(const QString &x)
{
QString ret(x);
- if(ret.startsWith("TMAKE")) //tmake no more!
- ret = "QMAKE" + ret.mid(5);
- else if(ret == "INTERFACES")
+ if(ret == "INTERFACES")
ret = "FORMS";
else if(ret == "QMAKE_POST_BUILD")
ret = "QMAKE_POST_LINK";
@@ -612,10 +610,6 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0)
concat << base_concat + QDir::separator() + "win32";
break;
}
- case Option::TARG_MAC9_MODE:
- concat << base_concat + QDir::separator() + "mac";
- concat << base_concat + QDir::separator() + "mac9";
- break;
}
concat << base_concat;
}
@@ -1456,9 +1450,6 @@ QMakeProject::read(uchar cmd)
while(qmakespec.endsWith(QString(QChar(QDir::separator()))))
qmakespec.truncate(qmakespec.length()-1);
QString spec = qmakespec + QDir::separator() + "qmake.conf";
- if(!QFile::exists(spec) &&
- QFile::exists(qmakespec + QDir::separator() + "tmake.conf"))
- spec = qmakespec + QDir::separator() + "tmake.conf";
debug_msg(1, "QMAKESPEC conf: reading %s", spec.toLatin1().constData());
if(!read(spec, base_vars)) {
fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.toLatin1().constData());
@@ -1617,12 +1608,7 @@ QMakeProject::isActiveConfig(const QString &x, bool regex, QMap<QString, QString
if((Option::target_mode == Option::TARG_MACX_MODE ||
Option::target_mode == Option::TARG_UNIX_MODE) && x == "unix")
return !isForSymbian();
- else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx")
- return !isForSymbian();
- else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9")
- return !isForSymbian();
- else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) &&
- x == "mac")
+ else if(Option::target_mode == Option::TARG_MACX_MODE && (x == "macx" || x == "mac"))
return !isForSymbian();
else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32")
return !isForSymbian();
@@ -3080,8 +3066,6 @@ QStringList &QMakeProject::values(const QString &_var, QMap<QString, QStringList
QString orig_template = place["TEMPLATE"].first(), real_template;
if(!Option::user_template_prefix.isEmpty() && !orig_template.startsWith(Option::user_template_prefix))
real_template = Option::user_template_prefix + orig_template;
- if(real_template.endsWith(".t"))
- real_template = real_template.left(real_template.length()-2);
if(!real_template.isEmpty()) {
var = ".BUILTIN." + var;
place[var] = QStringList(real_template);
diff --git a/qmake/property.cpp b/qmake/property.cpp
index 34368cd..cab034f 100644
--- a/qmake/property.cpp
+++ b/qmake/property.cpp
@@ -104,7 +104,7 @@ QMakeProperty::value(QString v, bool just_check)
else if(v == "QT_INSTALL_DEMOS")
return QLibraryInfo::location(QLibraryInfo::DemosPath);
else if(v == "QMAKE_MKSPECS")
- return qmake_mkspec_paths().join(Option::target_mode == Option::TARG_WIN_MODE ? ";" : ":");
+ return qmake_mkspec_paths().join(Option::dirlist_sep);
else if(v == "QMAKE_VERSION")
return qmake_version();
#ifdef QT_VERSION_STR
diff --git a/qmake/qmake.pri b/qmake/qmake.pri
index efe4f36..17d9518 100644
--- a/qmake/qmake.pri
+++ b/qmake/qmake.pri
@@ -12,7 +12,7 @@ SOURCES += project.cpp property.cpp main.cpp generators/makefile.cpp \
generators/makefiledeps.cpp generators/metamakefile.cpp generators/mac/pbuilder_pbx.cpp \
generators/xmloutput.cpp generators/win32/borland_bmake.cpp \
generators/win32/msvc_nmake.cpp generators/projectgenerator.cpp \
- generators/win32/msvc_dsp.cpp generators/win32/msvc_vcproj.cpp \
+ generators/win32/msvc_vcproj.cpp \
generators/win32/msvc_objectmodel.cpp \
generators/symbian/symmake.cpp \
generators/symbian/symmake_abld.cpp \
@@ -24,7 +24,7 @@ HEADERS += project.h property.h generators/makefile.h \
generators/win32/winmakefile.h generators/projectgenerator.h \
generators/makefiledeps.h generators/metamakefile.h generators/mac/pbuilder_pbx.h \
generators/xmloutput.h generators/win32/borland_bmake.h generators/win32/msvc_nmake.h \
- generators/win32/msvc_dsp.h generators/win32/msvc_vcproj.h \
+ generators/win32/msvc_vcproj.h \
generators/win32/mingw_make.h generators/win32/msvc_objectmodel.h \
generators/symbian/symmake.h \
generators/symbian/symmake_abld.h \
diff --git a/qmake/qmake.pro b/qmake/qmake.pro
index 560aee9..00dcbce 100644
--- a/qmake/qmake.pro
+++ b/qmake/qmake.pro
@@ -17,9 +17,15 @@ VPATH += $$QT_SOURCE_TREE/src/corelib/global \
$$QT_SOURCE_TREE/src/corelib/kernel \
$$QT_SOURCE_TREE/src/corelib/codecs \
$$QT_SOURCE_TREE/src/corelib/plugin \
- $$QT_SOURCE_TREE/src/corelib/xml \
- $$QT_SOURCE_TREE/src/corelib/io
-INCPATH += generators generators/unix generators/win32 generators/mac generators/symbian \
- $$QT_SOURCE_TREE/include $$QT_SOURCE_TREE/include/QtCore
+ $$QT_SOURCE_TREE/src/corelib/xml \
+ $$QT_SOURCE_TREE/src/corelib/io
+INCPATH += generators \
+ generators/unix \
+ generators/win32 \
+ generators/mac \
+ generators/symbian \
+ $$QT_SOURCE_TREE/include \
+ $$QT_SOURCE_TREE/include/QtCore \
+ $$QT_SOURCE_TREE/qmake
include(qmake.pri)
diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp
index 1eddaee..09d42a4 100644
--- a/src/3rdparty/phonon/ds9/videowidget.cpp
+++ b/src/3rdparty/phonon/ds9/videowidget.cpp
@@ -223,6 +223,9 @@ namespace Phonon
if (toNative && m_noNativeRendererSupported)
return current; //no switch here
+ if (!mediaObject())
+ return current;
+
//firt we delete the renderer
//initialization of the widgets
for(int i = 0; i < FILTER_COUNT; ++i) {
diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.cpp b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
index 4a6ce29..d4f5223 100644
--- a/src/3rdparty/phonon/mmf/environmentalreverb.cpp
+++ b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
@@ -139,77 +139,68 @@ bool EnvironmentalReverb::getParameters(CMdaAudioOutputStream *stream,
TInt32 min, max;
TUint32 umin, umax;
- // DecayHFRatio
- // Ratio of high-frequency decay time to the value specified by
- // DecayTime.
effect->DecayHFRatioRange(umin, umax);
+ //: DecayHFRatio: Ratio of high-frequency decay time to the value specified by
+ //: DecayTime.
parameters.append(createParameter(
DecayHFRatio, tr("Decay HF ratio (%)"), effect->DecayHFRatio(),
umin, umax));
- // DecayTime
- // Time over which reverberation is diminished.
effect->DecayTimeRange(umin, umax);
+ //: DecayTime: Time over which reverberation is diminished.
parameters.append(createParameter(
DecayTime, tr("Decay time (ms)"), effect->DecayTime(),
umin, umax));
- // Density
- // Delay between first and subsequent reflections.
- // Note that the S60 platform documentation does not make clear
- // the distinction between this value and the Diffusion value.
+ //: Density Delay between first and subsequent reflections.
+ //: Note that the S60 platform documentation does not make clear
+ //: the distinction between this value and the Diffusion value.
parameters.append(createParameter(
Density, tr("Density (%)"), effect->Density(), 0, 100));
- // Diffusion
- // Delay between first and subsequent reflections.
- // Note that the S60 platform documentation does not make clear
- // the distinction between this value and the Density value.
+ //: Diffusion: Delay between first and subsequent reflections.
+ //: Note that the S60 platform documentation does not make clear
+ //: the distinction between this value and the Density value.
parameters.append(createParameter(
Diffusion, tr("Diffusion (%)"), effect->Diffusion(), 0, 100));
- // ReflectionsDelay
- // Amount of delay between the arrival the direct path from the
- // source and the arrival of the first reflection.
+ //: ReflectionsDelay: Amount of delay between the arrival the direct
+ //: path from the source and the arrival of the first reflection.
parameters.append(createParameter(
ReflectionsDelay, tr("Reflections delay (ms)"),
effect->ReflectionsDelay(), 0, effect->ReflectionsDelayMax()));
- // ReflectionsLevel
- // Amplitude of reflections. This value is corrected by the RoomLevel
- // to give the final reflection amplitude.
- effect->ReflectionLevelRange(min, max);
+ effect->ReflectionLevelRange(min, max);
+ //: ReflectionsLevel: Amplitude of reflections. This value is
+ //: corrected by the RoomLevel to give the final reflection amplitude.
parameters.append(createParameter(
ReflectionsLevel, tr("Reflections level (mB)"),
effect->ReflectionsLevel(),
min, max, EffectParameter::LogarithmicHint));
- // ReverbDelay
- // Amount of time between arrival of the first reflection and start of
- // the late reverberation.
+ //: ReverbDelay: Amount of time between arrival of the first
+ //: reflection and start of the late reverberation.
parameters.append(createParameter(
ReverbDelay, tr("Reverb delay (ms)"), effect->ReverbDelay(),
0, effect->ReverbDelayMax()));
- // ReverbLevel
- // Amplitude of reverberations. This value is corrected by the
- // RoomLevel to give the final reverberation amplitude.
effect->ReverbLevelRange(min, max);
+ //: ReverbLevel Amplitude of reverberations. This value is
+ //: corrected by the RoomLevel to give the final reverberation
+ //: amplitude.
parameters.append(createParameter(
ReverbLevel, tr("Reverb level (mB)"), effect->ReverbLevel(),
min, max, EffectParameter::LogarithmicHint));
- // RoomHFLevel
- // Amplitude of low-pass filter used to attenuate the high frequency
- // component of reflected sound.
effect->RoomHFLevelRange(min, max);
+ //: RoomHFLevel: Amplitude of low-pass filter used to attenuate the
+ //: high frequency component of reflected sound.
parameters.append(createParameter(
RoomHFLevel, tr("Room HF level"), effect->RoomHFLevel(),
min, max));
- // RoomLevel
- // Master volume control for all reflected sound.
effect->RoomLevelRange(min, max);
+ //: RoomLevel: Master volume control for all reflected sound.
parameters.append(createParameter(
RoomLevel, tr("Room level (mB)"), effect->RoomLevel(),
min, max, EffectParameter::LogarithmicHint));
diff --git a/src/3rdparty/s60/eiksoftkeyimage.h b/src/3rdparty/s60/eiksoftkeyimage.h
new file mode 100644
index 0000000..a658421
--- /dev/null
+++ b/src/3rdparty/s60/eiksoftkeyimage.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EIKSOFTKEYIMAGE_H
+#define EIKSOFTKEYIMAGE_H
+
+// FORWARD DECLARATIONS
+class CEikButtonGroupContainer;
+
+// CLASS DECLARATION
+
+/**
+* Changes cba button's label to image.
+*
+* @lib EIKCOCTL
+* @since 2.0
+*/
+class EikSoftkeyImage
+ {
+ public:
+
+ /**
+ * Set image to cba button by replacing label
+ * @since 2.0
+ * @param aButtonGroupContainer Button container
+ * @param aImage Image to button,
+ * Takes Images ownership
+ * @param aLeft Boolean: left or right button.
+ * If true, then change left,
+ * if false, change right
+ */
+ IMPORT_C static void SetImage(CEikButtonGroupContainer* aButtonGroupContainer, CEikImage& aImage, TBool aLeft);
+
+ /**
+ * Change to cba button image back to label
+ * @since 2.0
+ * @param aButtonGroupContainer Button container
+ * @param aLeft Boolean: left or right button.
+ * If true, then change left,
+ * if false, change right
+ */
+ IMPORT_C static void SetLabel(CEikButtonGroupContainer* aButtonGroupContainer, TBool aLeft);
+
+ private:
+
+ /**
+ * C++ default constructor.
+ */
+ EikSoftkeyImage() {};
+
+
+ };
+
+#endif // EIKSOFTKEYIMAGE_H
+
+// End of File
+
diff --git a/src/3rdparty/webkit/JavaScriptCore/ChangeLog b/src/3rdparty/webkit/JavaScriptCore/ChangeLog
index b943840..6446773 100644
--- a/src/3rdparty/webkit/JavaScriptCore/ChangeLog
+++ b/src/3rdparty/webkit/JavaScriptCore/ChangeLog
@@ -1,3 +1,16 @@
+2010-02-09 Janne Koskinen <janne.p.koskinen@digia.com>
+
+ Reviewed by Laszlo Gombos.
+
+ [Qt] use nanval() for Symbian as nonInlineNaN
+ https://bugs.webkit.org/show_bug.cgi?id=34170
+
+ numeric_limits<double>::quiet_NaN is broken in Symbian
+ causing NaN to be evaluated as a number.
+
+ * runtime/JSValue.cpp:
+ (JSC::nonInlineNaN):
+
2010-01-07 Norbert Leser <norbert.leser@nokia.com>
Reviewed by NOBODY (OOPS!).
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp
index 699c1cd..bafb85b 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp
@@ -174,7 +174,11 @@ uint32_t toUInt32SlowCase(double d, bool& ok)
NEVER_INLINE double nonInlineNaN()
{
+#if PLATFORM(SYMBIAN)
+ return nanval();
+#else
return std::numeric_limits<double>::quiet_NaN();
+#endif
}
} // namespace JSC
diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION
index c304876..cc0e04f 100644
--- a/src/3rdparty/webkit/VERSION
+++ b/src/3rdparty/webkit/VERSION
@@ -8,4 +8,4 @@ The commit imported was from the
and has the sha1 checksum
- 69dd29fbeb12d076741dce70ac6bc155101ccd6f
+ ffae5e11181a3961193fa21ea405851cad714d4b
diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog
index 18d119a..61c2227 100644
--- a/src/3rdparty/webkit/WebCore/ChangeLog
+++ b/src/3rdparty/webkit/WebCore/ChangeLog
@@ -1,7 +1,57 @@
+2010-01-14 Diego Gonzalez <diego.gonzalez@openbossa.org>
+
+ Reviewed by Kenneth Christiansen.
+
+ [Qt] Missing fileSystemPath() method in Qt KURL implementation
+ https://bugs.webkit.org/show_bug.cgi?id=33614
+
+ No new tests.
+
+ * platform/qt/KURLQt.cpp:
+ (WebCore::KURL::fileSystemPath):
+
2010-02-01 Andreas Kling <andreas.kling@nokia.com>
Reviewed by Kenneth Rohde Christiansen.
+ [Qt] In the StyledPainter determine the style from the Render and Scrollbar theme instead of from the paint device
+ https://bugs.webkit.org/show_bug.cgi?id=34054
+
+ Getting the style from the painter's paint device is a hack that breaks when
+ the paint device's style is different than the style that is used when
+ calculating the metries earlier when there is no painter available.
+
+ This change moves us closer to always using the same style.
+
+ * platform/qt/RenderThemeQt.cpp:
+ (WebCore::StylePainter::StylePainter):
+ (WebCore::StylePainter::init):
+ (WebCore::RenderThemeQt::paintButton):
+ (WebCore::RenderThemeQt::paintTextField):
+ (WebCore::RenderThemeQt::paintMenuList):
+ (WebCore::RenderThemeQt::paintMenuListButton):
+ (WebCore::RenderThemeQt::paintSliderTrack):
+ (WebCore::RenderThemeQt::paintMediaMuteButton):
+ (WebCore::RenderThemeQt::paintMediaPlayButton):
+ (WebCore::RenderThemeQt::paintMediaSliderTrack):
+ (WebCore::RenderThemeQt::paintMediaSliderThumb):
+ * platform/qt/RenderThemeQt.h:
+ * platform/qt/ScrollbarThemeQt.cpp:
+ (WebCore::ScrollbarThemeQt::paint):
+ (WebCore::ScrollbarThemeQt::hitTest):
+ (WebCore::ScrollbarThemeQt::shouldCenterOnThumb):
+ (WebCore::ScrollbarThemeQt::scrollbarThickness):
+ (WebCore::ScrollbarThemeQt::thumbLength):
+ (WebCore::ScrollbarThemeQt::trackPosition):
+ (WebCore::ScrollbarThemeQt::trackLength):
+ (WebCore::ScrollbarThemeQt::paintScrollCorner):
+ (WebCore::ScrollbarThemeQt::style):
+ * platform/qt/ScrollbarThemeQt.h:
+
+2010-01-25 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
[Qt] Use the fallback style on Maemo 5
https://bugs.webkit.org/show_bug.cgi?id=34376
diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro
index 7b0366d..c9b622a 100644
--- a/src/3rdparty/webkit/WebCore/WebCore.pro
+++ b/src/3rdparty/webkit/WebCore/WebCore.pro
@@ -26,9 +26,7 @@ symbian: {
# RO text (code) section in qtwebkit.dll exceeds allocated space for gcce udeb target.
# Move RW-section base address to start from 0xE00000 instead of the toolchain default 0x400000.
- MMP_RULES += "LINKEROPTION armcc --rw-base 0xE00000"
- MMP_RULES += ALWAYS_BUILD_AS_ARM
- QMAKE_CXXFLAGS.ARMCC += -OTime -O3
+ QMAKE_LFLAGS.ARMCC += --rw-base 0xE00000
}
include($$PWD/../WebKit.pri)
diff --git a/src/3rdparty/webkit/WebCore/platform/qt/KURLQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/KURLQt.cpp
index 0763fe0..1f62006 100644
--- a/src/3rdparty/webkit/WebCore/platform/qt/KURLQt.cpp
+++ b/src/3rdparty/webkit/WebCore/platform/qt/KURLQt.cpp
@@ -95,8 +95,10 @@ KURL::operator QUrl() const
String KURL::fileSystemPath() const
{
- notImplemented();
- return String();
+ if (!isValid() || !protocolIs("file"))
+ return String();
+
+ return String(path());
}
}
diff --git a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp
index 6a1eee8..37a6408 100644
--- a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp
@@ -44,6 +44,7 @@
#include "Page.h"
#include "RenderBox.h"
#include "RenderTheme.h"
+#include "ScrollbarThemeQt.h"
#include "UserAgentStyleSheets.h"
#include "QWebPageClient.h"
#include "qwebpage.h"
@@ -66,17 +67,17 @@ namespace WebCore {
using namespace HTMLNames;
-StylePainter::StylePainter(const RenderObject::PaintInfo& paintInfo)
+StylePainter::StylePainter(RenderThemeQt* theme, const RenderObject::PaintInfo& paintInfo)
{
- init(paintInfo.context ? paintInfo.context : 0);
+ init(paintInfo.context ? paintInfo.context : 0, theme->qStyle());
}
-StylePainter::StylePainter(GraphicsContext* context)
+StylePainter::StylePainter(ScrollbarThemeQt* theme, GraphicsContext* context)
{
- init(context);
+ init(context, theme->style());
}
-void StylePainter::init(GraphicsContext* context)
+void StylePainter::init(GraphicsContext* context, QStyle* themeStyle)
{
painter = static_cast<QPainter*>(context->platformContext());
widget = 0;
@@ -85,7 +86,7 @@ void StylePainter::init(GraphicsContext* context)
dev = painter->device();
if (dev && dev->devType() == QInternal::Widget)
widget = static_cast<QWidget*>(dev);
- style = (widget ? widget->style() : QApplication::style());
+ style = themeStyle;
if (painter) {
// the styles often assume being called with a pristine painter where no brush is set,
@@ -464,7 +465,7 @@ void RenderThemeQt::setButtonPadding(RenderStyle* style) const
bool RenderThemeQt::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
- StylePainter p(i);
+ StylePainter p(this, i);
if (!p.isValid())
return true;
@@ -497,7 +498,7 @@ void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style,
bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
- StylePainter p(i);
+ StylePainter p(this, i);
if (!p.isValid())
return true;
@@ -566,7 +567,7 @@ void RenderThemeQt::setPopupPadding(RenderStyle* style) const
bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
- StylePainter p(i);
+ StylePainter p(this, i);
if (!p.isValid())
return true;
@@ -606,7 +607,7 @@ void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* st
bool RenderThemeQt::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i,
const IntRect& r)
{
- StylePainter p(i);
+ StylePainter p(this, i);
if (!p.isValid())
return true;
@@ -837,7 +838,7 @@ bool RenderThemeQt::paintMediaMuteButton(RenderObject* o, const RenderObject::Pa
if (!mediaElement)
return false;
- StylePainter p(paintInfo);
+ StylePainter p(this, paintInfo);
if (!p.isValid())
return true;
@@ -866,7 +867,7 @@ bool RenderThemeQt::paintMediaPlayButton(RenderObject* o, const RenderObject::Pa
if (!mediaElement)
return false;
- StylePainter p(paintInfo);
+ StylePainter p(this, paintInfo);
if (!p.isValid())
return true;
@@ -905,7 +906,7 @@ bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const RenderObject::P
if (!mediaElement)
return false;
- StylePainter p(paintInfo);
+ StylePainter p(this, paintInfo);
if (!p.isValid())
return true;
@@ -932,7 +933,7 @@ bool RenderThemeQt::paintMediaSliderThumb(RenderObject* o, const RenderObject::P
if (!mediaElement)
return false;
- StylePainter p(paintInfo);
+ StylePainter p(this, paintInfo);
if (!p.isValid())
return true;
diff --git a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h
index 19337ac..13fb42f 100644
--- a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h
+++ b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h
@@ -35,6 +35,7 @@ namespace WebCore {
class RenderStyle;
class HTMLMediaElement;
+class ScrollbarThemeQt;
class RenderThemeQt : public RenderTheme {
private:
@@ -75,6 +76,8 @@ public:
virtual String extraMediaControlsStyleSheet();
#endif
+ QStyle* qStyle() const;
+
protected:
virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
virtual void setCheckboxSize(RenderStyle*) const;
@@ -137,7 +140,6 @@ private:
void setButtonPadding(RenderStyle*) const;
void setPopupPadding(RenderStyle*) const;
- QStyle* qStyle() const;
QStyle* fallbackStyle() const;
Page* m_page;
@@ -152,8 +154,8 @@ private:
class StylePainter {
public:
- explicit StylePainter(const RenderObject::PaintInfo& paintInfo);
- explicit StylePainter(GraphicsContext* context);
+ explicit StylePainter(RenderThemeQt*, const RenderObject::PaintInfo&);
+ explicit StylePainter(ScrollbarThemeQt*, GraphicsContext*);
~StylePainter();
bool isValid() const { return painter && style; }
@@ -170,7 +172,7 @@ public:
{ style->drawComplexControl(cc, &opt, painter, widget); }
private:
- void init(GraphicsContext* context);
+ void init(GraphicsContext* context, QStyle*);
QBrush oldBrush;
bool oldAntialiasing;
diff --git a/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.cpp
index 561e55f..c0692ca 100644
--- a/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.cpp
+++ b/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.cpp
@@ -140,7 +140,7 @@ bool ScrollbarThemeQt::paint(Scrollbar* scrollbar, GraphicsContext* graphicsCont
return false;
}
- StylePainter p(graphicsContext);
+ StylePainter p(this, graphicsContext);
if (!p.isValid())
return true;
@@ -172,14 +172,14 @@ ScrollbarPart ScrollbarThemeQt::hitTest(Scrollbar* scrollbar, const PlatformMous
QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
const QPoint pos = scrollbar->convertFromContainingWindow(evt.pos());
opt->rect.moveTo(QPoint(0, 0));
- QStyle::SubControl sc = QApplication::style()->hitTestComplexControl(QStyle::CC_ScrollBar, opt, pos, 0);
+ QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, opt, pos, 0);
return scrollbarPart(sc);
}
bool ScrollbarThemeQt::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
{
// Middle click centers slider thumb (if supported)
- return QApplication::style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition) && evt.button() == MiddleButton;
+ return style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition) && evt.button() == MiddleButton;
}
void ScrollbarThemeQt::invalidatePart(Scrollbar* scrollbar, ScrollbarPart)
@@ -190,13 +190,12 @@ void ScrollbarThemeQt::invalidatePart(Scrollbar* scrollbar, ScrollbarPart)
int ScrollbarThemeQt::scrollbarThickness(ScrollbarControlSize controlSize)
{
- QStyle* s = QApplication::style();
QStyleOptionSlider o;
o.orientation = Qt::Vertical;
o.state &= ~QStyle::State_Horizontal;
if (controlSize != RegularScrollbar)
o.state |= QStyle::State_Mini;
- return s->pixelMetric(QStyle::PM_ScrollBarExtent, &o, 0);
+ return style()->pixelMetric(QStyle::PM_ScrollBarExtent, &o, 0);
}
int ScrollbarThemeQt::thumbPosition(Scrollbar* scrollbar)
@@ -209,21 +208,21 @@ int ScrollbarThemeQt::thumbPosition(Scrollbar* scrollbar)
int ScrollbarThemeQt::thumbLength(Scrollbar* scrollbar)
{
QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
- IntRect thumb = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarSlider, 0);
+ IntRect thumb = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarSlider, 0);
return scrollbar->orientation() == HorizontalScrollbar ? thumb.width() : thumb.height();
}
int ScrollbarThemeQt::trackPosition(Scrollbar* scrollbar)
{
QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
- IntRect track = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
+ IntRect track = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
return scrollbar->orientation() == HorizontalScrollbar ? track.x() - scrollbar->x() : track.y() - scrollbar->y();
}
int ScrollbarThemeQt::trackLength(Scrollbar* scrollbar)
{
QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
- IntRect track = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
+ IntRect track = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
return scrollbar->orientation() == HorizontalScrollbar ? track.width() : track.height();
}
@@ -237,7 +236,7 @@ void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext
#if QT_VERSION < 0x040500
context->fillRect(rect, QApplication::palette().color(QPalette::Normal, QPalette::Window));
#else
- StylePainter p(context);
+ StylePainter p(this, context);
if (!p.isValid())
return;
@@ -247,5 +246,10 @@ void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext
#endif
}
+QStyle* ScrollbarThemeQt::style() const
+{
+ return QApplication::style();
+}
+
}
diff --git a/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.h b/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.h
index 6ca44ea..cf4882d 100644
--- a/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.h
+++ b/src/3rdparty/webkit/WebCore/platform/qt/ScrollbarThemeQt.h
@@ -28,6 +28,12 @@
#include "ScrollbarTheme.h"
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+class QStyle;
+QT_END_NAMESPACE
+
namespace WebCore {
class ScrollbarThemeQt : public ScrollbarTheme {
@@ -49,6 +55,8 @@ public:
virtual int trackLength(Scrollbar*);
virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
+
+ QStyle* style() const;
};
}
diff --git a/src/corelib/arch/sparc/arch.pri b/src/corelib/arch/sparc/arch.pri
index 3113dd3..9bb3a88 100644
--- a/src/corelib/arch/sparc/arch.pri
+++ b/src/corelib/arch/sparc/arch.pri
@@ -1,7 +1,7 @@
#
# SPARC architecture
#
-*-64 {
+*-64* {
SOURCES += $$QT_ARCH_CPP/qatomic64.s
}
else {
diff --git a/src/corelib/codecs/qsimplecodec.cpp b/src/corelib/codecs/qsimplecodec.cpp
index 445565a..4cc7912 100644
--- a/src/corelib/codecs/qsimplecodec.cpp
+++ b/src/corelib/codecs/qsimplecodec.cpp
@@ -681,7 +681,7 @@ QByteArray QSimpleTextCodec::convertFromUnicode(const QChar *in, int length, Con
int u;
const QChar* ucp = in;
unsigned char* rp = (unsigned char *)r.data();
- const unsigned char* rmp = (const unsigned char *)reverseMap->data();
+ const unsigned char* rmp = (const unsigned char *)reverseMap->constData();
int rmsize = (int) reverseMap->size();
while(i--)
{
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 86845c7..1c607a6 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -79,7 +79,7 @@
# endif
#endif // QT_NO_CODECS
#include "qlocale.h"
-#include "private/qmutexpool_p.h"
+#include "qmutex.h"
#include <stdlib.h>
#include <ctype.h>
@@ -659,13 +659,13 @@ static void setupLocaleMapper()
#endif
}
-
-static void setup()
-{
#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(&all));
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, textCodecsMutex, (QMutex::Recursive));
#endif
+// textCodecsMutex need to be locked to enter this function
+static void setup()
+{
if (all)
return;
@@ -903,8 +903,6 @@ QTextCodec::ConverterState::~ConverterState()
*/
/*!
- \nonreentrant
-
Constructs a QTextCodec, and gives it the highest precedence. The
QTextCodec should always be constructed on the heap (i.e. with \c
new). Qt takes ownership and will delete it when the application
@@ -912,6 +910,9 @@ QTextCodec::ConverterState::~ConverterState()
*/
QTextCodec::QTextCodec()
{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
setup();
all->prepend(this);
}
@@ -929,8 +930,12 @@ QTextCodec::~QTextCodec()
if (!destroying_is_ok)
qWarning("QTextCodec::~QTextCodec: Called by application");
#endif
- if (all)
+ if (all) {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
all->removeAll(this);
+ }
}
/*!
@@ -951,6 +956,9 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name)
if (name.isEmpty())
return 0;
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
setup();
for (int i = 0; i < all->size(); ++i) {
@@ -958,8 +966,8 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name)
if (nameMatch(cursor->name(), name))
return cursor;
QList<QByteArray> aliases = cursor->aliases();
- for (int i = 0; i < aliases.size(); ++i)
- if (nameMatch(aliases.at(i), name))
+ for (int y = 0; y < aliases.size(); ++y)
+ if (nameMatch(aliases.at(y), name))
return cursor;
}
@@ -973,6 +981,9 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name)
*/
QTextCodec* QTextCodec::codecForMib(int mib)
{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
setup();
// Qt 3 used 1000 (mib for UCS2) as its identifier for the utf16 codec. Map
@@ -1001,6 +1012,9 @@ QTextCodec* QTextCodec::codecForMib(int mib)
*/
QList<QByteArray> QTextCodec::availableCodecs()
{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
setup();
QList<QByteArray> codecs;
@@ -1008,6 +1022,11 @@ QList<QByteArray> QTextCodec::availableCodecs()
codecs += all->at(i)->name();
codecs += all->at(i)->aliases();
}
+
+#ifndef QT_NO_THREAD
+ locker.unlock();
+#endif
+
#ifndef QT_NO_TEXTCODECPLUGIN
QFactoryLoader *l = loader();
QStringList keys = l->keys();
@@ -1031,11 +1050,19 @@ QList<QByteArray> QTextCodec::availableCodecs()
*/
QList<int> QTextCodec::availableMibs()
{
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
setup();
QList<int> codecs;
for (int i = 0; i < all->size(); ++i)
codecs += all->at(i)->mibEnum();
+
+#ifndef QT_NO_THREAD
+ locker.unlock();
+#endif
+
#ifndef QT_NO_TEXTCODECPLUGIN
QFactoryLoader *l = loader();
QStringList keys = l->keys();
@@ -1082,6 +1109,9 @@ QTextCodec* QTextCodec::codecForLocale()
if (localeMapper)
return localeMapper;
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(textCodecsMutex());
+#endif
setup();
return localeMapper;
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 7f33791..9a15bf1 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -35,6 +35,4 @@ symbian: {
# Workaroud for problems with paging this dll
MMP_RULES -= PAGED
MMP_RULES *= UNPAGED
- # Timezone server
- LIBS += -ltzclient
}
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index f48c1b3..c8f836a 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1994,7 +1994,6 @@ void qt_check_pointer(const char *n, int l)
qWarning("In file %s, line %d: Out of memory", n, l);
}
-#ifndef QT_NO_EXCEPTIONS
/* \internal
Allows you to throw an exception without including <new>
Called internally from Q_CHECK_PTR on certain OS combinations
@@ -2003,7 +2002,6 @@ void qBadAlloc()
{
QT_THROW(std::bad_alloc());
}
-#endif
/*
The Q_ASSERT macro calls this function when the test fails.
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index b237659..99bbe42 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1676,10 +1676,7 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
#endif
Q_CORE_EXPORT void qt_check_pointer(const char *, int);
-
-#ifndef QT_NO_EXCEPTIONS
Q_CORE_EXPORT void qBadAlloc();
-#endif
#ifdef QT_NO_EXCEPTIONS
# if defined(QT_NO_DEBUG)
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 177bee4..35ff8e7 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1235,7 +1235,10 @@ public:
BusyCursor,
OpenHandCursor,
ClosedHandCursor,
- LastCursor = ClosedHandCursor,
+ DragCopyCursor,
+ DragMoveCursor,
+ DragLinkCursor,
+ LastCursor = DragLinkCursor,
BitmapCursor = 24,
CustomCursor = 25
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 6627c76..1f1c8f7 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -157,7 +157,7 @@
\value AA_MacDontSwapCtrlAndMeta On Mac OS X by default, Qt swaps the
Control and Meta (Command) keys (i.e., whenever Control is pressed, Qt
- sends Meta and whenever Meta is pressed Control is sent. When this
+ sends Meta, and whenever Meta is pressed Control is sent). When this
attribute is true, Qt will not do the flip. QKeySequence::StandardShortcuts
will also flip accordingly (i.e., QKeySequence::Copy will be
Command+C on the keyboard regardless of the value set, though what is output for
@@ -493,7 +493,7 @@
\omitvalue WordBreak
\omitvalue TextForceLeftToRight
\omitvalue TextForceRightToLeft
- \omitvalue TextLongestVariant Always use the longest variant when computing the size of a multi-variant string
+ \omitvalue TextLongestVariant Always use the longest variant when computing the size of a multi-variant string.
You can use as many modifier flags as you want, except that
Qt::TextSingleLine and Qt::TextWordWrap cannot be combined.
@@ -2115,7 +2115,7 @@
On some platforms this implies Qt::WindowSystemMenuHint for it to work.
\value MacWindowToolBarButtonHint On Mac OS X adds a tool bar button (i.e.,
- the oblong button that is on the top right of windows that have toolbars.
+ the oblong button that is on the top right of windows that have toolbars).
\value BypassGraphicsProxyWidget Prevents the window and its children from
automatically embedding themselves into a QGraphicsProxyWidget if the
@@ -2508,6 +2508,15 @@
operations that allow the user to interact with
the application while they are performed in the
background.
+ \value DragMoveCursor
+ A cursor that is usually used when dragging an item.
+ \value DragCopyCursor
+ A cursor that is usually used when dragging an item
+ to copy it.
+ \value DragLinkCursor
+ A cursor that is usually used when dragging an item
+ to make a link to it.
+
\value BitmapCursor
\omitvalue LastCursor
\omitvalue CustomCursor
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index a7dc8fa..4740a89 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -235,7 +235,7 @@ QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd)
QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine()
{
- foreach (int id, pathToID.values())
+ foreach (int id, pathToID)
inotify_rm_watch(inotifyFd, id < 0 ? -id : id);
::close(inotifyFd);
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index f088ded..8396481 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -109,7 +109,7 @@ QKqueueFileSystemWatcherEngine::~QKqueueFileSystemWatcherEngine()
close(kqpipe[0]);
close(kqpipe[1]);
- foreach (int id, pathToID.values())
+ foreach (int id, pathToID)
::close(id < 0 ? -id : id);
}
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index dbf422e..b0503be 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -1006,6 +1006,9 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
Returns the child of the model index that is stored in the given \a row and
\a column.
+ \note This function does not work for an invalid model index which is often
+ used as the root index.
+
\sa parent(), sibling()
*/
@@ -1245,7 +1248,7 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
/*!
\fn QModelIndex QAbstractItemModel::parent(const QModelIndex &index) const = 0
- Returns the parent of the model item with the given \a index. If the model
+ Returns the parent of the model item with the given \a index. If the item
has no parent, an invalid QModelIndex is returned.
A common convention used in models that expose tree data structures is that
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 9a361c0..c1027ed 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -75,7 +75,6 @@
#if defined(Q_OS_SYMBIAN)
#include <e32std.h>
-#include <tz.h>
#endif
QT_BEGIN_NAMESPACE
@@ -3722,32 +3721,23 @@ static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
#elif defined(Q_OS_SYMBIAN)
// months and days are zero index based
_LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = User::UTCOffset();
TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
TTime epochTTime;
TInt err = epochTTime.Set(KUnixEpoch);
tm res;
if(err == KErrNone) {
TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
- TRAP(err,
- RTz tz;
- User::LeaveIfError(tz.Connect());
- CleanupClosePushL(tz);
- res.tm_isdst = tz.IsDaylightSavingOnL(*tz.GetTimeZoneIdL(),utcTTime);
- User::LeaveIfError(tz.ConvertToLocalTime(utcTTime));
- CleanupStack::PopAndDestroy(&tz));
- if (KErrNone == err) {
- TDateTime localDateTime = utcTTime.DateTime();
- res.tm_sec = localDateTime.Second();
- res.tm_min = localDateTime.Minute();
- res.tm_hour = localDateTime.Hour();
- res.tm_mday = localDateTime.Day() + 1; // non-zero based index for tm struct
- res.tm_mon = localDateTime.Month();
- res.tm_year = localDateTime.Year() - 1900;
- // Symbian's timezone server doesn't know how to handle DST before year 1997
- if (res.tm_year < 97)
- res.tm_isdst = -1;
- brokenDown = &res;
- }
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = 0;
+ brokenDown = &res;
}
#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// use the reentrant version of localtime() where available
@@ -3822,27 +3812,23 @@ static void localToUtc(QDate &date, QTime &time, int isdst)
#elif defined(Q_OS_SYMBIAN)
// months and days are zero index based
_LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = TTimeIntervalSeconds(0 - User::UTCOffset().Int());
TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
TTime epochTTime;
TInt err = epochTTime.Set(KUnixEpoch);
tm res;
if(err == KErrNone) {
- TTime localTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
- RTz tz;
- if (KErrNone == tz.Connect()) {
- if (KErrNone == tz.ConvertToUniversalTime(localTTime)) {
- TDateTime utcDateTime = localTTime.DateTime();
- res.tm_sec = utcDateTime.Second();
- res.tm_min = utcDateTime.Minute();
- res.tm_hour = utcDateTime.Hour();
- res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
- res.tm_mon = utcDateTime.Month();
- res.tm_year = utcDateTime.Year() - 1900;
- res.tm_isdst = (int)isdst;
- brokenDown = &res;
- }
- tz.Close();
- }
+ TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = (int)isdst;
+ brokenDown = &res;
}
#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// use the reentrant version of gmtime() where available
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index d60087f..9850ee7 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -374,7 +374,7 @@ QDebug operator<<(QDebug dbg, const QPoint &p) {
QDebug operator<<(QDebug d, const QPointF &p)
{
d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')';
- return d;
+ return d.space();
}
#endif
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 5e3b0fd..702a21a 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -595,7 +595,7 @@ private:
struct Data {
QBasicAtomicInt ref;
int alloc, size;
- ushort *data;
+ ushort *data; // QT5: put that after the bit field to fill alignment gap; don't use sizeof any more then
ushort clean : 1;
ushort simpletext : 1;
ushort righttoleft : 1;
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index ddb5c7d..74661c2 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -71,7 +71,7 @@ public:
private:
const int m_size;
- const char *m_data;
+ const char * const m_data;
};
struct Q_CORE_EXPORT QAbstractConcatenable
diff --git a/src/declarative/3rdparty/3rdparty.pri b/src/declarative/3rdparty/3rdparty.pri
new file mode 100644
index 0000000..fbdcc11
--- /dev/null
+++ b/src/declarative/3rdparty/3rdparty.pri
@@ -0,0 +1,7 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qlistmodelinterface_p.h\
+
+SOURCES += \
+ $$PWD/qlistmodelinterface.cpp \
diff --git a/src/declarative/3rdparty/qlistmodelinterface.cpp b/src/declarative/3rdparty/qlistmodelinterface.cpp
new file mode 100644
index 0000000..cfd4cff
--- /dev/null
+++ b/src/declarative/3rdparty/qlistmodelinterface.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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 "qlistmodelinterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QListModelInterface
+ \brief The QListModelInterface class can be subclassed to provide C++ models to QmlGraphics Views
+
+ This class is comprised primarily of pure virtual functions which
+ you must implement in a subclass. You can then use the subclass
+ as a model for a QmlGraphics view, such as a QmlGraphicsListView.
+*/
+
+/*! \fn QListModelInterface::QListModelInterface(QObject *parent)
+ Constructs a QListModelInterface with the specified \a parent.
+*/
+
+ /*! \fn QListModelInterface::QListModelInterface(QObjectPrivate &dd, QObject *parent)
+
+ \internal
+ */
+
+/*! \fn QListModelInterface::~QListModelInterface()
+ The destructor is virtual.
+ */
+
+/*! \fn int QListModelInterface::count() const
+ Returns the number of data entries in the model.
+*/
+
+/*! \fn QHash<int,QVariant> QListModelInterface::data(int index, const QList<int>& roles) const
+ Returns the data at the given \a index for the specifed \a roles.
+*/
+
+/*! \fn bool QListModelInterface::setData(int index, const QHash<int,QVariant>& values)
+ Sets the data at the given \a index. \a values is a mapping of
+ QVariant values to roles. Returns false.
+*/
+
+/*! \fn QList<int> QListModelInterface::roles() const
+ Returns the list of roles for which the list model interface
+ provides data.
+*/
+
+/*! \fn QString QListModelInterface::toString(int role) const
+ Returns a string description of the specified \a role.
+*/
+
+/*! \fn void QListModelInterface::itemsInserted(int index, int count)
+ Emit this signal when \a count items are inserted at \a index.
+ */
+
+/*! \fn void QListModelInterface::itemsRemoved(int index, int count)
+ Emit this signal when \a count items are removed at \a index.
+ */
+
+/*! \fn void QListModelInterface::itemsMoved(int from, int to, int count)
+ Emit this signal when \a count items are moved from index \a from
+ to index \a to.
+ */
+
+/*! \fn void QListModelInterface::itemsChanged(int index, int count, const QList<int> &roles)
+ Emit this signal when \a count items at \a index have had their
+ \a roles changed.
+ */
+
+QT_END_NAMESPACE
diff --git a/src/declarative/3rdparty/qlistmodelinterface_p.h b/src/declarative/3rdparty/qlistmodelinterface_p.h
new file mode 100644
index 0000000..a958ead
--- /dev/null
+++ b/src/declarative/3rdparty/qlistmodelinterface_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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 QLISTMODELINTERFACE_H
+#define QLISTMODELINTERFACE_H
+
+#include <QtCore/QHash>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QListModelInterface : public QObject
+{
+ Q_OBJECT
+ public:
+ QListModelInterface(QObject *parent = 0) : QObject(parent) {}
+ virtual ~QListModelInterface() {}
+
+ virtual int count() const = 0;
+ virtual QHash<int,QVariant> data(int index, const QList<int>& roles = QList<int>()) const = 0;
+ virtual QVariant data(int index, int role) const = 0;
+ virtual bool setData(int index, const QHash<int,QVariant>& values)
+ { Q_UNUSED(index); Q_UNUSED(values); return false; }
+
+ virtual QList<int> roles() const = 0;
+ virtual QString toString(int role) const = 0;
+
+ Q_SIGNALS:
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count, const QList<int> &roles);
+
+ protected:
+ QListModelInterface(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent) {}
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif //QTREEMODELINTERFACE_H
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt
new file mode 100644
index 0000000..e54ec95
--- /dev/null
+++ b/src/declarative/QmlChanges.txt
@@ -0,0 +1,122 @@
+
+
+Listview: sectionExpression has been replaced by section.property, section.criteria
+
+
+=============================================================================
+The changes below are pre-4.6.0 release.
+
+QML API Review
+==============
+
+The QML API is being reviewed. This file documents the changes.
+Note that the changes are incremental, so a rename A->B for example may be followed
+by another subsequent rename B->C, if later reviews override earlier reviews.
+
+API Changes
+===========
+
+Renamed Elements:
+LineEdit -> TextInput
+VerticalLayout -> Column
+HorizontalLayout -> Row
+VerticalPositioner -> Column
+HorizontalPositioner -> Row
+GridLayout -> Grid
+GridPositioner -> Grid
+Rect -> Rectangle
+FocusRealm -> FocusScope
+FontFamily -> FontLoader
+Palette -> SystemPalette
+Bind -> Binding
+SetProperties -> PropertyChanges
+RunScript -> StateChangeScript
+SetAnchors -> AnchorChanges
+SetPropertyAction -> PropertyAction
+RunScriptAction -> ScriptAction
+ParentChangeAction -> ParentAction
+VisualModel -> VisualDataModel
+Follow -> SpringFollow
+
+Renamed properties:
+Item: contents -> childrenRect
+MouseRegion: xmin -> minimumX
+MouseRegion: xmax -> maximumX
+MouseRegion: ymin -> minimumY
+MouseRegion: ymin -> maximumY
+Text elements: hAlign -> horizontalAlignment
+Text elements: vAlign -> verticalAlignment
+Text elements: highlightColor -> selectionColor
+Text elements: highlightedTextColor -> selectedTextColor
+Text elements: preserveSelection -> persistentSelection
+State: operations -> changes
+Transition: operations -> animations
+Transition: fromState -> from
+Transition: toState -> to
+Follow: followValue -> value
+Flickable: xPosition -> viewportX
+Flickable: yPosition -> viewportY
+Flickable: xVelocity -> horizontalVelocity
+Flickable: yVelocity -> verticalVelocity
+Flickable: velocityDecay -> reportedVelocitySmoothing
+Flickable: locked -> interactive (note reversal of meaning)
+Flickable: pageXPosition -> visibleArea.xPosition
+Flickable: pageYPosition -> visibleArea.yPosition
+Flickable: pageWidth -> visibleArea.widthRatio
+Flickable: pageHeight -> visibleArea.heightRatio
+WebView: idealWidth -> preferredWidth
+WebView: idealHeight -> preferredHeight
+WebView: status -> statusText
+WebView: mouseX -> clickX (parameter to onDoubleClick)
+WebView: mouseY -> clickY (parameter to onDoubleClick)
+WebView: cacheSize -> pixelCacheSize
+Repeater: component -> delegate
+Repeater: dataSource -> model
+ListView: current -> currentItem
+GridView: current -> currentItem
+ListView: wrap -> keyNavigationWraps
+ListView: autoHighlight -> highlightFollowsCurrentItem
+GridView: wrap -> keyNavigationWraps
+GridView: autoHighlight -> highlightFollowsCurrentItem
+Animation: targets -> matchTargets
+Animation: properties -> matchProperties
+
+Additions:
+MouseRegion: add "acceptedButtons" property
+MouseRegion: add "hoverEnabled" property
+MouseRegion: add "pressedButtons" property
+Timer: add start() and stop() slots
+WebView: add newWindowComponent and newWindowParent properties
+Loader: add status() and progress() properties
+Loader: add sourceComponent property
+Loader: add resizeMode property
+ListView: preferredHighlightBegin, preferredHighlightEnd
+ListView: strictlyEnforceHighlightRange
+Particles: Added emissionRate, emissionVariance and burst()
+
+Deletions:
+Column/VerticalPositioner: lost "margins" property
+Row/HorizontalPositioner: lost "margins" property
+Grid/Positioner/Layout: lost "margins" property
+WebView: lost "interactive" property (always true now)
+Flickable: removed "dragMode" property
+ComponentInstance: removed. Replaced by Loader.sourceComponent
+ListView: removed currentItemMode. Replaced by highligh range.
+ListView: removed snapPos.
+Particles: removed streamIn. Replaced by emissionRate
+
+Other Changes:
+ids must be lowercase: Text { id: foo }, not Text { id: Foo }
+Drag: axis becomes an enum with values "XAxis", "YAxis", "XandYAxis"
+Image: scaleGrid property removed. New item called BorderImage instead.
+KeyActions: changed to a Keys attached property on any item.
+KeyProxy: changed to a Keys.forwardTo property on any item.
+Script: now an intrinsic type in the language
+ - cannot be assigned to properties
+ - good: Item { Script { ... } }
+ - bad: Item { resources: Script { ... } }
+Script: delay-loaded of the QML file until their source has been loaded (this only effects QML files loaded across the network.)
+Scope: declared properties shadow a property of the same name (was previously the reverse)
+ScriptAction and StateChangeScript: the script property now takes script rather than a string containing script (script: doSomething() rather than script: "doSomething()")
+QmlGraphicsItem::transformOrigin default changed from TopLeft to Center
+Animations used as PropertySourceValues are set to 'running: true' as default
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
new file mode 100644
index 0000000..261b2ff
--- /dev/null
+++ b/src/declarative/debugger/debugger.pri
@@ -0,0 +1,15 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qmldebuggerstatus.cpp \
+ $$PWD/qpacketprotocol.cpp \
+ $$PWD/qmldebugservice.cpp \
+ $$PWD/qmldebugclient.cpp \
+ $$PWD/qmldebug.cpp
+
+HEADERS += \
+ $$PWD/qmldebuggerstatus_p.h \
+ $$PWD/qpacketprotocol_p.h \
+ $$PWD/qmldebugservice_p.h \
+ $$PWD/qmldebugclient_p.h \
+ $$PWD/qmldebug_p.h
diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp
new file mode 100644
index 0000000..dc779ac
--- /dev/null
+++ b/src/declarative/debugger/qmldebug.cpp
@@ -0,0 +1,934 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebug_p.h"
+
+#include "qmldebugclient_p.h"
+
+#include <qmlenginedebug_p.h>
+
+#include <private/qobject_p.h>
+
+class QmlEngineDebugClient : public QmlDebugClient
+{
+public:
+ QmlEngineDebugClient(QmlDebugConnection *client, QmlEngineDebugPrivate *p);
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ QmlEngineDebugPrivate *priv;
+};
+
+class QmlEngineDebugPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEngineDebug)
+public:
+ QmlEngineDebugPrivate(QmlDebugConnection *);
+
+ void message(const QByteArray &);
+
+ QmlEngineDebugClient *client;
+ int nextId;
+ int getId();
+
+ void decode(QDataStream &, QmlDebugContextReference &);
+ void decode(QDataStream &, QmlDebugObjectReference &, bool simple);
+
+ static void remove(QmlEngineDebug *, QmlDebugEnginesQuery *);
+ static void remove(QmlEngineDebug *, QmlDebugRootContextQuery *);
+ static void remove(QmlEngineDebug *, QmlDebugObjectQuery *);
+ static void remove(QmlEngineDebug *, QmlDebugExpressionQuery *);
+
+ QHash<int, QmlDebugEnginesQuery *> enginesQuery;
+ QHash<int, QmlDebugRootContextQuery *> rootContextQuery;
+ QHash<int, QmlDebugObjectQuery *> objectQuery;
+ QHash<int, QmlDebugExpressionQuery *> expressionQuery;
+
+ QHash<int, QmlDebugWatch *> watched;
+};
+
+QmlEngineDebugClient::QmlEngineDebugClient(QmlDebugConnection *client,
+ QmlEngineDebugPrivate *p)
+: QmlDebugClient(QLatin1String("QmlEngine"), client), priv(p)
+{
+ setEnabled(true);
+}
+
+void QmlEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ priv->message(data);
+}
+
+QmlEngineDebugPrivate::QmlEngineDebugPrivate(QmlDebugConnection *c)
+: client(new QmlEngineDebugClient(c, this)), nextId(0)
+{
+}
+
+int QmlEngineDebugPrivate::getId()
+{
+ return nextId++;
+}
+
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugEnginesQuery *q)
+{
+ if (c && q) {
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->enginesQuery.remove(q->m_queryId);
+ }
+}
+
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c,
+ QmlDebugRootContextQuery *q)
+{
+ if (c && q) {
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->rootContextQuery.remove(q->m_queryId);
+ }
+}
+
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugObjectQuery *q)
+{
+ if (c && q) {
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->objectQuery.remove(q->m_queryId);
+ }
+}
+
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugExpressionQuery *q)
+{
+ if (c && q) {
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->expressionQuery.remove(q->m_queryId);
+ }
+}
+
+
+Q_DECLARE_METATYPE(QmlDebugObjectReference);
+void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o,
+ bool simple)
+{
+ QmlEngineDebugServer::QmlObjectData data;
+ ds >> data;
+ o.m_debugId = data.objectId;
+ o.m_class = data.objectType;
+ o.m_name = data.objectName;
+ o.m_source.m_url = data.url;
+ o.m_source.m_lineNumber = data.lineNumber;
+ o.m_source.m_columnNumber = data.columnNumber;
+ o.m_contextDebugId = data.contextId;
+
+ if (simple)
+ return;
+
+ int childCount;
+ bool recur;
+ ds >> childCount >> recur;
+
+ for (int ii = 0; ii < childCount; ++ii) {
+ o.m_children.append(QmlDebugObjectReference());
+ decode(ds, o.m_children.last(), !recur);
+ }
+
+ int propCount;
+ ds >> propCount;
+
+ for (int ii = 0; ii < propCount; ++ii) {
+ QmlEngineDebugServer::QmlObjectProperty data;
+ ds >> data;
+ QmlDebugPropertyReference prop;
+ prop.m_objectDebugId = o.m_debugId;
+ prop.m_name = data.name;
+ prop.m_binding = data.binding;
+ prop.m_hasNotifySignal = data.hasNotifySignal;
+ prop.m_valueTypeName = data.valueTypeName;
+ switch (data.type) {
+ case QmlEngineDebugServer::QmlObjectProperty::Basic:
+ case QmlEngineDebugServer::QmlObjectProperty::List:
+ case QmlEngineDebugServer::QmlObjectProperty::SignalProperty:
+ {
+ prop.m_value = data.value;
+ break;
+ }
+ case QmlEngineDebugServer::QmlObjectProperty::Object:
+ {
+ QmlDebugObjectReference obj;
+ obj.m_debugId = prop.m_value.toInt();
+ prop.m_value = qVariantFromValue(obj);
+ break;
+ }
+ case QmlEngineDebugServer::QmlObjectProperty::Unknown:
+ break;
+ }
+ o.m_properties << prop;
+ }
+}
+
+void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugContextReference &c)
+{
+ ds >> c.m_name >> c.m_debugId;
+
+ int contextCount;
+ ds >> contextCount;
+
+ for (int ii = 0; ii < contextCount; ++ii) {
+ c.m_contexts.append(QmlDebugContextReference());
+ decode(ds, c.m_contexts.last());
+ }
+
+ int objectCount;
+ ds >> objectCount;
+
+ for (int ii = 0; ii < objectCount; ++ii) {
+ QmlDebugObjectReference obj;
+ decode(ds, obj, true);
+
+ obj.m_contextDebugId = c.m_debugId;
+ c.m_objects << obj;
+ }
+}
+
+void QmlEngineDebugPrivate::message(const QByteArray &data)
+{
+ QDataStream ds(data);
+
+ QByteArray type;
+ ds >> type;
+
+ //qDebug() << "QmlEngineDebugPrivate::message()" << type;
+
+ if (type == "LIST_ENGINES_R") {
+ int queryId;
+ ds >> queryId;
+
+ QmlDebugEnginesQuery *query = enginesQuery.value(queryId);
+ if (!query)
+ return;
+ enginesQuery.remove(queryId);
+
+ int count;
+ ds >> count;
+
+ for (int ii = 0; ii < count; ++ii) {
+ QmlDebugEngineReference ref;
+ ds >> ref.m_name;
+ ds >> ref.m_debugId;
+ query->m_engines << ref;
+ }
+
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
+ } else if (type == "LIST_OBJECTS_R") {
+ int queryId;
+ ds >> queryId;
+
+ QmlDebugRootContextQuery *query = rootContextQuery.value(queryId);
+ if (!query)
+ return;
+ rootContextQuery.remove(queryId);
+
+ if (!ds.atEnd())
+ decode(ds, query->m_context);
+
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
+ } else if (type == "FETCH_OBJECT_R") {
+ int queryId;
+ ds >> queryId;
+
+ QmlDebugObjectQuery *query = objectQuery.value(queryId);
+ if (!query)
+ return;
+ objectQuery.remove(queryId);
+
+ if (!ds.atEnd())
+ decode(ds, query->m_object, false);
+
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
+ } else if (type == "EVAL_EXPRESSION_R") {
+ int queryId;
+ QVariant result;
+ ds >> queryId >> result;
+
+ QmlDebugExpressionQuery *query = expressionQuery.value(queryId);
+ if (!query)
+ return;
+ expressionQuery.remove(queryId);
+
+ query->m_result = result;
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
+ } else if (type == "WATCH_PROPERTY_R") {
+ int queryId;
+ bool ok;
+ ds >> queryId >> ok;
+
+ QmlDebugWatch *watch = watched.value(queryId);
+ if (!watch)
+ return;
+
+ watch->setState(ok ? QmlDebugWatch::Active : QmlDebugWatch::Inactive);
+ } else if (type == "WATCH_OBJECT_R") {
+ int queryId;
+ bool ok;
+ ds >> queryId >> ok;
+
+ QmlDebugWatch *watch = watched.value(queryId);
+ if (!watch)
+ return;
+
+ watch->setState(ok ? QmlDebugWatch::Active : QmlDebugWatch::Inactive);
+ } else if (type == "WATCH_EXPR_OBJECT_R") {
+ int queryId;
+ bool ok;
+ ds >> queryId >> ok;
+
+ QmlDebugWatch *watch = watched.value(queryId);
+ if (!watch)
+ return;
+
+ watch->setState(ok ? QmlDebugWatch::Active : QmlDebugWatch::Inactive);
+ } else if (type == "UPDATE_WATCH") {
+ int queryId;
+ int debugId;
+ QByteArray name;
+ QVariant value;
+ ds >> queryId >> debugId >> name >> value;
+
+ QmlDebugWatch *watch = watched.value(queryId, 0);
+ if (!watch)
+ return;
+ emit watch->valueChanged(name, value);
+ }
+}
+
+QmlEngineDebug::QmlEngineDebug(QmlDebugConnection *client, QObject *parent)
+: QObject(*(new QmlEngineDebugPrivate(client)), parent)
+{
+}
+
+QmlDebugPropertyWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference &property, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugPropertyWatch *watch = new QmlDebugPropertyWatch(parent);
+ if (d->client->isConnected()) {
+ int queryId = d->getId();
+ watch->m_queryId = queryId;
+ watch->m_client = this;
+ watch->m_objectDebugId = property.objectDebugId();
+ watch->m_name = property.name();
+ d->watched.insert(queryId, watch);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toUtf8();
+ d->client->sendMessage(message);
+ } else {
+ watch->m_state = QmlDebugWatch::Dead;
+ }
+
+ return watch;
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugContextReference &, const QString &, QObject *)
+{
+ qWarning("QmlEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+QmlDebugObjectExpressionWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &object, const QString &expr, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+ QmlDebugObjectExpressionWatch *watch = new QmlDebugObjectExpressionWatch(parent);
+ if (d->client->isConnected()) {
+ int queryId = d->getId();
+ watch->m_queryId = queryId;
+ watch->m_client = this;
+ watch->m_objectDebugId = object.debugId();
+ watch->m_expr = expr;
+ d->watched.insert(queryId, watch);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_EXPR_OBJECT") << queryId << object.debugId() << expr;
+ d->client->sendMessage(message);
+ } else {
+ watch->m_state = QmlDebugWatch::Dead;
+ }
+ return watch;
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugWatch *watch = new QmlDebugWatch(parent);
+ if (d->client->isConnected()) {
+ int queryId = d->getId();
+ watch->m_queryId = queryId;
+ watch->m_client = this;
+ watch->m_objectDebugId = object.debugId();
+ d->watched.insert(queryId, watch);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_OBJECT") << queryId << object.debugId();
+ d->client->sendMessage(message);
+ } else {
+ watch->m_state = QmlDebugWatch::Dead;
+ }
+
+ return watch;
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugFileReference &, QObject *)
+{
+ qWarning("QmlEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+void QmlEngineDebug::removeWatch(QmlDebugWatch *watch)
+{
+ Q_D(QmlEngineDebug);
+
+ if (!watch || !watch->m_client)
+ return;
+
+ watch->m_client = 0;
+ watch->setState(QmlDebugWatch::Inactive);
+
+ d->watched.remove(watch->queryId());
+
+ if (d->client && d->client->isConnected()) {
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("NO_WATCH") << watch->queryId();
+ d->client->sendMessage(message);
+ }
+}
+
+QmlDebugEnginesQuery *QmlEngineDebug::queryAvailableEngines(QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugEnginesQuery *query = new QmlDebugEnginesQuery(parent);
+ if (d->client->isConnected()) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->enginesQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_ENGINES") << queryId;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugRootContextQuery *QmlEngineDebug::queryRootContexts(const QmlDebugEngineReference &engine, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugRootContextQuery *query = new QmlDebugRootContextQuery(parent);
+ if (d->client->isConnected() && engine.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->rootContextQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_OBJECTS") << queryId << engine.debugId();
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugObjectQuery *QmlEngineDebug::queryObject(const QmlDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugObjectQuery *query = new QmlDebugObjectQuery(parent);
+ if (d->client->isConnected() && object.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->objectQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ << false;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugObjectQuery *QmlEngineDebug::queryObjectRecursive(const QmlDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugObjectQuery *query = new QmlDebugObjectQuery(parent);
+ if (d->client->isConnected() && object.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->objectQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ << true;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugExpressionQuery *QmlEngineDebug::queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugExpressionQuery *query = new QmlDebugExpressionQuery(parent);
+ if (d->client->isConnected() && objectDebugId != -1) {
+ query->m_client = this;
+ query->m_expr = expr;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->expressionQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("EVAL_EXPRESSION") << queryId << objectDebugId << expr;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugWatch::QmlDebugWatch(QObject *parent)
+: QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1)
+{
+}
+
+QmlDebugWatch::~QmlDebugWatch()
+{
+}
+
+int QmlDebugWatch::queryId() const
+{
+ return m_queryId;
+}
+
+int QmlDebugWatch::objectDebugId() const
+{
+ return m_objectDebugId;
+}
+
+QmlDebugWatch::State QmlDebugWatch::state() const
+{
+ return m_state;
+}
+
+void QmlDebugWatch::setState(State s)
+{
+ if (m_state == s)
+ return;
+ m_state = s;
+ emit stateChanged(m_state);
+}
+
+QmlDebugPropertyWatch::QmlDebugPropertyWatch(QObject *parent)
+ : QmlDebugWatch(parent)
+{
+}
+
+QString QmlDebugPropertyWatch::name() const
+{
+ return m_name;
+}
+
+
+QmlDebugObjectExpressionWatch::QmlDebugObjectExpressionWatch(QObject *parent)
+ : QmlDebugWatch(parent)
+{
+}
+
+QString QmlDebugObjectExpressionWatch::expression() const
+{
+ return m_expr;
+}
+
+
+QmlDebugQuery::QmlDebugQuery(QObject *parent)
+: QObject(parent), m_state(Waiting)
+{
+}
+
+QmlDebugQuery::State QmlDebugQuery::state() const
+{
+ return m_state;
+}
+
+bool QmlDebugQuery::isWaiting() const
+{
+ return m_state == Waiting;
+}
+
+void QmlDebugQuery::setState(State s)
+{
+ if (m_state == s)
+ return;
+ m_state = s;
+ emit stateChanged(m_state);
+}
+
+QmlDebugEnginesQuery::QmlDebugEnginesQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugEnginesQuery::~QmlDebugEnginesQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QList<QmlDebugEngineReference> QmlDebugEnginesQuery::engines() const
+{
+ return m_engines;
+}
+
+QmlDebugRootContextQuery::QmlDebugRootContextQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugRootContextQuery::~QmlDebugRootContextQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QmlDebugContextReference QmlDebugRootContextQuery::rootContext() const
+{
+ return m_context;
+}
+
+QmlDebugObjectQuery::QmlDebugObjectQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugObjectQuery::~QmlDebugObjectQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QmlDebugObjectReference QmlDebugObjectQuery::object() const
+{
+ return m_object;
+}
+
+QmlDebugExpressionQuery::QmlDebugExpressionQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugExpressionQuery::~QmlDebugExpressionQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QString QmlDebugExpressionQuery::expression() const
+{
+ return m_expr;
+}
+
+QVariant QmlDebugExpressionQuery::result() const
+{
+ return m_result;
+}
+
+QmlDebugEngineReference::QmlDebugEngineReference()
+: m_debugId(-1)
+{
+}
+
+QmlDebugEngineReference::QmlDebugEngineReference(int debugId)
+: m_debugId(debugId)
+{
+}
+
+QmlDebugEngineReference::QmlDebugEngineReference(const QmlDebugEngineReference &o)
+: m_debugId(o.m_debugId), m_name(o.m_name)
+{
+}
+
+QmlDebugEngineReference &
+QmlDebugEngineReference::operator=(const QmlDebugEngineReference &o)
+{
+ m_debugId = o.m_debugId; m_name = o.m_name;
+ return *this;
+}
+
+int QmlDebugEngineReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QmlDebugEngineReference::name() const
+{
+ return m_name;
+}
+
+QmlDebugObjectReference::QmlDebugObjectReference()
+: m_debugId(-1), m_contextDebugId(-1)
+{
+}
+
+QmlDebugObjectReference::QmlDebugObjectReference(int debugId)
+: m_debugId(debugId), m_contextDebugId(-1)
+{
+}
+
+QmlDebugObjectReference::QmlDebugObjectReference(const QmlDebugObjectReference &o)
+: m_debugId(o.m_debugId), m_class(o.m_class), m_name(o.m_name),
+ m_source(o.m_source), m_contextDebugId(o.m_contextDebugId),
+ m_properties(o.m_properties), m_children(o.m_children)
+{
+}
+
+QmlDebugObjectReference &
+QmlDebugObjectReference::operator=(const QmlDebugObjectReference &o)
+{
+ m_debugId = o.m_debugId; m_class = o.m_class; m_name = o.m_name;
+ m_source = o.m_source; m_contextDebugId = o.m_contextDebugId;
+ m_properties = o.m_properties; m_children = o.m_children;
+ return *this;
+}
+
+int QmlDebugObjectReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QmlDebugObjectReference::className() const
+{
+ return m_class;
+}
+
+QString QmlDebugObjectReference::name() const
+{
+ return m_name;
+}
+
+QmlDebugFileReference QmlDebugObjectReference::source() const
+{
+ return m_source;
+}
+
+int QmlDebugObjectReference::contextDebugId() const
+{
+ return m_contextDebugId;
+}
+
+QList<QmlDebugPropertyReference> QmlDebugObjectReference::properties() const
+{
+ return m_properties;
+}
+
+QList<QmlDebugObjectReference> QmlDebugObjectReference::children() const
+{
+ return m_children;
+}
+
+QmlDebugContextReference::QmlDebugContextReference()
+: m_debugId(-1)
+{
+}
+
+QmlDebugContextReference::QmlDebugContextReference(const QmlDebugContextReference &o)
+: m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts)
+{
+}
+
+QmlDebugContextReference &QmlDebugContextReference::operator=(const QmlDebugContextReference &o)
+{
+ m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects;
+ m_contexts = o.m_contexts;
+ return *this;
+}
+
+int QmlDebugContextReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QmlDebugContextReference::name() const
+{
+ return m_name;
+}
+
+QList<QmlDebugObjectReference> QmlDebugContextReference::objects() const
+{
+ return m_objects;
+}
+
+QList<QmlDebugContextReference> QmlDebugContextReference::contexts() const
+{
+ return m_contexts;
+}
+
+QmlDebugFileReference::QmlDebugFileReference()
+: m_lineNumber(-1), m_columnNumber(-1)
+{
+}
+
+QmlDebugFileReference::QmlDebugFileReference(const QmlDebugFileReference &o)
+: m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber)
+{
+}
+
+QmlDebugFileReference &QmlDebugFileReference::operator=(const QmlDebugFileReference &o)
+{
+ m_url = o.m_url; m_lineNumber = o.m_lineNumber; m_columnNumber = o.m_columnNumber;
+ return *this;
+}
+
+QUrl QmlDebugFileReference::url() const
+{
+ return m_url;
+}
+
+void QmlDebugFileReference::setUrl(const QUrl &u)
+{
+ m_url = u;
+}
+
+int QmlDebugFileReference::lineNumber() const
+{
+ return m_lineNumber;
+}
+
+void QmlDebugFileReference::setLineNumber(int l)
+{
+ m_lineNumber = l;
+}
+
+int QmlDebugFileReference::columnNumber() const
+{
+ return m_columnNumber;
+}
+
+void QmlDebugFileReference::setColumnNumber(int c)
+{
+ m_columnNumber = c;
+}
+
+QmlDebugPropertyReference::QmlDebugPropertyReference()
+: m_objectDebugId(-1), m_hasNotifySignal(false)
+{
+}
+
+QmlDebugPropertyReference::QmlDebugPropertyReference(const QmlDebugPropertyReference &o)
+: m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value),
+ m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding),
+ m_hasNotifySignal(o.m_hasNotifySignal)
+{
+}
+
+QmlDebugPropertyReference &QmlDebugPropertyReference::operator=(const QmlDebugPropertyReference &o)
+{
+ m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value;
+ m_valueTypeName = o.m_valueTypeName; m_binding = o.m_binding;
+ m_hasNotifySignal = o.m_hasNotifySignal;
+ return *this;
+}
+
+int QmlDebugPropertyReference::objectDebugId() const
+{
+ return m_objectDebugId;
+}
+
+QString QmlDebugPropertyReference::name() const
+{
+ return m_name;
+}
+
+QString QmlDebugPropertyReference::valueTypeName() const
+{
+ return m_valueTypeName;
+}
+
+QVariant QmlDebugPropertyReference::value() const
+{
+ return m_value;
+}
+
+QString QmlDebugPropertyReference::binding() const
+{
+ return m_binding;
+}
+
+bool QmlDebugPropertyReference::hasNotifySignal() const
+{
+ return m_hasNotifySignal;
+}
diff --git a/src/declarative/debugger/qmldebug_p.h b/src/declarative/debugger/qmldebug_p.h
new file mode 100644
index 0000000..cd2adf6
--- /dev/null
+++ b/src/declarative/debugger/qmldebug_p.h
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QMLDEBUG_H
+#define QMLDEBUG_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlDebugConnection;
+class QmlDebugWatch;
+class QmlDebugPropertyWatch;
+class QmlDebugObjectExpressionWatch;
+class QmlDebugEnginesQuery;
+class QmlDebugRootContextQuery;
+class QmlDebugObjectQuery;
+class QmlDebugExpressionQuery;
+class QmlDebugPropertyReference;
+class QmlDebugContextReference;
+class QmlDebugObjectReference;
+class QmlDebugFileReference;
+class QmlDebugEngineReference;
+class QmlEngineDebugPrivate;
+class Q_DECLARATIVE_EXPORT QmlEngineDebug : public QObject
+{
+Q_OBJECT
+public:
+ QmlEngineDebug(QmlDebugConnection *, QObject * = 0);
+
+ QmlDebugPropertyWatch *addWatch(const QmlDebugPropertyReference &,
+ QObject *parent = 0);
+ QmlDebugWatch *addWatch(const QmlDebugContextReference &, const QString &,
+ QObject *parent = 0);
+ QmlDebugObjectExpressionWatch *addWatch(const QmlDebugObjectReference &, const QString &,
+ QObject *parent = 0);
+ QmlDebugWatch *addWatch(const QmlDebugObjectReference &,
+ QObject *parent = 0);
+ QmlDebugWatch *addWatch(const QmlDebugFileReference &,
+ QObject *parent = 0);
+
+ void removeWatch(QmlDebugWatch *watch);
+
+ QmlDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0);
+ QmlDebugRootContextQuery *queryRootContexts(const QmlDebugEngineReference &,
+ QObject *parent = 0);
+ QmlDebugObjectQuery *queryObject(const QmlDebugObjectReference &,
+ QObject *parent = 0);
+ QmlDebugObjectQuery *queryObjectRecursive(const QmlDebugObjectReference &,
+ QObject *parent = 0);
+ QmlDebugExpressionQuery *queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QmlEngineDebug)
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugWatch : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Waiting, Active, Inactive, Dead };
+
+ QmlDebugWatch(QObject *);
+ ~QmlDebugWatch();
+
+ int queryId() const;
+ int objectDebugId() const;
+ State state() const;
+
+Q_SIGNALS:
+ void stateChanged(QmlDebugWatch::State);
+ //void objectChanged(int, const QmlDebugObjectReference &);
+ //void valueChanged(int, const QVariant &);
+
+ // Server sends value as string if it is a user-type variant
+ void valueChanged(const QByteArray &name, const QVariant &value);
+
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ void setState(State);
+ State m_state;
+ int m_queryId;
+ QmlEngineDebug *m_client;
+ int m_objectDebugId;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugPropertyWatch : public QmlDebugWatch
+{
+ Q_OBJECT
+public:
+ QmlDebugPropertyWatch(QObject *parent);
+
+ QString name() const;
+
+private:
+ friend class QmlEngineDebug;
+ QString m_name;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugObjectExpressionWatch : public QmlDebugWatch
+{
+ Q_OBJECT
+public:
+ QmlDebugObjectExpressionWatch(QObject *parent);
+
+ QString expression() const;
+
+private:
+ friend class QmlEngineDebug;
+ QString m_expr;
+ int m_debugId;
+};
+
+
+class Q_DECLARATIVE_EXPORT QmlDebugQuery : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Waiting, Error, Completed };
+
+ State state() const;
+ bool isWaiting() const;
+
+// bool waitUntilCompleted();
+
+Q_SIGNALS:
+ void stateChanged(QmlDebugQuery::State);
+
+protected:
+ QmlDebugQuery(QObject *);
+
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ void setState(State);
+ State m_state;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugFileReference
+{
+public:
+ QmlDebugFileReference();
+ QmlDebugFileReference(const QmlDebugFileReference &);
+ QmlDebugFileReference &operator=(const QmlDebugFileReference &);
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ int lineNumber() const;
+ void setLineNumber(int);
+ int columnNumber() const;
+ void setColumnNumber(int);
+
+private:
+ friend class QmlEngineDebugPrivate;
+ QUrl m_url;
+ int m_lineNumber;
+ int m_columnNumber;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugEngineReference
+{
+public:
+ QmlDebugEngineReference();
+ QmlDebugEngineReference(int);
+ QmlDebugEngineReference(const QmlDebugEngineReference &);
+ QmlDebugEngineReference &operator=(const QmlDebugEngineReference &);
+
+ int debugId() const;
+ QString name() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ int m_debugId;
+ QString m_name;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugObjectReference
+{
+public:
+ QmlDebugObjectReference();
+ QmlDebugObjectReference(int);
+ QmlDebugObjectReference(const QmlDebugObjectReference &);
+ QmlDebugObjectReference &operator=(const QmlDebugObjectReference &);
+
+ int debugId() const;
+ QString className() const;
+ QString name() const;
+
+ QmlDebugFileReference source() const;
+ int contextDebugId() const;
+
+ QList<QmlDebugPropertyReference> properties() const;
+ QList<QmlDebugObjectReference> children() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ int m_debugId;
+ QString m_class;
+ QString m_name;
+ QmlDebugFileReference m_source;
+ int m_contextDebugId;
+ QList<QmlDebugPropertyReference> m_properties;
+ QList<QmlDebugObjectReference> m_children;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugContextReference
+{
+public:
+ QmlDebugContextReference();
+ QmlDebugContextReference(const QmlDebugContextReference &);
+ QmlDebugContextReference &operator=(const QmlDebugContextReference &);
+
+ int debugId() const;
+ QString name() const;
+
+ QList<QmlDebugObjectReference> objects() const;
+ QList<QmlDebugContextReference> contexts() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ int m_debugId;
+ QString m_name;
+ QList<QmlDebugObjectReference> m_objects;
+ QList<QmlDebugContextReference> m_contexts;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugPropertyReference
+{
+public:
+ QmlDebugPropertyReference();
+ QmlDebugPropertyReference(const QmlDebugPropertyReference &);
+ QmlDebugPropertyReference &operator=(const QmlDebugPropertyReference &);
+
+ int objectDebugId() const;
+ QString name() const;
+ QVariant value() const;
+ QString valueTypeName() const;
+ QString binding() const;
+ bool hasNotifySignal() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ int m_objectDebugId;
+ QString m_name;
+ QVariant m_value;
+ QString m_valueTypeName;
+ QString m_binding;
+ bool m_hasNotifySignal;
+};
+
+
+class Q_DECLARATIVE_EXPORT QmlDebugEnginesQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugEnginesQuery();
+ QList<QmlDebugEngineReference> engines() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugEnginesQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QList<QmlDebugEngineReference> m_engines;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugRootContextQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugRootContextQuery();
+ QmlDebugContextReference rootContext() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugRootContextQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QmlDebugContextReference m_context;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugObjectQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugObjectQuery();
+ QmlDebugObjectReference object() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugObjectQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QmlDebugObjectReference m_object;
+
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugExpressionQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugExpressionQuery();
+ QString expression() const;
+ QVariant result() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugExpressionQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QString m_expr;
+ QVariant m_result;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDEBUG_H
diff --git a/src/declarative/debugger/qmldebugclient.cpp b/src/declarative/debugger/qmldebugclient.cpp
new file mode 100644
index 0000000..68e14c2
--- /dev/null
+++ b/src/declarative/debugger/qmldebugclient.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebugclient_p.h"
+
+#include "qpacketprotocol_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlDebugConnectionPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QmlDebugConnectionPrivate(QmlDebugConnection *c);
+ QmlDebugConnection *q;
+ QPacketProtocol *protocol;
+
+ QStringList enabled;
+ QHash<QString, QmlDebugClient *> plugins;
+public Q_SLOTS:
+ void connected();
+ void readyRead();
+};
+
+QmlDebugConnectionPrivate::QmlDebugConnectionPrivate(QmlDebugConnection *c)
+: QObject(c), q(c), protocol(0)
+{
+ protocol = new QPacketProtocol(q, this);
+ QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
+ QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void QmlDebugConnectionPrivate::connected()
+{
+ QPacket pack;
+ pack << QString(QLatin1String("QmlDebugServer")) << enabled;
+ protocol->send(pack);
+}
+
+void QmlDebugConnectionPrivate::readyRead()
+{
+ QPacket pack = protocol->read();
+ QString name; QByteArray message;
+ pack >> name >> message;
+
+ QHash<QString, QmlDebugClient *>::Iterator iter =
+ plugins.find(name);
+ if (iter == plugins.end()) {
+ qWarning() << "QmlDebugConnection: Message received for missing plugin" << name;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+}
+
+QmlDebugConnection::QmlDebugConnection(QObject *parent)
+: QTcpSocket(parent), d(new QmlDebugConnectionPrivate(this))
+{
+}
+
+bool QmlDebugConnection::isConnected() const
+{
+ return state() == ConnectedState;
+}
+
+class QmlDebugClientPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDebugClient)
+public:
+ QmlDebugClientPrivate();
+
+ QString name;
+ QmlDebugConnection *client;
+ bool enabled;
+};
+
+QmlDebugClientPrivate::QmlDebugClientPrivate()
+: client(0), enabled(false)
+{
+}
+
+QmlDebugClient::QmlDebugClient(const QString &name,
+ QmlDebugConnection *parent)
+: QObject(*(new QmlDebugClientPrivate), parent)
+{
+ Q_D(QmlDebugClient);
+ d->name = name;
+ d->client = parent;
+
+ if (!d->client)
+ return;
+
+ if (d->client->d->plugins.contains(name)) {
+ qWarning() << "QmlDebugClient: Conflicting plugin name" << name;
+ d->client = 0;
+ } else {
+ d->client->d->plugins.insert(name, this);
+ }
+}
+
+QString QmlDebugClient::name() const
+{
+ Q_D(const QmlDebugClient);
+ return d->name;
+}
+
+bool QmlDebugClient::isEnabled() const
+{
+ Q_D(const QmlDebugClient);
+ return d->enabled;
+}
+
+void QmlDebugClient::setEnabled(bool e)
+{
+ Q_D(QmlDebugClient);
+ if (e == d->enabled)
+ return;
+
+ d->enabled = e;
+
+ if (d->client) {
+ if (e)
+ d->client->d->enabled.append(d->name);
+ else
+ d->client->d->enabled.removeAll(d->name);
+
+ if (d->client->state() == QTcpSocket::ConnectedState) {
+ QPacket pack;
+ pack << QString(QLatin1String("QmlDebugServer"));
+ if (e) pack << (int)1;
+ else pack << (int)2;
+ pack << d->name;
+ d->client->d->protocol->send(pack);
+ }
+ }
+}
+
+bool QmlDebugClient::isConnected() const
+{
+ Q_D(const QmlDebugClient);
+
+ if (!d->client)
+ return false;
+ return d->client->isConnected();
+}
+
+void QmlDebugClient::sendMessage(const QByteArray &message)
+{
+ Q_D(QmlDebugClient);
+
+ if (!d->client || !d->client->isConnected())
+ return;
+
+ QPacket pack;
+ pack << d->name << message;
+ d->client->d->protocol->send(pack);
+}
+
+void QmlDebugClient::messageReceived(const QByteArray &)
+{
+}
+
+QT_END_NAMESPACE
+
+#include <qmldebugclient.moc>
diff --git a/src/declarative/debugger/qmldebugclient_p.h b/src/declarative/debugger/qmldebugclient_p.h
new file mode 100644
index 0000000..d64541b
--- /dev/null
+++ b/src/declarative/debugger/qmldebugclient_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGCLIENT_H
+#define QMLDEBUGCLIENT_H
+
+#include <QtNetwork/qtcpsocket.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlDebugConnectionPrivate;
+class Q_DECLARATIVE_EXPORT QmlDebugConnection : public QTcpSocket
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QmlDebugConnection)
+public:
+ QmlDebugConnection(QObject * = 0);
+
+ bool isConnected() const;
+private:
+ QmlDebugConnectionPrivate *d;
+ friend class QmlDebugClient;
+ friend class QmlDebugClientPrivate;
+};
+
+class QmlDebugClientPrivate;
+class Q_DECLARATIVE_EXPORT QmlDebugClient : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlDebugClient)
+ Q_DISABLE_COPY(QmlDebugClient)
+
+public:
+ QmlDebugClient(const QString &, QmlDebugConnection *parent);
+
+ QString name() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ bool isConnected() const;
+
+ void sendMessage(const QByteArray &);
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ friend class QmlDebugConnection;
+ friend class QmlDebugConnectionPrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDEBUGCLIENT_H
diff --git a/src/declarative/debugger/qmldebuggerstatus.cpp b/src/declarative/debugger/qmldebuggerstatus.cpp
new file mode 100644
index 0000000..dc1cfb0
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebuggerstatus_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlDebuggerStatus::~QmlDebuggerStatus()
+{
+}
+
+void QmlDebuggerStatus::setSelectedState(bool)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebuggerstatus_p.h b/src/declarative/debugger/qmldebuggerstatus_p.h
new file mode 100644
index 0000000..7c8070b
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGGERSTATUS_P_H
+#define QMLDEBUGGERSTATUS_P_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlDebuggerStatus
+{
+public:
+ virtual ~QmlDebuggerStatus();
+
+ virtual void setSelectedState(bool);
+};
+Q_DECLARE_INTERFACE(QmlDebuggerStatus, "com.trolltech.qml.QmlDebuggerStatus")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLMDEBUGGERSTATUS_P_H
diff --git a/src/declarative/debugger/qmldebugservice.cpp b/src/declarative/debugger/qmldebugservice.cpp
new file mode 100644
index 0000000..810fbed
--- /dev/null
+++ b/src/declarative/debugger/qmldebugservice.cpp
@@ -0,0 +1,393 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebugservice_p.h"
+
+#include "qpacketprotocol_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtNetwork/qtcpserver.h>
+#include <QtNetwork/qtcpsocket.h>
+#include <QtCore/qstringlist.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlDebugServerPrivate;
+class QmlDebugServer : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlDebugServer)
+ Q_DISABLE_COPY(QmlDebugServer)
+public:
+ static QmlDebugServer *instance();
+ void wait();
+
+private Q_SLOTS:
+ void readyRead();
+
+private:
+ friend class QmlDebugService;
+ friend class QmlDebugServicePrivate;
+ QmlDebugServer(int);
+};
+
+class QmlDebugServerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDebugServer)
+public:
+ QmlDebugServerPrivate();
+ void wait();
+
+ int port;
+ QTcpSocket *connection;
+ QPacketProtocol *protocol;
+ QHash<QString, QmlDebugService *> plugins;
+ QStringList enabledPlugins;
+};
+
+class QmlDebugServicePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDebugService)
+public:
+ QmlDebugServicePrivate();
+
+ QString name;
+ QmlDebugServer *server;
+};
+
+QmlDebugServerPrivate::QmlDebugServerPrivate()
+: connection(0), protocol(0)
+{
+}
+
+void QmlDebugServerPrivate::wait()
+{
+ Q_Q(QmlDebugServer);
+ QTcpServer server;
+
+ if (!server.listen(QHostAddress::Any, port)) {
+ qWarning("QmlDebugServer: Unable to listen on port %d", port);
+ return;
+ }
+
+ qWarning("QmlDebugServer: Waiting for connection on port %d...", port);
+
+ if (!server.waitForNewConnection(-1)) {
+ qWarning("QmlDebugServer: Connection error");
+ return;
+ }
+
+ connection = server.nextPendingConnection();
+ connection->setParent(q);
+ protocol = new QPacketProtocol(connection, q);
+
+ // ### Wait for hello
+ while (!protocol->packetsAvailable()) {
+ connection->waitForReadyRead();
+ }
+ QPacket hello = protocol->read();
+ QString name;
+ hello >> name >> enabledPlugins;
+ if (name != QLatin1String("QmlDebugServer")) {
+ qWarning("QmlDebugServer: Invalid hello message");
+ delete protocol; delete connection; connection = 0; protocol = 0;
+ return;
+ }
+
+ QObject::connect(protocol, SIGNAL(readyRead()), q, SLOT(readyRead()));
+ q->readyRead();
+
+ qWarning("QmlDebugServer: Connection established");
+}
+
+QmlDebugServer *QmlDebugServer::instance()
+{
+ static bool envTested = false;
+ static QmlDebugServer *server = 0;
+
+ if (!envTested) {
+ envTested = true;
+ QByteArray env = qgetenv("QML_DEBUG_SERVER_PORT");
+
+ bool ok = false;
+ int port = env.toInt(&ok);
+
+ if (ok && port > 1024)
+ server = new QmlDebugServer(port);
+ }
+
+ return server;
+}
+
+void QmlDebugServer::wait()
+{
+ Q_D(QmlDebugServer);
+ d->wait();
+}
+
+QmlDebugServer::QmlDebugServer(int port)
+: QObject(*(new QmlDebugServerPrivate))
+{
+ Q_D(QmlDebugServer);
+ d->port = port;
+}
+
+void QmlDebugServer::readyRead()
+{
+ Q_D(QmlDebugServer);
+
+ QString debugServer(QLatin1String("QmlDebugServer"));
+
+ while (d->protocol->packetsAvailable()) {
+ QPacket pack = d->protocol->read();
+
+ QString name;
+ pack >> name;
+
+ if (name == debugServer) {
+ int op = -1; QString plugin;
+ pack >> op >> plugin;
+
+ if (op == 1) {
+ // Enable
+ if (!d->enabledPlugins.contains(plugin)) {
+ d->enabledPlugins.append(plugin);
+ QHash<QString, QmlDebugService *>::Iterator iter =
+ d->plugins.find(plugin);
+ if (iter != d->plugins.end())
+ (*iter)->enabledChanged(true);
+ }
+
+ } else if (op == 2) {
+ // Disable
+ if (d->enabledPlugins.contains(plugin)) {
+ d->enabledPlugins.removeAll(plugin);
+ QHash<QString, QmlDebugService *>::Iterator iter =
+ d->plugins.find(plugin);
+ if (iter != d->plugins.end())
+ (*iter)->enabledChanged(false);
+ }
+ } else {
+ qWarning("QmlDebugServer: Invalid control message %d", op);
+ }
+
+ } else {
+ QByteArray message;
+ pack >> message;
+
+ QHash<QString, QmlDebugService *>::Iterator iter =
+ d->plugins.find(name);
+ if (iter == d->plugins.end()) {
+ qWarning() << "QmlDebugServer: Message received for missing plugin" << name;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+ }
+ }
+}
+
+QmlDebugServicePrivate::QmlDebugServicePrivate()
+: server(0)
+{
+}
+
+QmlDebugService::QmlDebugService(const QString &name, QObject *parent)
+: QObject(*(new QmlDebugServicePrivate), parent)
+{
+ Q_D(QmlDebugService);
+ d->name = name;
+ d->server = QmlDebugServer::instance();
+
+ if (!d->server)
+ return;
+
+ if (d->server->d_func()->plugins.contains(name)) {
+ qWarning() << "QmlDebugService: Conflicting plugin name" << name;
+ d->server = 0;
+ } else {
+ d->server->d_func()->plugins.insert(name, this);
+ }
+}
+
+QString QmlDebugService::name() const
+{
+ Q_D(const QmlDebugService);
+ return d->name;
+}
+
+bool QmlDebugService::isEnabled() const
+{
+ Q_D(const QmlDebugService);
+ return (d->server && d->server->d_func()->enabledPlugins.contains(d->name));
+}
+
+namespace {
+
+ struct ObjectReference
+ {
+ QPointer<QObject> object;
+ int id;
+ };
+
+ struct ObjectReferenceHash
+ {
+ ObjectReferenceHash() : nextId(0) {}
+
+ QHash<QObject *, ObjectReference> objects;
+ QHash<int, QObject *> ids;
+
+ int nextId;
+ };
+
+}
+Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash);
+
+
+/*!
+ Returns a unique id for \a object. Calling this method multiple times
+ for the same object will return the same id.
+*/
+int QmlDebugService::idForObject(QObject *object)
+{
+ if (!object)
+ return -1;
+
+ ObjectReferenceHash *hash = objectReferenceHash();
+ QHash<QObject *, ObjectReference>::Iterator iter =
+ hash->objects.find(object);
+
+ if (iter == hash->objects.end()) {
+ int id = hash->nextId++;
+
+ hash->ids.insert(id, object);
+ iter = hash->objects.insert(object, ObjectReference());
+ iter->object = object;
+ iter->id = id;
+ } else if (iter->object != object) {
+ int id = hash->nextId++;
+
+ hash->ids.remove(iter->id);
+
+ hash->ids.insert(id, object);
+ iter->object = object;
+ iter->id = id;
+ }
+ return iter->id;
+}
+
+/*!
+ Returns the object for unique \a id. If the object has not previously been
+ assigned an id, through idForObject(), then 0 is returned. If the object
+ has been destroyed, 0 is returned.
+*/
+QObject *QmlDebugService::objectForId(int id)
+{
+ ObjectReferenceHash *hash = objectReferenceHash();
+
+ QHash<int, QObject *>::Iterator iter = hash->ids.find(id);
+ if (iter == hash->ids.end())
+ return 0;
+
+
+ QHash<QObject *, ObjectReference>::Iterator objIter =
+ hash->objects.find(*iter);
+ Q_ASSERT(objIter != hash->objects.end());
+
+ if (objIter->object == 0) {
+ hash->ids.erase(iter);
+ hash->objects.erase(objIter);
+ return 0;
+ } else {
+ return *iter;
+ }
+}
+
+bool QmlDebugService::isDebuggingEnabled()
+{
+ return QmlDebugServer::instance() != 0;
+}
+
+QString QmlDebugService::objectToString(QObject *obj)
+{
+ if(!obj)
+ return QLatin1String("NULL");
+
+ QString objectName = obj->objectName();
+ if(objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+
+ QString rv = QString::fromUtf8(obj->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+
+ return rv;
+}
+
+void QmlDebugService::waitForClients()
+{
+ QmlDebugServer::instance()->wait();
+}
+
+void QmlDebugService::sendMessage(const QByteArray &message)
+{
+ Q_D(QmlDebugService);
+
+ if (!d->server || !d->server->d_func()->connection)
+ return;
+
+ QPacket pack;
+ pack << d->name << message;
+ d->server->d_func()->protocol->send(pack);
+ d->server->d_func()->connection->flush();
+}
+
+void QmlDebugService::enabledChanged(bool)
+{
+}
+
+void QmlDebugService::messageReceived(const QByteArray &)
+{
+}
+
+QT_END_NAMESPACE
+
+#include <qmldebugservice.moc>
diff --git a/src/declarative/debugger/qmldebugservice_p.h b/src/declarative/debugger/qmldebugservice_p.h
new file mode 100644
index 0000000..b406a3c
--- /dev/null
+++ b/src/declarative/debugger/qmldebugservice_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGSERVICE_H
+#define QMLDEBUGSERVICE_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlDebugServicePrivate;
+class Q_DECLARATIVE_EXPORT QmlDebugService : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlDebugService)
+ Q_DISABLE_COPY(QmlDebugService)
+public:
+ QmlDebugService(const QString &, QObject *parent = 0);
+
+ QString name() const;
+
+ bool isEnabled() const;
+
+ void sendMessage(const QByteArray &);
+
+ static int idForObject(QObject *);
+ static QObject *objectForId(int);
+
+
+ static bool isDebuggingEnabled();
+ static QString objectToString(QObject *obj);
+
+ static void waitForClients();
+
+protected:
+ virtual void enabledChanged(bool);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ friend class QmlDebugServer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDEBUGSERVICE_H
+
diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp
new file mode 100644
index 0000000..fb07c62
--- /dev/null
+++ b/src/declarative/debugger/qpacketprotocol.cpp
@@ -0,0 +1,498 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpacketprotocol_p.h"
+
+#include <QBuffer>
+
+QT_BEGIN_NAMESPACE
+
+#define MAX_PACKET_SIZE 0x7FFFFFFF
+
+/*!
+ \class QPacketProtocol
+ \internal
+
+ \brief The QPacketProtocol class encapsulates communicating discrete packets
+ across fragmented IO channels, such as TCP sockets.
+
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ fragmented transports such as TCP and UDP.
+
+ As transmission boundaries are not respected, sending packets over protocols
+ like TCP frequently involves "stitching" them back together at the receiver.
+ QPacketProtocol makes this easier by performing this task for you. Packet
+ data sent using QPacketProtocol is prepended with a 4-byte size header
+ allowing the receiving QPacketProtocol to buffer the packet internally until
+ it has all been received. QPacketProtocol does not perform any sanity
+ checking on the size or on the data, so this class should only be used in
+ prototyping or trusted situations where DOS attacks are unlikely.
+
+ QPacketProtocol does not perform any communications itself. Instead it can
+ operate on any QIODevice that supports the QIODevice::readyRead() signal. A
+ logical "packet" is encapsulated by the companion QPacket class. The
+ following example shows two ways to send data using QPacketProtocol. The
+ transmitted data is equivalent in both.
+
+ \code
+ QTcpSocket socket;
+ // ... connect socket ...
+
+ QPacketProtocol protocol(&socket);
+
+ // Send packet the quick way
+ protocol.send() << "Hello world" << 123;
+
+ // Send packet the longer way
+ QPacket packet;
+ packet << "Hello world" << 123;
+ protocol.send(packet);
+ \endcode
+
+ Likewise, the following shows how to read data from QPacketProtocol, assuming
+ that the QPacketProtocol::readyRead() signal has been emitted.
+
+ \code
+ // ... QPacketProtocol::readyRead() is emitted ...
+
+ int a;
+ QByteArray b;
+
+ // Receive packet the quick way
+ protocol.read() >> a >> b;
+
+ // Receive packet the longer way
+ QPacket packet = protocol.read();
+ p >> a >> b;
+ \endcode
+
+ \ingroup io
+ \sa QPacket
+*/
+
+class QPacketProtocolPrivate : public QObject
+{
+Q_OBJECT
+public:
+ QPacketProtocolPrivate(QPacketProtocol * parent, QIODevice * _dev)
+ : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
+ dev(_dev)
+ {
+ Q_ASSERT(4 == sizeof(qint32));
+
+ QObject::connect(this, SIGNAL(readyRead()),
+ parent, SIGNAL(readyRead()));
+ QObject::connect(this, SIGNAL(packetWritten()),
+ parent, SIGNAL(packetWritten()));
+ QObject::connect(this, SIGNAL(invalidPacket()),
+ parent, SIGNAL(invalidPacket()));
+ QObject::connect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::connect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ }
+
+Q_SIGNALS:
+ void readyRead();
+ void packetWritten();
+ void invalidPacket();
+
+public Q_SLOTS:
+ void aboutToClose()
+ {
+ inProgress.clear();
+ sendingPackets.clear();
+ inProgressSize = -1;
+ }
+
+ void bytesWritten(qint64 bytes)
+ {
+ Q_ASSERT(!sendingPackets.isEmpty());
+
+ while(bytes) {
+ if(sendingPackets.at(0) > bytes) {
+ sendingPackets[0] -= bytes;
+ bytes = 0;
+ } else {
+ bytes -= sendingPackets.at(0);
+ sendingPackets.removeFirst();
+ emit packetWritten();
+ }
+ }
+ }
+
+ void readyToRead()
+ {
+ if(-1 == inProgressSize) {
+ // We need a size header of sizeof(qint32)
+ if(sizeof(qint32) > (uint)dev->bytesAvailable())
+ return;
+
+ // Read size header
+ int read = dev->read((char *)&inProgressSize, sizeof(qint32));
+ Q_ASSERT(read == sizeof(qint32));
+ Q_UNUSED(read);
+
+ // Check sizing constraints
+ if(inProgressSize > maxPacketSize) {
+ QObject::disconnect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::disconnect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ dev = 0;
+ emit invalidPacket();
+ return;
+ }
+
+ inProgressSize -= sizeof(qint32);
+
+ // Need to get trailing data
+ readyToRead();
+ } else {
+ inProgress.append(dev->read(inProgressSize - inProgress.size()));
+
+ if(inProgressSize == inProgress.size()) {
+ // Packet has arrived!
+ packets.append(inProgress);
+ inProgressSize = -1;
+ inProgress.clear();
+
+ emit readyRead();
+
+ // Need to get trailing data
+ readyToRead();
+ }
+ }
+ }
+
+public:
+ QList<qint64> sendingPackets;
+ QList<QByteArray> packets;
+ QByteArray inProgress;
+ qint32 inProgressSize;
+ qint32 maxPacketSize;
+ QIODevice * dev;
+};
+
+/*!
+ Construct a QPacketProtocol instance that works on \a dev with the
+ specified \a parent.
+ */
+QPacketProtocol::QPacketProtocol(QIODevice * dev, QObject * parent)
+: QObject(parent), d(new QPacketProtocolPrivate(this, dev))
+{
+ Q_ASSERT(dev);
+}
+
+/*!
+ Destroys the QPacketProtocol instance.
+ */
+QPacketProtocol::~QPacketProtocol()
+{
+}
+
+/*!
+ Returns the maximum packet size allowed. By default this is
+ 2,147,483,647 bytes.
+
+ If a packet claiming to be larger than the maximum packet size is received,
+ the QPacketProtocol::invalidPacket() signal is emitted.
+
+ \sa QPacketProtocol::setMaximumPacketSize()
+ */
+qint32 QPacketProtocol::maximumPacketSize() const
+{
+ return d->maxPacketSize;
+}
+
+/*!
+ Sets the maximum allowable packet size to \a max.
+
+ \sa QPacketProtocol::maximumPacketSize()
+ */
+qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
+{
+ if(max > (signed)sizeof(qint32))
+ d->maxPacketSize = max;
+ return d->maxPacketSize;
+}
+
+/*!
+ Returns a streamable object that is transmitted on destruction. For example
+
+ \code
+ protocol.send() << "Hello world" << 123;
+ \endcode
+
+ will send a packet containing "Hello world" and 123. To construct more
+ complex packets, explicitly construct a QPacket instance.
+ */
+QPacketAutoSend QPacketProtocol::send()
+{
+ return QPacketAutoSend(this);
+}
+
+/*!
+ \fn void QPacketProtocol::send(const QPacket & packet)
+
+ Transmit the \a packet.
+ */
+void QPacketProtocol::send(const QPacket & p)
+{
+ if(p.b.isEmpty())
+ return; // We don't send empty packets
+
+ qint64 sendSize = p.b.size() + sizeof(qint32);
+
+ d->sendingPackets.append(sendSize);
+ qint32 sendSize32 = sendSize;
+ qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_ASSERT(writeBytes == sizeof(qint32));
+ writeBytes = d->dev->write(p.b);
+ Q_ASSERT(writeBytes == p.b.size());
+}
+
+/*!
+ Returns the number of received packets yet to be read.
+ */
+qint64 QPacketProtocol::packetsAvailable() const
+{
+ return d->packets.count();
+}
+
+/*!
+ Discard any unread packets.
+ */
+void QPacketProtocol::clear()
+{
+ d->packets.clear();
+}
+
+/*!
+ Return the next unread packet, or an invalid QPacket instance if no packets
+ are available. This method does NOT block.
+ */
+QPacket QPacketProtocol::read()
+{
+ if(0 == d->packets.count())
+ return QPacket();
+
+ QPacket rv(d->packets.at(0));
+ d->packets.removeFirst();
+ return rv;
+}
+
+/*!
+ Return the QIODevice passed to the QPacketProtocol constructor.
+*/
+QIODevice * QPacketProtocol::device()
+{
+ return d->dev;
+}
+
+/*!
+ \fn void QPacketProtocol::readyRead()
+
+ Emitted whenever a new packet is received. Applications may use
+ QPacketProtocol::read() to retrieve this packet.
+ */
+
+/*!
+ \fn void QPacketProtocol::invalidPacket()
+
+ A packet larger than the maximum allowable packet size was received. The
+ packet will be discarded and, as it indicates corruption in the protocol, no
+ further packets will be received.
+ */
+
+/*!
+ \fn void QPacketProtocol::packetWritten()
+
+ Emitted each time a packet is completing written to the device. This signal
+ may be used for communications flow control.
+ */
+
+/*!
+ \class QPacket
+ \internal
+
+ \brief The QPacket class encapsulates an unfragmentable packet of data to be
+ transmitted by QPacketProtocol.
+
+ The QPacket class works together with QPacketProtocol to make it simple to
+ send arbitrary sized data "packets" across fragmented transports such as TCP
+ and UDP.
+
+ QPacket provides a QDataStream interface to an unfragmentable packet.
+ Applications should construct a QPacket, propagate it with data and then
+ transmit it over a QPacketProtocol instance. For example:
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket myPacket;
+ myPacket << "Hello world!" << 123;
+ protocol.send(myPacket);
+ \endcode
+
+ As long as both ends of the connection are using the QPacketProtocol class,
+ the data within this packet will be delivered unfragmented at the other end,
+ ready for extraction.
+
+ \code
+ QByteArray greeting;
+ int count;
+
+ QPacket myPacket = protocol.read();
+
+ myPacket >> greeting >> count;
+ \endcode
+
+ Only packets returned from QPacketProtocol::read() may be read from. QPacket
+ instances constructed by directly by applications are for transmission only
+ and are considered "write only". Attempting to read data from them will
+ result in undefined behavior.
+
+ \ingroup io
+ \sa QPacketProtocol
+ */
+
+/*!
+ Constructs an empty write-only packet.
+ */
+QPacket::QPacket()
+: QDataStream(), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::WriteOnly);
+ setDevice(buf);
+}
+
+/*!
+ Destroys the QPacket instance.
+ */
+QPacket::~QPacket()
+{
+ if(buf) {
+ delete buf;
+ buf = 0;
+ }
+}
+
+/*!
+ Creates a copy of \a other. The initial stream positions are shared, but the
+ two packets are otherwise independant.
+ */
+QPacket::QPacket(const QPacket & other)
+: QDataStream(), b(other.b), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(other.buf->openMode());
+ setDevice(buf);
+}
+
+/*!
+ \internal
+ */
+QPacket::QPacket(const QByteArray & ba)
+: QDataStream(), b(ba), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::ReadOnly);
+ setDevice(buf);
+}
+
+/*!
+ Returns true if this packet is empty - that is, contains no data.
+ */
+bool QPacket::isEmpty() const
+{
+ return b.isEmpty();
+}
+
+/*!
+ Clears data in the packet. This is useful for reusing one writable packet.
+ For example
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket packet;
+
+ packet << "Hello world!" << 123;
+ protocol.send(packet);
+
+ packet.clear();
+ packet << "Goodbyte world!" << 789;
+ protocol.send(packet);
+ \endcode
+ */
+void QPacket::clear()
+{
+ QBuffer::OpenMode oldMode = buf->openMode();
+ buf->close();
+ b.clear();
+ buf->setBuffer(&b); // reset QBuffer internals with new size of b.
+ buf->open(oldMode);
+}
+
+/*!
+ \class QPacketAutoSend
+ \internal
+
+ \internal
+ */
+QPacketAutoSend::QPacketAutoSend(QPacketProtocol * _p)
+: QPacket(), p(_p)
+{
+}
+
+QPacketAutoSend::~QPacketAutoSend()
+{
+ if(!b.isEmpty())
+ p->send(*this);
+}
+
+QT_END_NAMESPACE
+
+#include <qpacketprotocol.moc>
diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h
new file mode 100644
index 0000000..265af81
--- /dev/null
+++ b/src/declarative/debugger/qpacketprotocol_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPACKETPROTOCOL_H
+#define QPACKETPROTOCOL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QIODevice;
+class QBuffer;
+class QPacket;
+class QPacketAutoSend;
+class QPacketProtocolPrivate;
+
+class Q_DECLARATIVE_EXPORT QPacketProtocol : public QObject
+{
+Q_OBJECT
+public:
+ explicit QPacketProtocol(QIODevice * dev, QObject * parent = 0);
+ virtual ~QPacketProtocol();
+
+ qint32 maximumPacketSize() const;
+ qint32 setMaximumPacketSize(qint32);
+
+ QPacketAutoSend send();
+ void send(const QPacket &);
+
+ qint64 packetsAvailable() const;
+ QPacket read();
+
+ void clear();
+
+ QIODevice * device();
+
+Q_SIGNALS:
+ void readyRead();
+ void invalidPacket();
+ void packetWritten();
+
+private:
+ QPacketProtocolPrivate * d;
+};
+
+
+class Q_DECLARATIVE_EXPORT QPacket : public QDataStream
+{
+public:
+ QPacket();
+ QPacket(const QPacket &);
+ virtual ~QPacket();
+
+ void clear();
+ bool isEmpty() const;
+
+protected:
+ friend class QPacketProtocol;
+ QPacket(const QByteArray & ba);
+ QByteArray b;
+ QBuffer * buf;
+};
+
+class Q_DECLARATIVE_EXPORT QPacketAutoSend : public QPacket
+{
+public:
+ virtual ~QPacketAutoSend();
+
+private:
+ friend class QPacketProtocol;
+ QPacketAutoSend(QPacketProtocol *);
+ QPacketProtocol * p;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
new file mode 100644
index 0000000..86a0370
--- /dev/null
+++ b/src/declarative/declarative.pro
@@ -0,0 +1,30 @@
+TARGET = QtDeclarative
+QPRO_PWD = $$PWD
+QT = core gui xml script network
+contains(QT_CONFIG, svg): QT += svg
+contains(QT_CONFIG, opengl): QT += opengl
+DEFINES += QT_BUILD_DECLARATIVE_LIB QT_NO_URL_CAST_FROM_STRING
+win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000
+solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+
+unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui QtXml
+
+exists("qml_enable_gcov") {
+ QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
+ LIBS += -lgcov
+}
+
+include(../qbase.pri)
+
+#INCLUDEPATH -= $$QMAKE_INCDIR_QT/$$TARGET
+#DESTDIR=.
+
+#modules
+include(3rdparty/3rdparty.pri)
+include(util/util.pri)
+include(graphicsitems/graphicsitems.pri)
+include(qml/qml.pri)
+include(widgets/widgets.pri)
+include(debugger/debugger.pri)
+
+symbian:TARGET.UID3=0x2001E623
diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri
new file mode 100644
index 0000000..eb6e0ad
--- /dev/null
+++ b/src/declarative/graphicsitems/graphicsitems.pri
@@ -0,0 +1,90 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qmlgraphicsanchors_p.h \
+ $$PWD/qmlgraphicsanchors_p_p.h \
+ $$PWD/qmlgraphicsevents_p_p.h \
+ $$PWD/qmlgraphicsflickable_p.h \
+ $$PWD/qmlgraphicsflickable_p_p.h \
+ $$PWD/qmlgraphicsflipable_p.h \
+ $$PWD/qmlgraphicsgridview_p.h \
+ $$PWD/qmlgraphicsimage_p.h \
+ $$PWD/qmlgraphicsimagebase_p.h \
+ $$PWD/qmlgraphicsborderimage_p.h \
+ $$PWD/qmlgraphicspainteditem_p.h \
+ $$PWD/qmlgraphicspainteditem_p_p.h \
+ $$PWD/qmlgraphicsimage_p_p.h \
+ $$PWD/qmlgraphicsborderimage_p_p.h \
+ $$PWD/qmlgraphicsimagebase_p_p.h \
+ $$PWD/qmlgraphicsanimatedimage_p.h \
+ $$PWD/qmlgraphicsanimatedimage_p_p.h \
+ $$PWD/qmlgraphicsitem.h \
+ $$PWD/qmlgraphicsitem_p.h \
+ $$PWD/qmlgraphicsfocuspanel_p.h \
+ $$PWD/qmlgraphicsfocusscope_p.h \
+ $$PWD/qmlgraphicspositioners_p.h \
+ $$PWD/qmlgraphicspositioners_p_p.h \
+ $$PWD/qmlgraphicsloader_p.h \
+ $$PWD/qmlgraphicsloader_p_p.h \
+ $$PWD/qmlgraphicsmouseregion_p.h \
+ $$PWD/qmlgraphicsmouseregion_p_p.h \
+ $$PWD/qmlgraphicspath_p.h \
+ $$PWD/qmlgraphicspath_p_p.h \
+ $$PWD/qmlgraphicspathview_p.h \
+ $$PWD/qmlgraphicspathview_p_p.h \
+ $$PWD/qmlgraphicsrectangle_p.h \
+ $$PWD/qmlgraphicsrectangle_p_p.h \
+ $$PWD/qmlgraphicsrepeater_p.h \
+ $$PWD/qmlgraphicsrepeater_p_p.h \
+ $$PWD/qmlgraphicsscalegrid_p_p.h \
+ $$PWD/qmlgraphicstextinput_p.h \
+ $$PWD/qmlgraphicstextinput_p_p.h \
+ $$PWD/qmlgraphicstextedit_p.h \
+ $$PWD/qmlgraphicstextedit_p_p.h \
+ $$PWD/qmlgraphicstext_p.h \
+ $$PWD/qmlgraphicstext_p_p.h \
+ $$PWD/qmlgraphicsvisualitemmodel_p.h \
+ $$PWD/qmlgraphicslistview_p.h \
+ $$PWD/qmlgraphicsgraphicsobjectcontainer_p.h \
+ $$PWD/qmlgraphicsparticles_p.h \
+ $$PWD/qmlgraphicslayoutitem_p.h \
+ $$PWD/qmlgraphicsitemchangelistener_p.h \
+ $$PWD/qmlgraphicseffects.cpp
+
+SOURCES += \
+ $$PWD/qmlgraphicsanchors.cpp \
+ $$PWD/qmlgraphicsevents.cpp \
+ $$PWD/qmlgraphicsflickable.cpp \
+ $$PWD/qmlgraphicsflipable.cpp \
+ $$PWD/qmlgraphicsgridview.cpp \
+ $$PWD/qmlgraphicsimage.cpp \
+ $$PWD/qmlgraphicsborderimage.cpp \
+ $$PWD/qmlgraphicsimagebase.cpp \
+ $$PWD/qmlgraphicsanimatedimage.cpp \
+ $$PWD/qmlgraphicspainteditem.cpp \
+ $$PWD/qmlgraphicsitem.cpp \
+ $$PWD/qmlgraphicsfocuspanel.cpp \
+ $$PWD/qmlgraphicsfocusscope.cpp \
+ $$PWD/qmlgraphicspositioners.cpp \
+ $$PWD/qmlgraphicsloader.cpp \
+ $$PWD/qmlgraphicsmouseregion.cpp \
+ $$PWD/qmlgraphicspath.cpp \
+ $$PWD/qmlgraphicspathview.cpp \
+ $$PWD/qmlgraphicsrectangle.cpp \
+ $$PWD/qmlgraphicsrepeater.cpp \
+ $$PWD/qmlgraphicsscalegrid.cpp \
+ $$PWD/qmlgraphicstextinput.cpp \
+ $$PWD/qmlgraphicstext.cpp \
+ $$PWD/qmlgraphicstextedit.cpp \
+ $$PWD/qmlgraphicsvisualitemmodel.cpp \
+ $$PWD/qmlgraphicslistview.cpp \
+ $$PWD/qmlgraphicsgraphicsobjectcontainer.cpp \
+ $$PWD/qmlgraphicsparticles.cpp \
+ $$PWD/qmlgraphicslayoutitem.cpp \
+
+contains(QT_CONFIG, webkit) {
+ QT+=webkit
+ SOURCES += $$PWD/qmlgraphicswebview.cpp
+ HEADERS += $$PWD/qmlgraphicswebview_p.h
+ HEADERS += $$PWD/qmlgraphicswebview_p_p.h
+}
diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp
new file mode 100644
index 0000000..93055fc
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp
@@ -0,0 +1,1060 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsanchors_p_p.h"
+
+#include "qmlgraphicsitem.h"
+#include "qmlgraphicsitem_p.h"
+
+#include <qmlinfo.h>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsAnchors)
+
+//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
+//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
+
+//### const item?
+//local position
+static qreal position(QmlGraphicsItem *item, QmlGraphicsAnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ switch(anchorLine) {
+ case QmlGraphicsAnchorLine::Left:
+ ret = item->x();
+ break;
+ case QmlGraphicsAnchorLine::Right:
+ ret = item->x() + item->width();
+ break;
+ case QmlGraphicsAnchorLine::Top:
+ ret = item->y();
+ break;
+ case QmlGraphicsAnchorLine::Bottom:
+ ret = item->y() + item->height();
+ break;
+ case QmlGraphicsAnchorLine::HCenter:
+ ret = item->x() + item->width()/2;
+ break;
+ case QmlGraphicsAnchorLine::VCenter:
+ ret = item->y() + item->height()/2;
+ break;
+ case QmlGraphicsAnchorLine::Baseline:
+ ret = item->y() + item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+//position when origin is 0,0
+static qreal adjustedPosition(QmlGraphicsItem *item, QmlGraphicsAnchorLine::AnchorLine anchorLine)
+{
+ int ret = 0;
+ switch(anchorLine) {
+ case QmlGraphicsAnchorLine::Left:
+ ret = 0;
+ break;
+ case QmlGraphicsAnchorLine::Right:
+ ret = item->width();
+ break;
+ case QmlGraphicsAnchorLine::Top:
+ ret = 0;
+ break;
+ case QmlGraphicsAnchorLine::Bottom:
+ ret = item->height();
+ break;
+ case QmlGraphicsAnchorLine::HCenter:
+ ret = item->width()/2;
+ break;
+ case QmlGraphicsAnchorLine::VCenter:
+ ret = item->height()/2;
+ break;
+ case QmlGraphicsAnchorLine::Baseline:
+ ret = item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ \internal
+ \class QmlGraphicsAnchors
+ \ingroup group_layouts
+ \brief The QmlGraphicsAnchors class provides a way to lay out items relative to other items.
+
+ \warning Currently, only anchoring to siblings or parent is supported.
+*/
+
+QmlGraphicsAnchors::QmlGraphicsAnchors(QObject *parent)
+ : QObject(*new QmlGraphicsAnchorsPrivate(0), parent)
+{
+ qFatal("QmlGraphicsAnchors::QmlGraphicsAnchors(QObject*) called");
+}
+
+QmlGraphicsAnchors::QmlGraphicsAnchors(QmlGraphicsItem *item, QObject *parent)
+ : QObject(*new QmlGraphicsAnchorsPrivate(item), parent)
+{
+}
+
+QmlGraphicsAnchors::~QmlGraphicsAnchors()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->remDepend(d->fill);
+ d->remDepend(d->centerIn);
+ d->remDepend(d->left.item);
+ d->remDepend(d->right.item);
+ d->remDepend(d->top.item);
+ d->remDepend(d->bottom.item);
+ d->remDepend(d->vCenter.item);
+ d->remDepend(d->hCenter.item);
+ d->remDepend(d->baseline.item);
+}
+
+void QmlGraphicsAnchorsPrivate::fillChanged()
+{
+ if (!fill || !isItemComplete())
+ return;
+
+ if (updatingFill < 2) {
+ ++updatingFill;
+
+ if (fill == item->parentItem()) { //child-parent
+ setItemPos(QPointF(leftMargin, topMargin));
+ } else if (fill->parentItem() == item->parentItem()) { //siblings
+ setItemPos(QPointF(fill->x()+leftMargin, fill->y()+topMargin));
+ }
+ setItemWidth(fill->width()-leftMargin-rightMargin);
+ setItemHeight(fill->height()-topMargin-bottomMargin);
+
+ --updatingFill;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Possible anchor loop detected on fill.");
+ }
+
+}
+
+void QmlGraphicsAnchorsPrivate::centerInChanged()
+{
+ if (!centerIn || fill || !isItemComplete())
+ return;
+
+ if (updatingCenterIn < 2) {
+ ++updatingCenterIn;
+
+ if (centerIn == item->parentItem()) {
+ QPointF p((item->parentItem()->width() - item->width()) / 2. + hCenterOffset,
+ (item->parentItem()->height() - item->height()) / 2. + vCenterOffset);
+ setItemPos(p);
+
+ } else if (centerIn->parentItem() == item->parentItem()) {
+
+ QPointF p(centerIn->x() + (centerIn->width() - item->width()) / 2. + hCenterOffset,
+ centerIn->y() + (centerIn->height() - item->height()) / 2. + vCenterOffset);
+ setItemPos(p);
+ }
+
+ --updatingCenterIn;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Possible anchor loop detected on centerIn.");
+ }
+}
+
+void QmlGraphicsAnchorsPrivate::clearItem(QmlGraphicsItem *item)
+{
+ if (!item)
+ return;
+ if (fill == item)
+ fill = 0;
+ if (centerIn == item)
+ centerIn = 0;
+ if (left.item == item) {
+ left.item = 0;
+ usedAnchors &= ~QmlGraphicsAnchors::HasLeftAnchor;
+ }
+ if (right.item == item) {
+ right.item = 0;
+ usedAnchors &= ~QmlGraphicsAnchors::HasRightAnchor;
+ }
+ if (top.item == item) {
+ top.item = 0;
+ usedAnchors &= ~QmlGraphicsAnchors::HasTopAnchor;
+ }
+ if (bottom.item == item) {
+ bottom.item = 0;
+ usedAnchors &= ~QmlGraphicsAnchors::HasBottomAnchor;
+ }
+ if (vCenter.item == item) {
+ vCenter.item = 0;
+ usedAnchors &= ~QmlGraphicsAnchors::HasVCenterAnchor;
+ }
+ if (hCenter.item == item) {
+ hCenter.item = 0;
+ usedAnchors &= ~QmlGraphicsAnchors::HasHCenterAnchor;
+ }
+ if (baseline.item == item) {
+ baseline.item = 0;
+ usedAnchors &= ~QmlGraphicsAnchors::HasBaselineAnchor;
+ }
+}
+
+void QmlGraphicsAnchorsPrivate::addDepend(QmlGraphicsItem *item)
+{
+ if (!item)
+ return;
+ QmlGraphicsItemPrivate *p =
+ static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(item));
+ p->addItemChangeListener(this, QmlGraphicsItemPrivate::Geometry);
+}
+
+void QmlGraphicsAnchorsPrivate::remDepend(QmlGraphicsItem *item)
+{
+ if (!item)
+ return;
+ QmlGraphicsItemPrivate *p =
+ static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(item));
+ p->removeItemChangeListener(this, QmlGraphicsItemPrivate::Geometry);
+}
+
+bool QmlGraphicsAnchorsPrivate::isItemComplete() const
+{
+ return componentComplete;
+}
+
+void QmlGraphicsAnchors::classBegin()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->componentComplete = false;
+}
+
+void QmlGraphicsAnchors::componentComplete()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->componentComplete = true;
+}
+
+void QmlGraphicsAnchorsPrivate::setItemHeight(qreal v)
+{
+ updatingMe = true;
+ item->setHeight(v);
+ updatingMe = false;
+}
+
+void QmlGraphicsAnchorsPrivate::setItemWidth(qreal v)
+{
+ updatingMe = true;
+ item->setWidth(v);
+ updatingMe = false;
+}
+
+void QmlGraphicsAnchorsPrivate::setItemX(qreal v)
+{
+ updatingMe = true;
+ item->setX(v);
+ updatingMe = false;
+}
+
+void QmlGraphicsAnchorsPrivate::setItemY(qreal v)
+{
+ updatingMe = true;
+ item->setY(v);
+ updatingMe = false;
+}
+
+void QmlGraphicsAnchorsPrivate::setItemPos(const QPointF &v)
+{
+ updatingMe = true;
+ item->setPos(v);
+ updatingMe = false;
+}
+
+void QmlGraphicsAnchorsPrivate::updateMe()
+{
+ if (updatingMe) {
+ updatingMe = false;
+ return;
+ }
+
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QmlGraphicsAnchorsPrivate::updateOnComplete()
+{
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QmlGraphicsAnchorsPrivate::itemGeometryChanged(QmlGraphicsItem *, const QRectF &newG, const QRectF &oldG)
+{
+ fillChanged();
+ centerInChanged();
+
+ if (newG.x() != oldG.x() || newG.width() != oldG.width())
+ updateHorizontalAnchors();
+ if (newG.y() != oldG.y() || newG.height() != oldG.height())
+ updateVerticalAnchors();
+}
+
+QmlGraphicsItem *QmlGraphicsAnchors::fill() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->fill;
+}
+
+void QmlGraphicsAnchors::setFill(QmlGraphicsItem *f)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->fill == f)
+ return;
+
+ if (!f) {
+ d->remDepend(d->fill);
+ d->fill = f;
+ emit fillChanged();
+ return;
+ }
+ if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
+ qmlInfo(d->item) << tr("Can't anchor to an item that isn't a parent or sibling.");
+ return;
+ }
+ d->remDepend(d->fill);
+ d->fill = f;
+ d->addDepend(d->fill);
+ emit fillChanged();
+ d->fillChanged();
+}
+
+void QmlGraphicsAnchors::resetFill()
+{
+ setFill(0);
+}
+
+QmlGraphicsItem *QmlGraphicsAnchors::centerIn() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->centerIn;
+}
+
+void QmlGraphicsAnchors::setCenterIn(QmlGraphicsItem* c)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->centerIn == c)
+ return;
+
+ if (!c) {
+ d->remDepend(d->centerIn);
+ d->centerIn = c;
+ emit centerInChanged();
+ return;
+ }
+ if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
+ qmlInfo(d->item) << tr("Can't anchor to an item that isn't a parent or sibling.");
+ return;
+ }
+
+ d->remDepend(d->centerIn);
+ d->centerIn = c;
+ d->addDepend(d->centerIn);
+ emit centerInChanged();
+ d->centerInChanged();
+}
+
+void QmlGraphicsAnchors::resetCenterIn()
+{
+ setCenterIn(0);
+}
+
+bool QmlGraphicsAnchorsPrivate::calcStretch(const QmlGraphicsAnchorLine &edge1,
+ const QmlGraphicsAnchorLine &edge2,
+ int offset1,
+ int offset2,
+ QmlGraphicsAnchorLine::AnchorLine line,
+ int &stretch)
+{
+ bool edge1IsParent = (edge1.item == item->parentItem());
+ bool edge2IsParent = (edge2.item == item->parentItem());
+ bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
+ bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
+
+ bool invalid = false;
+ if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsParent && edge1IsSibling) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(item->parentItem(), line)
+ + (int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsSibling && edge1IsParent) {
+ stretch = ((int)position(item->parentItem(), line) + (int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else
+ invalid = true;
+
+ return invalid;
+}
+
+void QmlGraphicsAnchorsPrivate::updateVerticalAnchors()
+{
+ if (fill || centerIn || !isItemComplete())
+ return;
+
+ if (updatingVerticalAnchor < 2) {
+ ++updatingVerticalAnchor;
+ if (usedAnchors & QmlGraphicsAnchors::HasTopAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ int height = 0;
+ if (usedAnchors & QmlGraphicsAnchors::HasBottomAnchor) {
+ invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QmlGraphicsAnchorLine::Top, height);
+ } else if (usedAnchors & QmlGraphicsAnchors::HasVCenterAnchor) {
+ invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QmlGraphicsAnchorLine::Top, height);
+ height *= 2;
+ }
+ if (!invalid)
+ setItemHeight(height);
+
+ //Handle top
+ if (top.item == item->parentItem()) {
+ setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
+ } else if (top.item->parentItem() == item->parentItem()) {
+ setItemY(position(top.item, top.anchorLine) + topMargin);
+ }
+ } else if (usedAnchors & QmlGraphicsAnchors::HasBottomAnchor) {
+ //Handle stretching (top + bottom case is handled above)
+ if (usedAnchors & QmlGraphicsAnchors::HasVCenterAnchor) {
+ int height = 0;
+ bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
+ QmlGraphicsAnchorLine::Top, height);
+ if (!invalid)
+ setItemHeight(height*2);
+ }
+
+ //Handle bottom
+ if (bottom.item == item->parentItem()) {
+ setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
+ } else if (bottom.item->parentItem() == item->parentItem()) {
+ setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
+ }
+ } else if (usedAnchors & QmlGraphicsAnchors::HasVCenterAnchor) {
+ //(stetching handled above)
+
+ //Handle vCenter
+ if (vCenter.item == item->parentItem()) {
+ setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
+ - item->height()/2 + vCenterOffset);
+ } else if (vCenter.item->parentItem() == item->parentItem()) {
+ setItemY(position(vCenter.item, vCenter.anchorLine) - item->height()/2 + vCenterOffset);
+ }
+ } else if (usedAnchors & QmlGraphicsAnchors::HasBaselineAnchor) {
+ //Handle baseline
+ if (baseline.item == item->parentItem()) {
+ setItemY(adjustedPosition(baseline.item, baseline.anchorLine)
+ - item->baselineOffset() + baselineOffset);
+ } else if (baseline.item->parentItem() == item->parentItem()) {
+ setItemY(position(baseline.item, baseline.anchorLine)
+ - item->baselineOffset() + baselineOffset);
+ }
+ }
+ --updatingVerticalAnchor;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Possible anchor loop detected on vertical anchor.");
+ }
+}
+
+void QmlGraphicsAnchorsPrivate::updateHorizontalAnchors()
+{
+ if (fill || centerIn || !isItemComplete())
+ return;
+
+ if (updatingHorizontalAnchor < 2) {
+ ++updatingHorizontalAnchor;
+
+ if (usedAnchors & QmlGraphicsAnchors::HasLeftAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ int width = 0;
+ if (usedAnchors & QmlGraphicsAnchors::HasRightAnchor) {
+ invalid = calcStretch(left, right, leftMargin, -rightMargin, QmlGraphicsAnchorLine::Left, width);
+ } else if (usedAnchors & QmlGraphicsAnchors::HasHCenterAnchor) {
+ invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QmlGraphicsAnchorLine::Left, width);
+ width *= 2;
+ }
+ if (!invalid)
+ setItemWidth(width);
+
+ //Handle left
+ if (left.item == item->parentItem()) {
+ setItemX(adjustedPosition(left.item, left.anchorLine) + leftMargin);
+ } else if (left.item->parentItem() == item->parentItem()) {
+ setItemX(position(left.item, left.anchorLine) + leftMargin);
+ }
+ } else if (usedAnchors & QmlGraphicsAnchors::HasRightAnchor) {
+ //Handle stretching (left + right case is handled in updateLeftAnchor)
+ if (usedAnchors & QmlGraphicsAnchors::HasHCenterAnchor) {
+ int width = 0;
+ bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin,
+ QmlGraphicsAnchorLine::Left, width);
+ if (!invalid)
+ setItemWidth(width*2);
+ }
+
+ //Handle right
+ if (right.item == item->parentItem()) {
+ setItemX(adjustedPosition(right.item, right.anchorLine) - item->width() - rightMargin);
+ } else if (right.item->parentItem() == item->parentItem()) {
+ setItemX(position(right.item, right.anchorLine) - item->width() - rightMargin);
+ }
+ } else if (usedAnchors & QmlGraphicsAnchors::HasHCenterAnchor) {
+ //Handle hCenter
+ if (hCenter.item == item->parentItem()) {
+ setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset);
+ } else if (hCenter.item->parentItem() == item->parentItem()) {
+ setItemX(position(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset);
+ }
+ }
+
+ --updatingHorizontalAnchor;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Possible anchor loop detected on horizontal anchor.");
+ }
+}
+
+QmlGraphicsAnchorLine QmlGraphicsAnchors::top() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->top;
+}
+
+void QmlGraphicsAnchors::setTop(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (!d->checkVAnchorValid(edge) || d->top == edge)
+ return;
+
+ d->usedAnchors |= HasTopAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~HasTopAnchor;
+ return;
+ }
+
+ d->remDepend(d->top.item);
+ d->top = edge;
+ d->addDepend(d->top.item);
+ emit topChanged();
+ d->updateVerticalAnchors();
+}
+
+void QmlGraphicsAnchors::resetTop()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->usedAnchors &= ~HasTopAnchor;
+ d->remDepend(d->top.item);
+ d->top = QmlGraphicsAnchorLine();
+ emit topChanged();
+ d->updateVerticalAnchors();
+}
+
+QmlGraphicsAnchorLine QmlGraphicsAnchors::bottom() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->bottom;
+}
+
+void QmlGraphicsAnchors::setBottom(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (!d->checkVAnchorValid(edge) || d->bottom == edge)
+ return;
+
+ d->usedAnchors |= HasBottomAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~HasBottomAnchor;
+ return;
+ }
+
+ d->remDepend(d->bottom.item);
+ d->bottom = edge;
+ d->addDepend(d->bottom.item);
+ emit bottomChanged();
+ d->updateVerticalAnchors();
+}
+
+void QmlGraphicsAnchors::resetBottom()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->usedAnchors &= ~HasBottomAnchor;
+ d->remDepend(d->bottom.item);
+ d->bottom = QmlGraphicsAnchorLine();
+ emit bottomChanged();
+ d->updateVerticalAnchors();
+}
+
+QmlGraphicsAnchorLine QmlGraphicsAnchors::verticalCenter() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->vCenter;
+}
+
+void QmlGraphicsAnchors::setVerticalCenter(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
+ return;
+
+ d->usedAnchors |= HasVCenterAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~HasVCenterAnchor;
+ return;
+ }
+
+ d->remDepend(d->vCenter.item);
+ d->vCenter = edge;
+ d->addDepend(d->vCenter.item);
+ emit verticalCenterChanged();
+ d->updateVerticalAnchors();
+}
+
+void QmlGraphicsAnchors::resetVerticalCenter()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->usedAnchors &= ~HasVCenterAnchor;
+ d->remDepend(d->vCenter.item);
+ d->vCenter = QmlGraphicsAnchorLine();
+ emit verticalCenterChanged();
+ d->updateVerticalAnchors();
+}
+
+QmlGraphicsAnchorLine QmlGraphicsAnchors::baseline() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->baseline;
+}
+
+void QmlGraphicsAnchors::setBaseline(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (!d->checkVAnchorValid(edge) || d->baseline == edge)
+ return;
+
+ d->usedAnchors |= HasBaselineAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~HasBaselineAnchor;
+ return;
+ }
+
+ d->remDepend(d->baseline.item);
+ d->baseline = edge;
+ d->addDepend(d->baseline.item);
+ emit baselineChanged();
+ d->updateVerticalAnchors();
+}
+
+void QmlGraphicsAnchors::resetBaseline()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->usedAnchors &= ~HasBaselineAnchor;
+ d->remDepend(d->baseline.item);
+ d->baseline = QmlGraphicsAnchorLine();
+ emit baselineChanged();
+ d->updateVerticalAnchors();
+}
+
+QmlGraphicsAnchorLine QmlGraphicsAnchors::left() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->left;
+}
+
+void QmlGraphicsAnchors::setLeft(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (!d->checkHAnchorValid(edge) || d->left == edge)
+ return;
+
+ d->usedAnchors |= HasLeftAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~HasLeftAnchor;
+ return;
+ }
+
+ d->remDepend(d->left.item);
+ d->left = edge;
+ d->addDepend(d->left.item);
+ emit leftChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QmlGraphicsAnchors::resetLeft()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->usedAnchors &= ~HasLeftAnchor;
+ d->remDepend(d->left.item);
+ d->left = QmlGraphicsAnchorLine();
+ emit leftChanged();
+ d->updateHorizontalAnchors();
+}
+
+QmlGraphicsAnchorLine QmlGraphicsAnchors::right() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->right;
+}
+
+void QmlGraphicsAnchors::setRight(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (!d->checkHAnchorValid(edge) || d->right == edge)
+ return;
+
+ d->usedAnchors |= HasRightAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~HasRightAnchor;
+ return;
+ }
+
+ d->remDepend(d->right.item);
+ d->right = edge;
+ d->addDepend(d->right.item);
+ emit rightChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QmlGraphicsAnchors::resetRight()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->usedAnchors &= ~HasRightAnchor;
+ d->remDepend(d->right.item);
+ d->right = QmlGraphicsAnchorLine();
+ emit rightChanged();
+ d->updateHorizontalAnchors();
+}
+
+QmlGraphicsAnchorLine QmlGraphicsAnchors::horizontalCenter() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->hCenter;
+}
+
+void QmlGraphicsAnchors::setHorizontalCenter(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
+ return;
+
+ d->usedAnchors |= HasHCenterAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~HasHCenterAnchor;
+ return;
+ }
+
+ d->remDepend(d->hCenter.item);
+ d->hCenter = edge;
+ d->addDepend(d->hCenter.item);
+ emit horizontalCenterChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QmlGraphicsAnchors::resetHorizontalCenter()
+{
+ Q_D(QmlGraphicsAnchors);
+ d->usedAnchors &= ~HasHCenterAnchor;
+ d->remDepend(d->hCenter.item);
+ d->hCenter = QmlGraphicsAnchorLine();
+ emit horizontalCenterChanged();
+ d->updateHorizontalAnchors();
+}
+
+qreal QmlGraphicsAnchors::leftMargin() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->leftMargin;
+}
+
+void QmlGraphicsAnchors::setLeftMargin(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->leftMargin == offset)
+ return;
+ d->leftMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit leftMarginChanged();
+}
+
+qreal QmlGraphicsAnchors::rightMargin() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->rightMargin;
+}
+
+void QmlGraphicsAnchors::setRightMargin(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->rightMargin == offset)
+ return;
+ d->rightMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit rightMarginChanged();
+}
+
+qreal QmlGraphicsAnchors::margins() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->margins;
+}
+
+void QmlGraphicsAnchors::setMargins(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->margins == offset)
+ return;
+ //###Is it significantly faster to set them directly so we can call fillChanged only once?
+ if(!d->rightMargin || d->rightMargin == d->margins)
+ setRightMargin(offset);
+ if(!d->leftMargin || d->leftMargin == d->margins)
+ setLeftMargin(offset);
+ if(!d->topMargin || d->topMargin == d->margins)
+ setTopMargin(offset);
+ if(!d->bottomMargin || d->bottomMargin == d->margins)
+ setBottomMargin(offset);
+ d->margins = offset;
+ emit marginsChanged();
+
+}
+
+qreal QmlGraphicsAnchors::horizontalCenterOffset() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->hCenterOffset;
+}
+
+void QmlGraphicsAnchors::setHorizontalCenterOffset(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->hCenterOffset == offset)
+ return;
+ d->hCenterOffset = offset;
+ if(d->centerIn)
+ d->centerInChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit horizontalCenterOffsetChanged();
+}
+
+qreal QmlGraphicsAnchors::topMargin() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->topMargin;
+}
+
+void QmlGraphicsAnchors::setTopMargin(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->topMargin == offset)
+ return;
+ d->topMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateVerticalAnchors();
+ emit topMarginChanged();
+}
+
+qreal QmlGraphicsAnchors::bottomMargin() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->bottomMargin;
+}
+
+void QmlGraphicsAnchors::setBottomMargin(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->bottomMargin == offset)
+ return;
+ d->bottomMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateVerticalAnchors();
+ emit bottomMarginChanged();
+}
+
+qreal QmlGraphicsAnchors::verticalCenterOffset() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->vCenterOffset;
+}
+
+void QmlGraphicsAnchors::setVerticalCenterOffset(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->vCenterOffset == offset)
+ return;
+ d->vCenterOffset = offset;
+ if(d->centerIn)
+ d->centerInChanged();
+ else
+ d->updateVerticalAnchors();
+ emit verticalCenterOffsetChanged();
+}
+
+qreal QmlGraphicsAnchors::baselineOffset() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->baselineOffset;
+}
+
+void QmlGraphicsAnchors::setBaselineOffset(qreal offset)
+{
+ Q_D(QmlGraphicsAnchors);
+ if (d->baselineOffset == offset)
+ return;
+ d->baselineOffset = offset;
+ d->updateVerticalAnchors();
+ emit baselineOffsetChanged();
+}
+
+QmlGraphicsAnchors::UsedAnchors QmlGraphicsAnchors::usedAnchors() const
+{
+ Q_D(const QmlGraphicsAnchors);
+ return d->usedAnchors;
+}
+
+bool QmlGraphicsAnchorsPrivate::checkHValid() const
+{
+ if (usedAnchors & QmlGraphicsAnchors::HasLeftAnchor &&
+ usedAnchors & QmlGraphicsAnchors::HasRightAnchor &&
+ usedAnchors & QmlGraphicsAnchors::HasHCenterAnchor) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't specify left, right, and hcenter anchors.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QmlGraphicsAnchorsPrivate::checkHAnchorValid(QmlGraphicsAnchorLine anchor) const
+{
+ if (!anchor.item) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor to a null item.");
+ return false;
+ } else if (anchor.anchorLine & QmlGraphicsAnchorLine::Vertical_Mask) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor a horizontal edge to a vertical edge.");
+ return false;
+ } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor to an item that isn't a parent or sibling.");
+ return false;
+ } else if (anchor.item == item) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor item to self.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QmlGraphicsAnchorsPrivate::checkVValid() const
+{
+ if (usedAnchors & QmlGraphicsAnchors::HasTopAnchor &&
+ usedAnchors & QmlGraphicsAnchors::HasBottomAnchor &&
+ usedAnchors & QmlGraphicsAnchors::HasVCenterAnchor) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't specify top, bottom, and vcenter anchors.");
+ return false;
+ } else if (usedAnchors & QmlGraphicsAnchors::HasBaselineAnchor &&
+ (usedAnchors & QmlGraphicsAnchors::HasTopAnchor ||
+ usedAnchors & QmlGraphicsAnchors::HasBottomAnchor ||
+ usedAnchors & QmlGraphicsAnchors::HasVCenterAnchor)) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QmlGraphicsAnchorsPrivate::checkVAnchorValid(QmlGraphicsAnchorLine anchor) const
+{
+ if (!anchor.item) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor to a null item.");
+ return false;
+ } else if (anchor.anchorLine & QmlGraphicsAnchorLine::Horizontal_Mask) {
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor a vertical edge to a horizontal edge.");
+ return false;
+ } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor to an item that isn't a parent or sibling.");
+ return false;
+ } else if (anchor.item == item){
+ qmlInfo(item) << QmlGraphicsAnchors::tr("Can't anchor item to self.");
+ return false;
+ }
+
+ return true;
+}
+
+#include <moc_qmlgraphicsanchors_p.cpp>
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors_p.h b/src/declarative/graphicsitems/qmlgraphicsanchors_p.h
new file mode 100644
index 0000000..5a8f8c1
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsanchors_p.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSANCHORS_H
+#define QMLGRAPHICSANCHORS_H
+
+#include "qmlgraphicsitem.h"
+
+#include <qml.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsAnchorsPrivate;
+class QmlGraphicsAnchorLine;
+class Q_DECLARATIVE_EXPORT QmlGraphicsAnchors : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlGraphicsAnchorLine left READ left WRITE setLeft RESET resetLeft NOTIFY leftChanged)
+ Q_PROPERTY(QmlGraphicsAnchorLine right READ right WRITE setRight RESET resetRight NOTIFY rightChanged)
+ Q_PROPERTY(QmlGraphicsAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter NOTIFY horizontalCenterChanged)
+ Q_PROPERTY(QmlGraphicsAnchorLine top READ top WRITE setTop RESET resetTop NOTIFY topChanged)
+ Q_PROPERTY(QmlGraphicsAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom NOTIFY bottomChanged)
+ Q_PROPERTY(QmlGraphicsAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter NOTIFY verticalCenterChanged)
+ Q_PROPERTY(QmlGraphicsAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline NOTIFY baselineChanged)
+ Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged())
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged())
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged())
+ Q_PROPERTY(QmlGraphicsItem *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged)
+ Q_PROPERTY(QmlGraphicsItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged)
+
+public:
+ QmlGraphicsAnchors(QObject *parent=0);
+ QmlGraphicsAnchors(QmlGraphicsItem *item, QObject *parent=0);
+ virtual ~QmlGraphicsAnchors();
+
+ enum UsedAnchor {
+ HasLeftAnchor = 0x01,
+ HasRightAnchor = 0x02,
+ HasTopAnchor = 0x04,
+ HasBottomAnchor = 0x08,
+ HasHCenterAnchor = 0x10,
+ HasVCenterAnchor = 0x20,
+ HasBaselineAnchor = 0x40,
+ Horizontal_Mask = HasLeftAnchor | HasRightAnchor | HasHCenterAnchor,
+ Vertical_Mask = HasTopAnchor | HasBottomAnchor | HasVCenterAnchor | HasBaselineAnchor
+ };
+ Q_DECLARE_FLAGS(UsedAnchors, UsedAnchor)
+
+ QmlGraphicsAnchorLine left() const;
+ void setLeft(const QmlGraphicsAnchorLine &edge);
+ void resetLeft();
+
+ QmlGraphicsAnchorLine right() const;
+ void setRight(const QmlGraphicsAnchorLine &edge);
+ void resetRight();
+
+ QmlGraphicsAnchorLine horizontalCenter() const;
+ void setHorizontalCenter(const QmlGraphicsAnchorLine &edge);
+ void resetHorizontalCenter();
+
+ QmlGraphicsAnchorLine top() const;
+ void setTop(const QmlGraphicsAnchorLine &edge);
+ void resetTop();
+
+ QmlGraphicsAnchorLine bottom() const;
+ void setBottom(const QmlGraphicsAnchorLine &edge);
+ void resetBottom();
+
+ QmlGraphicsAnchorLine verticalCenter() const;
+ void setVerticalCenter(const QmlGraphicsAnchorLine &edge);
+ void resetVerticalCenter();
+
+ QmlGraphicsAnchorLine baseline() const;
+ void setBaseline(const QmlGraphicsAnchorLine &edge);
+ void resetBaseline();
+
+ qreal leftMargin() const;
+ void setLeftMargin(qreal);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal);
+
+ qreal horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(qreal);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal);
+
+ qreal margins() const;
+ void setMargins(qreal);
+
+ qreal verticalCenterOffset() const;
+ void setVerticalCenterOffset(qreal);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);
+
+ QmlGraphicsItem *fill() const;
+ void setFill(QmlGraphicsItem *);
+ void resetFill();
+
+ QmlGraphicsItem *centerIn() const;
+ void setCenterIn(QmlGraphicsItem *);
+ void resetCenterIn();
+
+ UsedAnchors usedAnchors() const;
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void leftChanged();
+ void rightChanged();
+ void topChanged();
+ void bottomChanged();
+ void verticalCenterChanged();
+ void horizontalCenterChanged();
+ void baselineChanged();
+ void fillChanged();
+ void centerInChanged();
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void marginsChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+ void baselineOffsetChanged();
+
+private:
+ friend class QmlGraphicsItem;
+ Q_DISABLE_COPY(QmlGraphicsAnchors)
+ Q_DECLARE_PRIVATE(QmlGraphicsAnchors)
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlGraphicsAnchors::UsedAnchors)
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsAnchors)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h
new file mode 100644
index 0000000..5b02158
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSANCHORS_P_H
+#define QMLGRAPHICSANCHORS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsanchors_p.h"
+#include "qmlgraphicsitemchangelistener_p.h"
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsAnchorLine
+{
+public:
+ QmlGraphicsAnchorLine() : item(0), anchorLine(Invalid)
+ {
+ }
+
+ enum AnchorLine {
+ Invalid = 0x0,
+ Left = 0x01,
+ Right = 0x02,
+ Top = 0x04,
+ Bottom = 0x08,
+ HCenter = 0x10,
+ VCenter = 0x20,
+ Baseline = 0x40,
+ Horizontal_Mask = Left | Right | HCenter,
+ Vertical_Mask = Top | Bottom | VCenter | Baseline
+ };
+
+ QmlGraphicsItem *item;
+ AnchorLine anchorLine;
+
+ bool operator==(const QmlGraphicsAnchorLine& other) const
+ {
+ return item == other.item && anchorLine == other.anchorLine;
+ }
+};
+Q_DECLARE_METATYPE(QmlGraphicsAnchorLine)
+
+
+
+class QmlGraphicsAnchorsPrivate : public QObjectPrivate, public QmlGraphicsItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsAnchors)
+public:
+ QmlGraphicsAnchorsPrivate(QmlGraphicsItem *i)
+ : updatingMe(false), updatingHorizontalAnchor(0),
+ updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0),
+ centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
+ margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0),
+ componentComplete(true)
+ {
+ }
+
+ void init()
+ {
+ }
+
+ void clearItem(QmlGraphicsItem *);
+
+ void addDepend(QmlGraphicsItem *);
+ void remDepend(QmlGraphicsItem *);
+ bool isItemComplete() const;
+
+ bool updatingMe;
+ int updatingHorizontalAnchor;
+ int updatingVerticalAnchor;
+ int updatingFill;
+ int updatingCenterIn;
+
+ void setItemHeight(qreal);
+ void setItemWidth(qreal);
+ void setItemX(qreal);
+ void setItemY(qreal);
+ void setItemPos(const QPointF &);
+
+ void updateOnComplete();
+ void updateMe();
+
+ // QmlGraphicsItemGeometryListener interface
+ void itemGeometryChanged(QmlGraphicsItem *, const QRectF &, const QRectF &);
+ QmlGraphicsAnchorsPrivate *anchorPrivate() { return this; }
+
+ bool checkHValid() const;
+ bool checkVValid() const;
+ bool checkHAnchorValid(QmlGraphicsAnchorLine anchor) const;
+ bool checkVAnchorValid(QmlGraphicsAnchorLine anchor) const;
+ bool calcStretch(const QmlGraphicsAnchorLine &edge1, const QmlGraphicsAnchorLine &edge2, int offset1, int offset2, QmlGraphicsAnchorLine::AnchorLine line, int &stretch);
+
+ void updateHorizontalAnchors();
+ void updateVerticalAnchors();
+ void fillChanged();
+ void centerInChanged();
+
+ QmlGraphicsItem *item;
+ QmlGraphicsAnchors::UsedAnchors usedAnchors;
+
+ QmlGraphicsItem *fill;
+ QmlGraphicsItem *centerIn;
+
+ QmlGraphicsAnchorLine left;
+ QmlGraphicsAnchorLine right;
+ QmlGraphicsAnchorLine top;
+ QmlGraphicsAnchorLine bottom;
+ QmlGraphicsAnchorLine vCenter;
+ QmlGraphicsAnchorLine hCenter;
+ QmlGraphicsAnchorLine baseline;
+
+ qreal leftMargin;
+ qreal rightMargin;
+ qreal topMargin;
+ qreal bottomMargin;
+ qreal margins;
+ qreal vCenterOffset;
+ qreal hCenterOffset;
+ qreal baselineOffset;
+
+ bool componentComplete;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsanimatedimage.cpp b/src/declarative/graphicsitems/qmlgraphicsanimatedimage.cpp
new file mode 100644
index 0000000..e01e569
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsanimatedimage.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsanimatedimage_p.h"
+#include "qmlgraphicsanimatedimage_p_p.h"
+
+#include <qmlengine.h>
+
+#include <QMovie>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlGraphicsAnimatedImage
+ \internal
+*/
+
+/*!
+ \qmlclass AnimatedImage QmlGraphicsAnimatedImage
+ \inherits Image
+
+ This item provides for playing animations stored as images containing a series of frames,
+ such as GIF files. The full list of supported formats can be determined with
+ QMovie::supportedFormats().
+
+ \table
+ \row
+ \o \image animatedimageitem.gif
+ \o
+ \qml
+Item {
+ width: anim.width; height: anim.height+8
+ AnimatedImage { id: anim; source: "pics/games-anim.gif" }
+ Rectangle { color: "red"; width: 4; height: 8; y: anim.height
+ x: (anim.width-width)*anim.currentFrame/(anim.frameCount-1)
+ }
+}
+ \endqml
+ \endtable
+*/
+QML_DEFINE_TYPE(Qt,4,6,AnimatedImage,QmlGraphicsAnimatedImage)
+
+QmlGraphicsAnimatedImage::QmlGraphicsAnimatedImage(QmlGraphicsItem *parent)
+ : QmlGraphicsImage(*(new QmlGraphicsAnimatedImagePrivate), parent)
+{
+}
+
+QmlGraphicsAnimatedImage::~QmlGraphicsAnimatedImage()
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ delete d->_movie;
+}
+
+/*!
+ \qmlproperty bool AnimatedImage::paused
+ This property holds whether the animated image is paused or not
+
+ Defaults to false, and can be set to true when you want to pause.
+*/
+bool QmlGraphicsAnimatedImage::isPaused() const
+{
+ Q_D(const QmlGraphicsAnimatedImage);
+ if(!d->_movie)
+ return false;
+ return d->_movie->state()==QMovie::Paused;
+}
+
+void QmlGraphicsAnimatedImage::setPaused(bool pause)
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ if(pause == d->paused)
+ return;
+ d->paused = pause;
+ if(!d->_movie)
+ return;
+ d->_movie->setPaused(pause);
+}
+/*!
+ \qmlproperty bool AnimatedImage::playing
+ This property holds whether the animated image is playing or not
+
+ Defaults to true, so as to start playing immediately.
+*/
+bool QmlGraphicsAnimatedImage::isPlaying() const
+{
+ Q_D(const QmlGraphicsAnimatedImage);
+ if (!d->_movie)
+ return false;
+ return d->_movie->state()!=QMovie::NotRunning;
+}
+
+void QmlGraphicsAnimatedImage::setPlaying(bool play)
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ if(play == d->playing)
+ return;
+ d->playing = play;
+ if (!d->_movie)
+ return;
+ if (play)
+ d->_movie->start();
+ else
+ d->_movie->stop();
+}
+
+/*!
+ \qmlproperty int AnimatedImage::currentFrame
+ \qmlproperty int AnimatedImage::frameCount
+
+ currentFrame is the frame that is currently visible. Watching when this changes can
+ allow other things to animate at the same time as the image. frameCount is the number
+ of frames in the animation. For some animation formats, frameCount is unknown and set to zero.
+*/
+int QmlGraphicsAnimatedImage::currentFrame() const
+{
+ Q_D(const QmlGraphicsAnimatedImage);
+ if (!d->_movie)
+ return d->preset_currentframe;
+ return d->_movie->currentFrameNumber();
+}
+
+void QmlGraphicsAnimatedImage::setCurrentFrame(int frame)
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ if (!d->_movie) {
+ d->preset_currentframe = frame;
+ return;
+ }
+ d->_movie->jumpToFrame(frame);
+}
+
+int QmlGraphicsAnimatedImage::frameCount() const
+{
+ Q_D(const QmlGraphicsAnimatedImage);
+ if (!d->_movie)
+ return 0;
+ return d->_movie->frameCount();
+}
+
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+void QmlGraphicsAnimatedImage::setSource(const QUrl &url)
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ if (url == d->url)
+ return;
+
+ delete d->_movie;
+ d->_movie = 0;
+
+ if (d->reply) {
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+
+ d->url = url;
+
+ if (url.isEmpty()) {
+ delete d->_movie;
+ d->status = Null;
+ } else {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ //### should be unified with movieRequestFinished
+ d->_movie = new QMovie(lf);
+ if (!d->_movie->isValid()){
+ qWarning() << "Error Reading Animated Image File" << d->url;
+ delete d->_movie;
+ d->_movie = 0;
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SLOT(playingStatusChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ if(d->playing)
+ d->_movie->start();
+ else
+ d->_movie->jumpToFrame(0);
+ if(d->paused)
+ d->_movie->setPaused(true);
+ d->setPixmap(d->_movie->currentPixmap());
+ d->status = Ready;
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit progressChanged(d->progress);
+ return;
+ }
+#endif
+ d->status = Loading;
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ d->reply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(movieRequestFinished()));
+ }
+
+ emit statusChanged(d->status);
+}
+
+void QmlGraphicsAnimatedImage::movieRequestFinished()
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ d->_movie = new QMovie(d->reply);
+ if (!d->_movie->isValid()){
+ qWarning() << "Error Reading Animated Image File " << d->url;
+ delete d->_movie;
+ d->_movie = 0;
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SLOT(playingStatusChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ if(d->playing)
+ d->_movie->start();
+ if (d->paused || !d->playing) {
+ d->_movie->jumpToFrame(d->preset_currentframe);
+ d->preset_currentframe = 0;
+ }
+ if(d->paused)
+ d->_movie->setPaused(true);
+ d->setPixmap(d->_movie->currentPixmap());
+}
+
+void QmlGraphicsAnimatedImage::movieUpdate()
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ d->setPixmap(d->_movie->currentPixmap());
+ emit frameChanged();
+}
+
+void QmlGraphicsAnimatedImage::playingStatusChanged()
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ if((d->_movie->state() != QMovie::NotRunning) != d->playing){
+ d->playing = (d->_movie->state() != QMovie::NotRunning);
+ emit playingChanged();
+ }
+ if((d->_movie->state() == QMovie::Paused) != d->paused){
+ d->playing = (d->_movie->state() == QMovie::Paused);
+ emit pausedChanged();
+ }
+}
+
+void QmlGraphicsAnimatedImage::componentComplete()
+{
+ Q_D(QmlGraphicsAnimatedImage);
+ if (!d->reply) {
+ setCurrentFrame(d->preset_currentframe);
+ d->preset_currentframe = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsanimatedimage_p.h b/src/declarative/graphicsitems/qmlgraphicsanimatedimage_p.h
new file mode 100644
index 0000000..a837702
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsanimatedimage_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSANIMATEDIMAGE_H
+#define QMLGRAPHICSANIMATEDIMAGE_H
+
+#include "qmlgraphicsimage_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QMovie;
+class QmlGraphicsAnimatedImagePrivate;
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsAnimatedImage : public QmlGraphicsImage
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged)
+ Q_PROPERTY(int frameCount READ frameCount)
+public:
+ QmlGraphicsAnimatedImage(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsAnimatedImage();
+
+ bool isPlaying() const;
+ void setPlaying(bool play);
+
+ bool isPaused() const;
+ void setPaused(bool pause);
+
+ int currentFrame() const;
+ void setCurrentFrame(int frame);
+
+ int frameCount() const;
+
+ // Extends QmlGraphicsImage's src property*/
+ virtual void setSource(const QUrl&);
+
+Q_SIGNALS:
+ void playingChanged();
+ void pausedChanged();
+ void frameChanged();
+
+private Q_SLOTS:
+ void movieUpdate();
+ void movieRequestFinished();
+ void playingStatusChanged();
+
+protected:
+ void componentComplete();
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsAnimatedImage)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsAnimatedImage)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsAnimatedImage)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsanimatedimage_p_p.h b/src/declarative/graphicsitems/qmlgraphicsanimatedimage_p_p.h
new file mode 100644
index 0000000..0d1c749
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsanimatedimage_p_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSANIMATEDIMAGE_P_H
+#define QMLGRAPHICSANIMATEDIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsimage_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMovie;
+class QNetworkReply;
+
+class QmlGraphicsAnimatedImagePrivate : public QmlGraphicsImagePrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsAnimatedImage)
+
+public:
+ QmlGraphicsAnimatedImagePrivate()
+ : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0)
+ {
+ }
+
+ bool playing;
+ bool paused;
+ int preset_currentframe;
+ QMovie *_movie;
+ QNetworkReply *reply;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSANIMATEDIMAGE_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp b/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp
new file mode 100644
index 0000000..877e141
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp
@@ -0,0 +1,409 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsborderimage_p.h"
+#include "qmlgraphicsborderimage_p_p.h"
+
+#include <qmlengine.h>
+
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,BorderImage,QmlGraphicsBorderImage)
+
+/*!
+ \qmlclass BorderImage QmlGraphicsBorderImage
+ \brief The BorderImage element provides an image that can be used as a border.
+ \inherits Item
+
+ \snippet snippets/declarative/border-image.qml 0
+
+ \image BorderImage.png
+ */
+
+/*!
+ \internal
+ \class QmlGraphicsBorderImage BorderImage
+ \brief The QmlGraphicsBorderImage class provides an image item that you can add to a QmlView.
+*/
+
+QmlGraphicsBorderImage::QmlGraphicsBorderImage(QmlGraphicsItem *parent)
+ : QmlGraphicsImageBase(*(new QmlGraphicsBorderImagePrivate), parent)
+{
+}
+
+QmlGraphicsBorderImage::~QmlGraphicsBorderImage()
+{
+ Q_D(QmlGraphicsBorderImage);
+ if (d->sciReply)
+ d->sciReply->deleteLater();
+ if (d->sciPendingPixmapCache)
+ QmlPixmapCache::cancel(d->sciurl, this);
+}
+/*!
+ \qmlproperty enum BorderImage::status
+
+ This property holds the status of image loading. It can be one of:
+ \list
+ \o Null - no image has been set
+ \o Ready - the image has been loaded
+ \o Loading - the image is currently being loaded
+ \o Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real BorderImage::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+/*!
+ \qmlproperty bool BorderImage::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty url BorderImage::source
+
+ BorderImage can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
+
+ It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies
+ the borders, the image file and the tile rules.
+
+ The following .sci file sets the borders to 10 on each side for the image \c picture.png:
+ \qml
+ border.left: 10
+ border.top: 10
+ border.bottom: 10
+ border.right: 10
+ source: picture.png
+ \endqml
+
+ The URL may be absolute, or relative to the URL of the component.
+*/
+
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+
+void QmlGraphicsBorderImage::setSource(const QUrl &url)
+{
+ Q_D(QmlGraphicsBorderImage);
+ //equality is fairly expensive, so we bypass for simple, common case
+ if ((d->url.isEmpty() == url.isEmpty()) && url == d->url)
+ return;
+
+ if (d->sciReply) {
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ }
+
+ if (d->pendingPixmapCache) {
+ QmlPixmapCache::cancel(d->url, this);
+ d->pendingPixmapCache = false;
+ }
+ if (d->sciPendingPixmapCache) {
+ QmlPixmapCache::cancel(d->sciurl, this);
+ d->sciPendingPixmapCache = false;
+ }
+
+ d->url = url;
+ d->sciurl = QUrl();
+ if (d->progress != 0.0) {
+ d->progress = 0.0;
+ emit progressChanged(d->progress);
+ }
+
+ if (url.isEmpty()) {
+ d->pix = QPixmap();
+ d->status = Null;
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ update();
+ } else {
+ d->status = Loading;
+ if (d->url.path().endsWith(QLatin1String(".sci"))) {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = toLocalFileOrQrc(d->url);
+ if (!lf.isEmpty()) {
+ QFile file(lf);
+ file.open(QIODevice::ReadOnly);
+ setGridScaledImage(QmlGraphicsGridScaledImage(&file));
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->sciReply, SIGNAL(finished()),
+ this, SLOT(sciRequestFinished()));
+ }
+ } else {
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->pix);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url);
+ d->pendingPixmapCache = true;
+ connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
+ connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ //### should be unified with requestFinished
+ setImplicitWidth(d->pix.width());
+ setImplicitHeight(d->pix.height());
+
+ if (d->pix.isNull())
+ d->status = Error;
+ if (d->status == Loading)
+ d->status = Ready;
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit progressChanged(d->progress);
+ update();
+ }
+ }
+ }
+
+ emit statusChanged(d->status);
+}
+
+/*!
+ \qmlproperty int BorderImage::border.left
+ \qmlproperty int BorderImage::border.right
+ \qmlproperty int BorderImage::border.top
+ \qmlproperty int BorderImage::border.bottom
+
+ \target ImagexmlpropertiesscaleGrid
+
+ The 4 border lines (2 horizontal and 2 vertical) break an image into 9 sections, as shown below:
+
+ \image declarative-scalegrid.png
+
+ When the image is scaled:
+ \list
+ \i the corners (sections 1, 3, 7, and 9) are not scaled at all
+ \i the middle (section 5) is scaled according to BorderImage::horizontalTileMode and BorderImage::verticalTileMode
+ \i sections 2 and 8 are scaled according to BorderImage::horizontalTileMode
+ \i sections 4 and 6 are scaled according to BorderImage::verticalTileMode
+ \endlist
+
+ Each border line (left, right, top, and bottom) specifies an offset from the respective side. For example, \c{border.bottom: 10} sets the bottom line 10 pixels up from the bottom of the image.
+
+ The border lines can also be specified using a
+ \l {BorderImage::source}{.sci file}.
+*/
+
+QmlGraphicsScaleGrid *QmlGraphicsBorderImage::border()
+{
+ Q_D(QmlGraphicsBorderImage);
+ return d->getScaleGrid();
+}
+
+/*!
+ \qmlproperty TileMode BorderImage::horizontalTileMode
+ \qmlproperty TileMode BorderImage::verticalTileMode
+
+ This property describes how to repeat or stretch the middle parts of the border image.
+
+ \list
+ \o Stretch - Scale the image to fit to the available area.
+ \o Repeat - Tile the image until there is no more space. May crop the last image.
+ \o Round - Like Repeat, but scales the images down to ensure that the last image is not cropped.
+ \endlist
+*/
+QmlGraphicsBorderImage::TileMode QmlGraphicsBorderImage::horizontalTileMode() const
+{
+ Q_D(const QmlGraphicsBorderImage);
+ return d->horizontalTileMode;
+}
+
+void QmlGraphicsBorderImage::setHorizontalTileMode(TileMode t)
+{
+ Q_D(QmlGraphicsBorderImage);
+ if (t != d->horizontalTileMode) {
+ d->horizontalTileMode = t;
+ emit horizontalTileModeChanged();
+ update();
+ }
+}
+
+QmlGraphicsBorderImage::TileMode QmlGraphicsBorderImage::verticalTileMode() const
+{
+ Q_D(const QmlGraphicsBorderImage);
+ return d->verticalTileMode;
+}
+
+void QmlGraphicsBorderImage::setVerticalTileMode(TileMode t)
+{
+ Q_D(QmlGraphicsBorderImage);
+ if (t != d->verticalTileMode) {
+ d->verticalTileMode = t;
+ emit verticalTileModeChanged();
+ update();
+ }
+}
+
+void QmlGraphicsBorderImage::setGridScaledImage(const QmlGraphicsGridScaledImage& sci)
+{
+ Q_D(QmlGraphicsBorderImage);
+ if (!sci.isValid()) {
+ d->status = Error;
+ emit statusChanged(d->status);
+ } else {
+ QmlGraphicsScaleGrid *sg = border();
+ sg->setTop(sci.gridTop());
+ sg->setBottom(sci.gridBottom());
+ sg->setLeft(sci.gridLeft());
+ sg->setRight(sci.gridRight());
+ d->horizontalTileMode = sci.horizontalTileRule();
+ d->verticalTileMode = sci.verticalTileRule();
+
+ d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->sciurl, &d->pix);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->sciurl);
+ d->sciPendingPixmapCache = true;
+ connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
+ connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ //### should be unified with requestFinished
+ setImplicitWidth(d->pix.width());
+ setImplicitHeight(d->pix.height());
+
+ if (d->pix.isNull())
+ d->status = Error;
+ if (d->status == Loading)
+ d->status = Ready;
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit progressChanged(1.0);
+ update();
+ }
+ }
+}
+
+void QmlGraphicsBorderImage::requestFinished()
+{
+ Q_D(QmlGraphicsBorderImage);
+
+ if (d->url.path().endsWith(QLatin1String(".sci"))) {
+ d->sciPendingPixmapCache = false;
+ QmlPixmapCache::get(d->sciurl, &d->pix);
+ } else {
+ d->pendingPixmapCache = false;
+ if (QmlPixmapCache::get(d->url, &d->pix) != QmlPixmapReply::Ready)
+ d->status = Error;
+ }
+ setImplicitWidth(d->pix.width());
+ setImplicitHeight(d->pix.height());
+
+ if (d->status == Loading)
+ d->status = Ready;
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit progressChanged(1.0);
+ update();
+}
+
+void QmlGraphicsBorderImage::sciRequestFinished()
+{
+ Q_D(QmlGraphicsBorderImage);
+ if (d->sciReply->error() != QNetworkReply::NoError) {
+ d->status = Error;
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ emit statusChanged(d->status);
+ } else {
+ QmlGraphicsGridScaledImage sci(d->sciReply);
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ setGridScaledImage(sci);
+ }
+}
+
+void QmlGraphicsBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QmlGraphicsBorderImage);
+ if (d->pix.isNull())
+ return;
+
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+
+ const QmlGraphicsScaleGrid *border = d->getScaleGrid();
+ QMargins margins(border->left(), border->top(), border->right(), border->bottom());
+ QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode);
+ qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, d->pix, d->pix.rect(), margins, rules);
+ if (d->smooth) {
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsborderimage_p.h b/src/declarative/graphicsitems/qmlgraphicsborderimage_p.h
new file mode 100644
index 0000000..cf3c518
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsborderimage_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSBORDERIMAGE_H
+#define QMLGRAPHICSBORDERIMAGE_H
+
+#include "qmlgraphicsimagebase_p.h"
+
+#include <QtNetwork/qnetworkreply.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsScaleGrid;
+class QmlGraphicsGridScaledImage;
+class QmlGraphicsBorderImagePrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsBorderImage : public QmlGraphicsImageBase
+{
+ Q_OBJECT
+ Q_ENUMS(TileMode)
+
+ Q_PROPERTY(QmlGraphicsScaleGrid *border READ border CONSTANT)
+ Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
+ Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
+
+public:
+ QmlGraphicsBorderImage(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsBorderImage();
+
+ QmlGraphicsScaleGrid *border();
+
+ enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
+
+ TileMode horizontalTileMode() const;
+ void setHorizontalTileMode(TileMode);
+
+ TileMode verticalTileMode() const;
+ void setVerticalTileMode(TileMode);
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ void setSource(const QUrl &url);
+
+Q_SIGNALS:
+ void horizontalTileModeChanged();
+ void verticalTileModeChanged();
+
+private:
+ void setGridScaledImage(const QmlGraphicsGridScaledImage& sci);
+
+private Q_SLOTS:
+ void requestFinished();
+ void sciRequestFinished();
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsBorderImage)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsBorderImage)
+};
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QmlGraphicsBorderImage)
+QT_END_HEADER
+
+#endif // QMLGRAPHICSBORDERIMAGE_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsborderimage_p_p.h b/src/declarative/graphicsitems/qmlgraphicsborderimage_p_p.h
new file mode 100644
index 0000000..51ebb02
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsborderimage_p_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSBORDERIMAGE_P_H
+#define QMLGRAPHICSBORDERIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsimagebase_p_p.h"
+#include "qmlgraphicsscalegrid_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+class QmlGraphicsBorderImagePrivate : public QmlGraphicsImageBasePrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsBorderImage)
+
+public:
+ QmlGraphicsBorderImagePrivate()
+ : border(0), sciReply(0),
+ sciPendingPixmapCache(false),
+ horizontalTileMode(QmlGraphicsBorderImage::Stretch),
+ verticalTileMode(QmlGraphicsBorderImage::Stretch)
+ {
+ }
+
+ ~QmlGraphicsBorderImagePrivate()
+ {
+ }
+
+ QmlGraphicsScaleGrid *getScaleGrid()
+ {
+ Q_Q(QmlGraphicsBorderImage);
+ if (!border)
+ border = new QmlGraphicsScaleGrid(q);
+ return border;
+ }
+
+ QmlGraphicsScaleGrid *border;
+ QUrl sciurl;
+ QNetworkReply *sciReply;
+ bool sciPendingPixmapCache;
+ QmlGraphicsBorderImage::TileMode horizontalTileMode;
+ QmlGraphicsBorderImage::TileMode verticalTileMode;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSBORDERIMAGE_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicseffects.cpp b/src/declarative/graphicsitems/qmlgraphicseffects.cpp
new file mode 100644
index 0000000..e1f5687
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicseffects.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qml.h>
+
+#include <QtGui/qgraphicseffect.h>
+
+QML_DECLARE_TYPE(QGraphicsEffect)
+QML_DEFINE_NOCREATE_TYPE(QGraphicsEffect)
+
+QML_DECLARE_TYPE(QGraphicsBlurEffect)
+QML_DEFINE_TYPE(Qt,4,6,Blur,QGraphicsBlurEffect)
+
+/*!
+ \qmlclass Blur QGraphicsBlurEffect
+ \brief The Blur object provides a blur effect.
+
+ A blur effect blurs the source item. This effect is useful for reducing details;
+ for example, when the a source loses focus and attention should be drawn to other
+ elements. Use blurRadius to control the level of detail and blurHint to control
+ the quality of the blur.
+
+ By default, the blur radius is 5 pixels.
+
+ \img graphicseffect-blur.png
+*/
+
+/*!
+ \qmlproperty real Blur::blurRadius
+
+ This controls how blurry an item will appear.
+
+ A smaller radius produces a sharper appearance, and a larger radius produces
+ a more blurred appearance.
+
+ The default radius is 5 pixels.
+*/
+/*!
+ \qmlproperty enumeration Blur::blurHint
+
+ Use Qt.PerformanceHint to specify a faster blur or Qt.QualityHint hint
+ to specify a higher quality blur.
+
+ If the blur radius is animated, it is recommended you use Qt.PerformanceHint.
+
+ The default hint is Qt.PerformanceHint.
+*/
+
+QML_DECLARE_TYPE(QGraphicsColorizeEffect)
+QML_DEFINE_TYPE(Qt,4,6,Colorize,QGraphicsColorizeEffect)
+
+/*!
+ \qmlclass Colorize QGraphicsColorizeEffect
+ \brief The Colorize object provides a colorize effect.
+
+ A colorize effect renders the source item with a tint of its color.
+
+ By default, the color is light blue.
+
+ \img graphicseffect-colorize.png
+*/
+
+/*!
+ \qmlproperty color Colorize::color
+ The color of the effect.
+
+ By default, the color is light blue.
+*/
+
+/*!
+ \qmlproperty real Colorize::strength
+
+ To what extent the source item is "colored". A strength of 0.0 is equal to no effect,
+ while 1.0 means full colorization. By default, the strength is 1.0.
+*/
+
+QML_DECLARE_TYPE(QGraphicsDropShadowEffect)
+QML_DEFINE_TYPE(Qt,4,6,DropShadow,QGraphicsDropShadowEffect)
+
+/*!
+ \qmlclass DropShadow QGraphicsDropShadowEffect
+ \brief The DropShadow object provides a drop shadow effect.
+
+ A drop shadow effect renders the source item with a drop shadow. The color of
+ the drop shadow can be modified using the color property. The drop
+ shadow offset can be modified using the xOffset and yOffset properties and the blur
+ radius of the drop shadow can be changed with the blurRadius property.
+
+ By default, the drop shadow is a semi-transparent dark gray shadow,
+ blurred with a radius of 1 at an offset of 8 pixels towards the lower right.
+
+ \img graphicseffect-drop-shadow.png
+*/
+
+/*!
+ \qmlproperty real DropShadow::xOffset
+ \qmlproperty real DropShadow::yOffset
+ The shadow offset in pixels.
+
+ By default, xOffset and yOffset are 8 pixels.
+*/
+
+/*!
+ \qmlproperty real DropShadow::blurRadius
+ The blur radius in pixels of the drop shadow.
+
+ Using a smaller radius results in a sharper shadow, whereas using a bigger
+ radius results in a more blurred shadow.
+
+ By default, the blur radius is 1 pixel.
+*/
+
+/*!
+ \qmlproperty color DropShadow::color
+ The color of the drop shadow.
+
+ By default, the drop color is a semi-transparent dark gray.
+*/
+
+QML_DECLARE_TYPE(QGraphicsOpacityEffect)
+QML_DEFINE_TYPE(Qt,4,6,Opacity,QGraphicsOpacityEffect)
+
+/*!
+ \qmlclass Opacity QGraphicsOpacityEffect
+ \brief The Opacity object provides an opacity effect.
+
+ An opacity effect renders the source with an opacity. This effect is useful
+ for making the source semi-transparent, similar to a fade-in/fade-out
+ sequence. The opacity can be modified using the opacity property.
+
+ By default, the opacity is 0.7.
+
+ \img graphicseffect-opacity.png
+*/
+
+/*!
+ \qmlproperty real Opacity::opacity
+ This property specifies how opaque an item should appear.
+
+ The value should be in the range of 0.0 to 1.0, where 0.0 is
+ fully transparent and 1.0 is fully opaque.
+
+ By default, the opacity is 0.7.
+*/
+
diff --git a/src/declarative/graphicsitems/qmlgraphicsevents.cpp b/src/declarative/graphicsitems/qmlgraphicsevents.cpp
new file mode 100644
index 0000000..9958dea
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsevents.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsevents_p_p.h"
+
+QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass KeyEvent QmlGraphicsKeyEvent
+ \brief The KeyEvent object provides information about a key event.
+
+ For example, the following changes the Item's state property when the Enter
+ key is pressed:
+ \qml
+Item {
+ focus: true
+ Keys.onPressed: { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; }
+}
+ \endqml
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsKeyEvent
+*/
+
+/*!
+ \qmlproperty int KeyEvent::key
+
+ This property holds the code of the key that was pressed or released.
+
+ See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are
+ independent of the underlying window system. Note that this
+ function does not distinguish between capital and non-capital
+ letters, use the text() function (returning the Unicode text the
+ key generated) for this purpose.
+
+ A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not
+ the result of a known key; for example, it may be the result of
+ a compose sequence, a keyboard macro, or due to key event
+ compression.
+*/
+
+/*!
+ \qmlproperty string KeyEvent::text
+
+ This property holds the Unicode text that the key generated.
+ The text returned can be an empty string in cases where modifier keys,
+ such as Shift, Control, Alt, and Meta, are being pressed or released.
+ In such cases \c key will contain a valid value
+*/
+
+/*!
+ \qmlproperty bool KeyEvent::isAutoRepeat
+
+ This property holds whether this event comes from an auto-repeating key.
+*/
+
+/*!
+ \qmlproperty int KeyEvent::count
+
+ This property holds the number of keys involved in this event. If \l KeyEvent::text
+ is not empty, this is simply the length of the string.
+*/
+
+/*!
+ \qmlproperty bool KeyEvent::accepted
+
+ Setting \a accepted to true prevents the key event from being
+ propagated to the item's parent.
+
+ Generally, if the item acts on the key event then it should be accepted
+ so that ancestor items do not also respond to the same event.
+*/
+
+
+/*!
+ \qmlclass MouseEvent QmlGraphicsMouseEvent
+ \brief The MouseEvent object provides information about a mouse event.
+
+ The position of the mouse can be found via the x and y properties.
+ The button that caused the event is available via the button property.
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsMouseEvent
+*/
+
+/*!
+ \qmlproperty int MouseEvent::x
+ \qmlproperty int MouseEvent::y
+
+ These properties hold the position of the mouse event.
+*/
+
+/*!
+ \qmlproperty enum MouseEvent::button
+
+ This property holds the button that caused the event. It can be one of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MidButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty bool MouseEvent::wasHeld
+
+ This property is true if the mouse button has been held pressed longer the
+ threshold (800ms).
+*/
+
+/*!
+ \qmlproperty int MouseEvent::buttons
+
+ This property holds the mouse buttons pressed when the event was generated.
+ For mouse move events, this is all buttons that are pressed down. For mouse
+ press and double click events this includes the button that caused the event.
+ For mouse release events this excludes the button that caused the event.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MidButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty int MouseEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Left mouse button click:
+ \qml
+MouseRegion {
+ onClicked: { if (mouse.button == Qt.LeftButton && mouse.modifiers & Qt.ShiftModifier) doSomething(); }
+}
+ \endqml
+*/
+
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsKeyEvent)
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsMouseEvent)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsevents_p_p.h b/src/declarative/graphicsitems/qmlgraphicsevents_p_p.h
new file mode 100644
index 0000000..b07fd88
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsevents_p_p.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSEVENTS_P_H
+#define QMLGRAPHICSEVENTS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsKeyEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key)
+ Q_PROPERTY(QString text READ text)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QmlGraphicsKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
+ : event(type, key, modifiers, text, autorep, count) { event.setAccepted(false); }
+ QmlGraphicsKeyEvent(const QKeyEvent &ke)
+ : event(ke) { event.setAccepted(false); }
+
+ int key() const { return event.key(); }
+ QString text() const { return event.text(); }
+ int modifiers() const { return event.modifiers(); }
+ bool isAutoRepeat() const { return event.isAutoRepeat(); }
+ int count() const { return event.count(); }
+
+ bool isAccepted() { return event.isAccepted(); }
+ void setAccepted(bool accepted) { event.setAccepted(accepted); }
+
+private:
+ QKeyEvent event;
+};
+
+class QmlGraphicsMouseEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x)
+ Q_PROPERTY(int y READ y)
+ Q_PROPERTY(int button READ button)
+ Q_PROPERTY(int buttons READ buttons)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool wasHeld READ wasHeld)
+ Q_PROPERTY(bool isClick READ isClick)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QmlGraphicsMouseEvent(int x, int y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers
+ , bool isClick=false, bool wasHeld=false)
+ : _x(x), _y(y), _button(button), _buttons(buttons), _modifiers(modifiers)
+ , _wasHeld(wasHeld), _isClick(isClick), _accepted(true) {}
+
+ int x() const { return _x; }
+ int y() const { return _y; }
+ int button() const { return _button; }
+ int buttons() const { return _buttons; }
+ int modifiers() const { return _modifiers; }
+ bool wasHeld() const { return _wasHeld; }
+ bool isClick() const { return _isClick; }
+
+ bool isAccepted() { return _accepted; }
+ void setAccepted(bool accepted) { _accepted = accepted; }
+
+private:
+ int _x;
+ int _y;
+ Qt::MouseButton _button;
+ Qt::MouseButtons _buttons;
+ Qt::KeyboardModifiers _modifiers;
+ bool _wasHeld;
+ bool _isClick;
+ bool _accepted;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsKeyEvent)
+QML_DECLARE_TYPE(QmlGraphicsMouseEvent)
+
+#endif // QMLGRAPHICSEVENTS_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
new file mode 100644
index 0000000..2ff3b30
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
@@ -0,0 +1,1374 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsflickable_p.h"
+#include "qmlgraphicsflickable_p_p.h"
+
+#include <QGraphicsSceneMouseEvent>
+#include <QPointer>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+
+// FlickThreshold determines how far the "mouse" must have moved
+// before we perform a flick.
+static const int FlickThreshold = 20;
+
+// Really slow flicks can be annoying.
+static const int minimumFlickVelocity = 200;
+
+class QmlGraphicsFlickableVisibleArea : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal xPosition READ xPosition NOTIFY pageChanged)
+ Q_PROPERTY(qreal yPosition READ yPosition NOTIFY pageChanged)
+ Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY pageChanged)
+ Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY pageChanged)
+
+public:
+ QmlGraphicsFlickableVisibleArea(QmlGraphicsFlickable *parent=0);
+
+ qreal xPosition() const;
+ qreal widthRatio() const;
+ qreal yPosition() const;
+ qreal heightRatio() const;
+
+ void updateVisible();
+
+signals:
+ void pageChanged();
+
+private:
+ QmlGraphicsFlickable *flickable;
+ qreal m_xPosition;
+ qreal m_widthRatio;
+ qreal m_yPosition;
+ qreal m_heightRatio;
+};
+
+QmlGraphicsFlickableVisibleArea::QmlGraphicsFlickableVisibleArea(QmlGraphicsFlickable *parent)
+ : QObject(parent), flickable(parent), m_xPosition(0.), m_widthRatio(0.)
+ , m_yPosition(0.), m_heightRatio(0.)
+{
+}
+
+qreal QmlGraphicsFlickableVisibleArea::widthRatio() const
+{
+ return m_widthRatio;
+}
+
+qreal QmlGraphicsFlickableVisibleArea::xPosition() const
+{
+ return m_xPosition;
+}
+
+qreal QmlGraphicsFlickableVisibleArea::heightRatio() const
+{
+ return m_heightRatio;
+}
+
+qreal QmlGraphicsFlickableVisibleArea::yPosition() const
+{
+ return m_yPosition;
+}
+
+void QmlGraphicsFlickableVisibleArea::updateVisible()
+{
+ QmlGraphicsFlickablePrivate *p = static_cast<QmlGraphicsFlickablePrivate *>(QGraphicsItemPrivate::get(flickable));
+ bool pageChange = false;
+
+ // Vertical
+ const qreal viewheight = flickable->height();
+ const qreal maxyextent = -flickable->maxYExtent() + flickable->minYExtent();
+ qreal pagePos = (-p->_moveY.value() + flickable->minYExtent()) / (maxyextent + viewheight);
+ qreal pageSize = viewheight / (maxyextent + viewheight);
+
+ if (pageSize != m_heightRatio) {
+ m_heightRatio = pageSize;
+ pageChange = true;
+ }
+ if (pagePos != m_yPosition) {
+ m_yPosition = pagePos;
+ pageChange = true;
+ }
+
+ // Horizontal
+ const qreal viewwidth = flickable->width();
+ const qreal maxxextent = -flickable->maxXExtent() + flickable->minXExtent();
+ pagePos = (-p->_moveX.value() + flickable->minXExtent()) / (maxxextent + viewwidth);
+ pageSize = viewwidth / (maxxextent + viewwidth);
+
+ if (pageSize != m_widthRatio) {
+ m_widthRatio = pageSize;
+ pageChange = true;
+ }
+ if (pagePos != m_xPosition) {
+ m_xPosition = pagePos;
+ pageChange = true;
+ }
+ if (pageChange)
+ emit pageChanged();
+}
+
+
+QmlGraphicsFlickablePrivate::QmlGraphicsFlickablePrivate()
+ : viewport(new QmlGraphicsItem)
+ , _moveX(this, &QmlGraphicsFlickablePrivate::setRoundedViewportX)
+ , _moveY(this, &QmlGraphicsFlickablePrivate::setRoundedViewportY)
+ , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false)
+ , pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true)
+ , interactive(true), deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100)
+ , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(200)
+ , horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0)
+ , flickDirection(QmlGraphicsFlickable::AutoFlickDirection)
+{
+ fixupXEvent = QmlTimeLineEvent::timeLineEvent<QmlGraphicsFlickablePrivate, &QmlGraphicsFlickablePrivate::fixupX>(&_moveX, this);
+ fixupYEvent = QmlTimeLineEvent::timeLineEvent<QmlGraphicsFlickablePrivate, &QmlGraphicsFlickablePrivate::fixupY>(&_moveY, this);
+}
+
+void QmlGraphicsFlickablePrivate::init()
+{
+ Q_Q(QmlGraphicsFlickable);
+ viewport->setParent(q);
+ QObject::connect(&timeline, SIGNAL(updated()), q, SLOT(ticked()));
+ QObject::connect(&timeline, SIGNAL(completed()), q, SLOT(movementEnding()));
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFiltersChildEvents(true);
+ QObject::connect(viewport, SIGNAL(xChanged()), q, SIGNAL(positionXChanged()));
+ QObject::connect(viewport, SIGNAL(yChanged()), q, SIGNAL(positionYChanged()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(heightChange()));
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(widthChange()));
+}
+
+void QmlGraphicsFlickablePrivate::flickX(qreal velocity)
+{
+ Q_Q(QmlGraphicsFlickable);
+ qreal maxDistance = -1;
+ // -ve velocity means list is moving up
+ if (velocity > 0) {
+ const qreal minX = q->minXExtent();
+ if (_moveX.value() < minX)
+ maxDistance = qAbs(minX -_moveX.value() + (overShoot?30:0));
+ flickTargetX = minX;
+ } else {
+ const qreal maxX = q->maxXExtent();
+ if (_moveX.value() > maxX)
+ maxDistance = qAbs(maxX - _moveX.value()) + (overShoot?30:0);
+ flickTargetX = maxX;
+ }
+ if (maxDistance > 0) {
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ timeline.reset(_moveX);
+ timeline.accel(_moveX, v, deceleration, maxDistance);
+ timeline.execute(fixupXEvent);
+ if (!flicked) {
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ }
+ } else {
+ timeline.reset(_moveX);
+ fixupX();
+ }
+}
+
+void QmlGraphicsFlickablePrivate::flickY(qreal velocity)
+{
+ Q_Q(QmlGraphicsFlickable);
+ qreal maxDistance = -1;
+ // -ve velocity means list is moving up
+ if (velocity > 0) {
+ const qreal minY = q->minYExtent();
+ if (_moveY.value() < minY)
+ maxDistance = qAbs(minY -_moveY.value() + (overShoot?30:0));
+ flickTargetY = minY;
+ } else {
+ const qreal maxY = q->maxYExtent();
+ if (_moveY.value() > maxY)
+ maxDistance = qAbs(maxY - _moveY.value()) + (overShoot?30:0);
+ flickTargetY = maxY;
+ }
+ if (maxDistance > 0) {
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ timeline.reset(_moveY);
+ timeline.accel(_moveY, v, deceleration, maxDistance);
+ timeline.execute(fixupYEvent);
+ if (!flicked) {
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ }
+ } else {
+ timeline.reset(_moveY);
+ fixupY();
+ }
+}
+
+void QmlGraphicsFlickablePrivate::fixupX()
+{
+ Q_Q(QmlGraphicsFlickable);
+ if (!q->xflick() || _moveX.timeLine())
+ return;
+
+ if (_moveX.value() > q->minXExtent() || (q->maxXExtent() > q->minXExtent())) {
+ timeline.reset(_moveX);
+ if (_moveX.value() != q->minXExtent()) {
+ if (fixupDuration)
+ timeline.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ else
+ _moveY.setValue(q->minYExtent());
+ }
+ //emit flickingChanged();
+ } else if (_moveX.value() < q->maxXExtent()) {
+ timeline.reset(_moveX);
+ if (fixupDuration)
+ timeline.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ else
+ _moveY.setValue(q->maxYExtent());
+ //emit flickingChanged();
+ } else {
+ flicked = false;
+ }
+
+ vTime = timeline.time();
+}
+
+void QmlGraphicsFlickablePrivate::fixupY()
+{
+ Q_Q(QmlGraphicsFlickable);
+ if (!q->yflick() || _moveY.timeLine())
+ return;
+
+ if (_moveY.value() > q->minYExtent() || (q->maxYExtent() > q->minYExtent())) {
+ timeline.reset(_moveY);
+ if (_moveY.value() != q->minYExtent()) {
+ if (fixupDuration)
+ timeline.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ else
+ _moveY.setValue(q->minYExtent());
+ }
+ //emit flickingChanged();
+ } else if (_moveY.value() < q->maxYExtent()) {
+ timeline.reset(_moveY);
+ if (fixupDuration)
+ timeline.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ else
+ _moveY.setValue(q->maxYExtent());
+ //emit flickingChanged();
+ } else {
+ flicked = false;
+ }
+
+ vTime = timeline.time();
+}
+
+void QmlGraphicsFlickablePrivate::updateBeginningEnd()
+{
+ Q_Q(QmlGraphicsFlickable);
+ bool atBoundaryChange = false;
+
+ // Vertical
+ const int maxyextent = int(-q->maxYExtent());
+ const qreal ypos = -_moveY.value();
+ bool atBeginning = (ypos <= -q->minYExtent());
+ bool atEnd = (maxyextent <= ypos);
+
+ if (atBeginning != atYBeginning) {
+ atYBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != atYEnd) {
+ atYEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ // Horizontal
+ const int maxxextent = int(-q->maxXExtent());
+ const qreal xpos = -_moveX.value();
+ atBeginning = (xpos <= -q->minXExtent());
+ atEnd = (maxxextent <= xpos);
+
+ if (atBeginning != atXBeginning) {
+ atXBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != atXEnd) {
+ atXEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ if (atBoundaryChange)
+ emit q->isAtBoundaryChanged();
+
+ if (visibleArea)
+ visibleArea->updateVisible();
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Flickable,QmlGraphicsFlickable)
+
+/*!
+ \qmlclass Flickable QmlGraphicsFlickable
+ \brief The Flickable item provides a surface that can be "flicked".
+ \inherits Item
+
+ Flickable places its children on a surface that can be dragged and flicked.
+
+ \code
+ Flickable {
+ width: 200; height: 200; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+ }
+ \endcode
+
+ \image flickable.gif
+
+ \note Flickable does not automatically clip its contents. If
+ it is not full-screen it is likely that \c clip should be set
+ to true.
+
+ \note Due to an implementation detail items placed inside a flickable cannot anchor to it by
+ id, use 'parent' instead.
+*/
+
+/*!
+ \qmlsignal Flickable::onMovementStarted()
+
+ This handler is called when the view begins moving due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal Flickable::onMovementEnded()
+
+ This handler is called when the view stops moving due to user
+ interaction. If a flick was generated, this handler will
+ be triggered once the flick stops. If a flick was not
+ generated, the handler will be triggered when the
+ user stops dragging - i.e. a mouse or touch release.
+*/
+
+/*!
+ \qmlsignal Flickable::onFlickStarted()
+
+ This handler is called when the view is flicked. A flick
+ starts from the point that the mouse or touch is released,
+ while still in motion.
+*/
+
+/*!
+ \qmlsignal Flickable::onFlickEnded()
+
+ This handler is called when the view stops moving due to a flick.
+*/
+
+/*!
+ \qmlproperty real Flickable::visibleArea.xPosition
+ \qmlproperty real Flickable::visibleArea.widthRatio
+ \qmlproperty real Flickable::visibleArea.yPosition
+ \qmlproperty real Flickable::visibleArea.heightRatio
+
+ These properties describe the position and size of the currently viewed area.
+ The size is defined as the percentage of the full view currently visible,
+ scaled to 0.0 - 1.0. The page position is in the range 0.0 (beginning) to
+ size ratio (end), i.e. yPosition is in the range 0.0 - heightRatio.
+
+ These properties are typically used to draw a scrollbar, for example:
+ \code
+ Rectangle {
+ opacity: 0.5; anchors.right: MyListView.right-2; width: 6
+ y: MyListView.visibleArea.yPosition * MyListView.height
+ height: MyListView.visibleArea.heightRatio * MyListView.height
+ }
+ \endcode
+*/
+
+QmlGraphicsFlickable::QmlGraphicsFlickable(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsFlickablePrivate), parent)
+{
+ Q_D(QmlGraphicsFlickable);
+ d->init();
+}
+
+QmlGraphicsFlickable::QmlGraphicsFlickable(QmlGraphicsFlickablePrivate &dd, QmlGraphicsItem *parent)
+ : QmlGraphicsItem(dd, parent)
+{
+ Q_D(QmlGraphicsFlickable);
+ d->init();
+}
+
+QmlGraphicsFlickable::~QmlGraphicsFlickable()
+{
+}
+
+/*!
+ \qmlproperty int Flickable::viewportX
+ \qmlproperty int Flickable::viewportY
+
+ These properties hold the surface coordinate currently at the top-left
+ corner of the Flickable. For example, if you flick an image up 100 pixels,
+ \c yPosition will be 100.
+*/
+qreal QmlGraphicsFlickable::viewportX() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return -d->_moveX.value();
+}
+
+void QmlGraphicsFlickable::setViewportX(qreal pos)
+{
+ Q_D(QmlGraphicsFlickable);
+ pos = qRound(pos);
+ d->timeline.reset(d->_moveX);
+ d->vTime = d->timeline.time();
+ if (-pos != d->_moveX.value()) {
+ d->_moveX.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+qreal QmlGraphicsFlickable::viewportY() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return -d->_moveY.value();
+}
+
+void QmlGraphicsFlickable::setViewportY(qreal pos)
+{
+ Q_D(QmlGraphicsFlickable);
+ pos = qRound(pos);
+ d->timeline.reset(d->_moveY);
+ d->vTime = d->timeline.time();
+ if (-pos != d->_moveY.value()) {
+ d->_moveY.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+/*!
+ \qmlproperty bool Flickable::interactive
+
+ A user cannot drag or flick a Flickable that is not interactive.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with Flickable's children: for example, you might want to
+ freeze a flickable map while viewing detailed information on a location popup that is a child of the Flickable.
+*/
+bool QmlGraphicsFlickable::isInteractive() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->interactive;
+}
+
+void QmlGraphicsFlickable::setInteractive(bool interactive)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (interactive != d->interactive) {
+ d->interactive = interactive;
+ if (!interactive && d->flicked) {
+ d->timeline.clear();
+ d->vTime = d->timeline.time();
+ d->flicked = false;
+ emit flickingChanged();
+ emit flickEnded();
+ }
+ emit interactiveChanged();
+ }
+}
+
+/*!
+ \qmlproperty real Flickable::horizontalVelocity
+ \qmlproperty real Flickable::verticalVelocity
+ \qmlproperty real Flickable::reportedVelocitySmoothing
+
+ The instantaneous velocity of movement along the x and y axes, in pixels/sec.
+
+ The reported velocity is smoothed to avoid erratic output.
+ reportedVelocitySmoothing determines how much smoothing is applied.
+*/
+qreal QmlGraphicsFlickable::horizontalVelocity() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->horizontalVelocity.value();
+}
+
+qreal QmlGraphicsFlickable::verticalVelocity() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->verticalVelocity.value();
+}
+
+/*!
+ \qmlproperty bool Flickable::atXBeginning
+ \qmlproperty bool Flickable::atXEnd
+ \qmlproperty bool Flickable::atYBeginning
+ \qmlproperty bool Flickable::atYEnd
+
+ These properties are true if the flickable view is positioned at the beginning,
+ or end respecively.
+*/
+bool QmlGraphicsFlickable::isAtXEnd() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->atXEnd;
+}
+
+bool QmlGraphicsFlickable::isAtXBeginning() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->atXBeginning;
+}
+
+bool QmlGraphicsFlickable::isAtYEnd() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->atYEnd;
+}
+
+bool QmlGraphicsFlickable::isAtYBeginning() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->atYBeginning;
+}
+
+void QmlGraphicsFlickable::ticked()
+{
+ viewportMoved();
+}
+
+QmlGraphicsItem *QmlGraphicsFlickable::viewport()
+{
+ Q_D(QmlGraphicsFlickable);
+ return d->viewport;
+}
+
+QmlGraphicsFlickableVisibleArea *QmlGraphicsFlickable::visibleArea()
+{
+ Q_D(QmlGraphicsFlickable);
+ if (!d->visibleArea)
+ d->visibleArea = new QmlGraphicsFlickableVisibleArea(this);
+ return d->visibleArea;
+}
+
+/*!
+ \qmlproperty enumeration Flickable::flickDirection
+
+ This property determines which directions the view can be flicked.
+
+ \list
+ \o AutoFlickDirection (default) - allows flicking vertically if the
+ \e viewportHeight is not equal to the \e height of the Flickable.
+ Allows flicking horizontally if the \e viewportWidth is not equal
+ to the \e width of the Flickable.
+ \o HorizontalFlick - allows flicking horizontally.
+ \o VerticalFlick - allows flicking vertically.
+ \o HorizontalAndVerticalFlick - allows flicking in both directions.
+ \endlist
+*/
+QmlGraphicsFlickable::FlickDirection QmlGraphicsFlickable::flickDirection() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->flickDirection;
+}
+
+void QmlGraphicsFlickable::setFlickDirection(FlickDirection direction)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (direction != d->flickDirection) {
+ d->flickDirection = direction;
+ emit flickDirectionChanged();
+ }
+}
+
+void QmlGraphicsFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (interactive && timeline.isActive() && (qAbs(velocityX) > 10 || qAbs(velocityY) > 10))
+ stealMouse = true; // If we've been flicked then steal the click.
+ else
+ stealMouse = false;
+ pressed = true;
+ timeline.clear();
+ velocityX = 0;
+ velocityY = 0;
+ lastPos = QPoint();
+ QmlGraphicsItemPrivate::start(lastPosTime);
+ pressPos = event->pos();
+ pressX = _moveX.value();
+ pressY = _moveY.value();
+ flicked = false;
+ QmlGraphicsItemPrivate::start(pressTime);
+ QmlGraphicsItemPrivate::start(velocityTime);
+}
+
+void QmlGraphicsFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QmlGraphicsFlickable);
+ if (!interactive || lastPosTime.isNull())
+ return;
+ bool rejectY = false;
+ bool rejectX = false;
+ bool moved = false;
+
+ if (q->yflick()) {
+ int dy = int(event->pos().y() - pressPos.y());
+ if (qAbs(dy) > QApplication::startDragDistance() || QmlGraphicsItemPrivate::elapsed(pressTime) > 200) {
+ qreal newY = dy + pressY;
+ const qreal minY = q->minYExtent();
+ const qreal maxY = q->maxYExtent();
+ if (newY > minY)
+ newY = minY + (newY - minY) / 2;
+ if (newY < maxY && maxY - minY <= 0)
+ newY = maxY + (newY - maxY) / 2;
+ if (!q->overShoot() && (newY > minY || newY < maxY)) {
+ if (newY > minY)
+ newY = minY;
+ else if (newY < maxY)
+ newY = maxY;
+ else
+ rejectY = true;
+ }
+ if (!rejectY) {
+ _moveY.setValue(newY);
+ moved = true;
+ }
+ if (qAbs(dy) > QApplication::startDragDistance())
+ stealMouse = true;
+ }
+ }
+
+ if (q->xflick()) {
+ int dx = int(event->pos().x() - pressPos.x());
+ if (qAbs(dx) > QApplication::startDragDistance() || QmlGraphicsItemPrivate::elapsed(pressTime) > 200) {
+ qreal newX = dx + pressX;
+ const qreal minX = q->minXExtent();
+ const qreal maxX = q->maxXExtent();
+ if (newX > minX)
+ newX = minX + (newX - minX) / 2;
+ if (newX < maxX && maxX - minX <= 0)
+ newX = maxX + (newX - maxX) / 2;
+ if (!q->overShoot() && (newX > minX || newX < maxX)) {
+ if (newX > minX)
+ newX = minX;
+ else if (newX < maxX)
+ newX = maxX;
+ else
+ rejectX = true;
+ }
+ if (!rejectX) {
+ _moveX.setValue(newX);
+ moved = true;
+ }
+
+ if (qAbs(dx) > QApplication::startDragDistance())
+ stealMouse = true;
+ }
+ }
+
+ if (!lastPos.isNull()) {
+ qreal elapsed = qreal(QmlGraphicsItemPrivate::restart(lastPosTime)) / 1000.;
+ if (elapsed <= 0)
+ elapsed = 1;
+ if (q->yflick()) {
+ qreal diff = event->pos().y() - lastPos.y();
+ // average to reduce the effect of spurious moves
+ velocityY += diff / elapsed;
+ velocityY /= 2;
+ }
+
+ if (q->xflick()) {
+ qreal diff = event->pos().x() - lastPos.x();
+ // average to reduce the effect of spurious moves
+ velocityX += diff / elapsed;
+ velocityX /= 2;
+ }
+ }
+
+ if (rejectY) velocityY = 0;
+ if (rejectX) velocityX = 0;
+
+ if (moved) {
+ q->movementStarting();
+ q->viewportMoved();
+ }
+
+ lastPos = event->pos();
+}
+
+void QmlGraphicsFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QmlGraphicsFlickable);
+ pressed = false;
+ if (lastPosTime.isNull())
+ return;
+
+ if (QmlGraphicsItemPrivate::elapsed(lastPosTime) > 100) {
+ // if we drag then pause before release we should not cause a flick.
+ velocityX = 0.0;
+ velocityY = 0.0;
+ }
+
+ vTime = timeline.time();
+ if (qAbs(velocityY) > 10 && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) {
+ qreal velocity = velocityY;
+ if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks.
+ velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity;
+ flickY(velocity);
+ } else {
+ fixupY();
+ }
+
+ if (qAbs(velocityX) > 10 && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) {
+ qreal velocity = velocityX;
+ if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks.
+ velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity;
+ flickX(velocity);
+ } else {
+ fixupX();
+ }
+
+ stealMouse = false;
+ lastPosTime = QTime();
+
+ if (!timeline.isActive())
+ q->movementEnding();
+}
+
+void QmlGraphicsFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->interactive) {
+ d->handleMousePressEvent(event);
+ event->accept();
+ } else {
+ QmlGraphicsItem::mousePressEvent(event);
+ }
+}
+
+void QmlGraphicsFlickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->interactive) {
+ d->handleMouseMoveEvent(event);
+ event->accept();
+ } else {
+ QmlGraphicsItem::mouseMoveEvent(event);
+ }
+}
+
+void QmlGraphicsFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->interactive) {
+ d->clearDelayedPress();
+ d->handleMouseReleaseEvent(event);
+ event->accept();
+ ungrabMouse();
+ } else {
+ QmlGraphicsItem::mouseReleaseEvent(event);
+ }
+}
+
+void QmlGraphicsFlickable::wheelEvent(QGraphicsSceneWheelEvent *event)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (!d->interactive) {
+ QmlGraphicsItem::wheelEvent(event);
+ } else if (yflick()) {
+ if (event->delta() > 0)
+ d->velocityY = qMax(event->delta() - d->verticalVelocity.value(), qreal(250.0));
+ else
+ d->velocityY = qMin(event->delta() - d->verticalVelocity.value(), qreal(-250.0));
+ d->flicked = false;
+ d->flickY(d->velocityY);
+ event->accept();
+ } else if (xflick()) {
+ if (event->delta() > 0)
+ d->velocityX = qMax(event->delta() - d->horizontalVelocity.value(), qreal(250.0));
+ else
+ d->velocityX = qMin(event->delta() - d->horizontalVelocity.value(), qreal(-250.0));
+ d->flicked = false;
+ d->flickX(d->velocityX);
+ event->accept();
+ } else {
+ QmlGraphicsItem::wheelEvent(event);
+ }
+}
+
+void QmlGraphicsFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QmlGraphicsFlickable);
+ if (!q->scene() || pressDelay <= 0)
+ return;
+ delayedPressTarget = q->scene()->mouseGrabberItem();
+ delayedPressEvent = new QGraphicsSceneMouseEvent(event->type());
+ delayedPressEvent->setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ delayedPressEvent->setButtonDownPos(button, event->buttonDownPos(button));
+ delayedPressEvent->setButtonDownScenePos(button, event->buttonDownScenePos(button));
+ delayedPressEvent->setButtonDownScreenPos(button, event->buttonDownScreenPos(button));
+ }
+ }
+ delayedPressEvent->setButtons(event->buttons());
+ delayedPressEvent->setButton(event->button());
+ delayedPressEvent->setPos(event->pos());
+ delayedPressEvent->setScenePos(event->scenePos());
+ delayedPressEvent->setScreenPos(event->screenPos());
+ delayedPressEvent->setLastPos(event->lastPos());
+ delayedPressEvent->setLastScenePos(event->lastScenePos());
+ delayedPressEvent->setLastScreenPos(event->lastScreenPos());
+ delayedPressEvent->setModifiers(event->modifiers());
+ delayedPressTimer.start(pressDelay, q);
+}
+
+void QmlGraphicsFlickablePrivate::clearDelayedPress()
+{
+ if (delayedPressEvent) {
+ delayedPressTimer.stop();
+ delete delayedPressEvent;
+ delayedPressEvent = 0;
+ }
+}
+
+void QmlGraphicsFlickablePrivate::setRoundedViewportX(qreal x)
+{
+ viewport->setX(qRound(x));
+}
+
+void QmlGraphicsFlickablePrivate::setRoundedViewportY(qreal y)
+{
+ viewport->setY(qRound(y));
+}
+
+void QmlGraphicsFlickable::timerEvent(QTimerEvent *event)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (event->timerId() == d->delayedPressTimer.timerId()) {
+ d->delayedPressTimer.stop();
+ if (d->delayedPressEvent) {
+ QmlGraphicsItem *grabber = scene() ? qobject_cast<QmlGraphicsItem*>(scene()->mouseGrabberItem()) : 0;
+ if (!grabber || grabber != this)
+ scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent);
+ delete d->delayedPressEvent;
+ d->delayedPressEvent = 0;
+ }
+ }
+}
+
+qreal QmlGraphicsFlickable::minYExtent() const
+{
+ return 0.0;
+}
+
+qreal QmlGraphicsFlickable::minXExtent() const
+{
+ return 0.0;
+}
+
+/* returns -ve */
+qreal QmlGraphicsFlickable::maxXExtent() const
+{
+ return width() - vWidth();
+}
+/* returns -ve */
+qreal QmlGraphicsFlickable::maxYExtent() const
+{
+ return height() - vHeight();
+}
+
+void QmlGraphicsFlickable::viewportMoved()
+{
+ Q_D(QmlGraphicsFlickable);
+
+ int elapsed = QmlGraphicsItemPrivate::restart(d->velocityTime);
+ if (!elapsed)
+ return;
+
+ qreal prevY = d->lastFlickablePosition.x();
+ qreal prevX = d->lastFlickablePosition.y();
+ d->velocityTimeline.clear();
+ if (d->pressed) {
+ qreal horizontalVelocity = (prevX - d->_moveX.value()) * 1000 / elapsed;
+ qreal verticalVelocity = (prevY - d->_moveY.value()) * 1000 / elapsed;
+ d->velocityTimeline.move(d->horizontalVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->horizontalVelocity, 0, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->verticalVelocity, verticalVelocity, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->verticalVelocity, 0, d->reportedVelocitySmoothing);
+ } else {
+ if (d->timeline.time() > d->vTime) {
+ qreal horizontalVelocity = (prevX - d->_moveX.value()) * 1000 / (d->timeline.time() - d->vTime);
+ qreal verticalVelocity = (prevY - d->_moveY.value()) * 1000 / (d->timeline.time() - d->vTime);
+ d->horizontalVelocity.setValue(horizontalVelocity);
+ d->verticalVelocity.setValue(verticalVelocity);
+ }
+ }
+
+ d->lastFlickablePosition = QPointF(d->_moveY.value(), d->_moveX.value());
+
+ d->vTime = d->timeline.time();
+ d->updateBeginningEnd();
+}
+
+void QmlGraphicsFlickable::cancelFlick()
+{
+ Q_D(QmlGraphicsFlickable);
+ d->timeline.reset(d->_moveX);
+ d->timeline.reset(d->_moveY);
+ movementEnding();
+}
+
+void QmlGraphicsFlickablePrivate::data_removeAt(int)
+{
+ // ###
+}
+
+int QmlGraphicsFlickablePrivate::data_count() const
+{
+ // ###
+ return 0;
+}
+
+void QmlGraphicsFlickablePrivate::data_append(QObject *o)
+{
+ Q_Q(QmlGraphicsFlickable);
+ QmlGraphicsItem *i = qobject_cast<QmlGraphicsItem *>(o);
+ if (i)
+ viewport->fxChildren()->append(i);
+ else
+ o->setParent(q);
+}
+
+void QmlGraphicsFlickablePrivate::data_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QmlGraphicsFlickablePrivate::data_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QmlGraphicsFlickablePrivate::data_clear()
+{
+ // ###
+}
+
+
+QmlList<QObject *> *QmlGraphicsFlickable::flickableData()
+{
+ Q_D(QmlGraphicsFlickable);
+ return &d->data;
+}
+
+QmlList<QmlGraphicsItem *> *QmlGraphicsFlickable::flickableChildren()
+{
+ Q_D(QmlGraphicsFlickable);
+ return d->viewport->fxChildren();
+}
+
+/*!
+ \qmlproperty bool Flickable::overShoot
+ This property holds the number of pixels the surface may overshoot the
+ Flickable's boundaries when flicked.
+
+ If overShoot is non-zero the contents can be flicked beyond the boundary
+ of the Flickable before being moved back to the boundary. This provides
+ the feeling that the edges of the view are soft, rather than a hard
+ physical boundary.
+*/
+bool QmlGraphicsFlickable::overShoot() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->overShoot;
+}
+
+void QmlGraphicsFlickable::setOverShoot(bool o)
+{
+ Q_D(QmlGraphicsFlickable);
+ d->overShoot = o;
+}
+
+/*!
+ \qmlproperty int Flickable::viewportWidth
+ \qmlproperty int Flickable::viewportHeight
+
+ The dimensions of the viewport (the surface controlled by Flickable). Typically this
+ should be set to the combined size of the items placed in the Flickable.
+
+ \code
+ Flickable {
+ width: 320; height: 480; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+ }
+ \endcode
+*/
+qreal QmlGraphicsFlickable::viewportWidth() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->vWidth;
+}
+
+void QmlGraphicsFlickable::setViewportWidth(qreal w)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->vWidth == w)
+ return;
+ d->vWidth = w;
+ if (w < 0)
+ d->viewport->setWidth(width());
+ else
+ d->viewport->setWidth(w);
+ // Make sure that we're entirely in view.
+ if (!d->pressed)
+ d->fixupX();
+ emit viewportWidthChanged();
+ d->updateBeginningEnd();
+}
+
+void QmlGraphicsFlickable::widthChange()
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->vWidth < 0) {
+ d->viewport->setWidth(width());
+ emit viewportWidthChanged();
+ }
+ d->updateBeginningEnd();
+}
+
+void QmlGraphicsFlickable::heightChange()
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->vHeight < 0) {
+ d->viewport->setHeight(height());
+ emit viewportHeightChanged();
+ }
+ d->updateBeginningEnd();
+}
+
+qreal QmlGraphicsFlickable::viewportHeight() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->vHeight;
+}
+
+void QmlGraphicsFlickable::setViewportHeight(qreal h)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->vHeight == h)
+ return;
+ d->vHeight = h;
+ if (h < 0)
+ d->viewport->setHeight(height());
+ else
+ d->viewport->setHeight(h);
+ // Make sure that we're entirely in view.
+ if (!d->pressed)
+ d->fixupY();
+ emit viewportHeightChanged();
+ d->updateBeginningEnd();
+}
+
+qreal QmlGraphicsFlickable::vWidth() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ if (d->vWidth < 0)
+ return width();
+ else
+ return d->vWidth;
+}
+
+qreal QmlGraphicsFlickable::vHeight() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ if (d->vHeight < 0)
+ return height();
+ else
+ return d->vHeight;
+}
+
+bool QmlGraphicsFlickable::xflick() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ if (d->flickDirection == QmlGraphicsFlickable::AutoFlickDirection)
+ return vWidth() != width();
+ return d->flickDirection & QmlGraphicsFlickable::HorizontalFlick;
+}
+
+bool QmlGraphicsFlickable::yflick() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ if (d->flickDirection == QmlGraphicsFlickable::AutoFlickDirection)
+ return vHeight() != height();
+ return d->flickDirection & QmlGraphicsFlickable::VerticalFlick;
+}
+
+bool QmlGraphicsFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsFlickable);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
+
+ QGraphicsScene *s = scene();
+ QmlGraphicsItem *grabber = s ? qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem()) : 0;
+ if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ d->handleMouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ if (d->delayedPressEvent)
+ return false;
+
+ d->handleMousePressEvent(&mouseEvent);
+ d->captureDelayedPress(event);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ if (d->delayedPressEvent) {
+ scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent);
+ d->clearDelayedPress();
+ }
+ d->handleMouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem());
+ if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this) {
+ d->clearDelayedPress();
+ grabMouse();
+ }
+
+ return d->stealMouse || d->delayedPressEvent;
+ } else if (!d->lastPosTime.isNull()) {
+ d->lastPosTime = QTime();
+ }
+ if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease)
+ d->clearDelayedPress();
+ return false;
+}
+
+bool QmlGraphicsFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (!isVisible() || !d->interactive)
+ return QmlGraphicsItem::sceneEventFilter(i, e);
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
+ default:
+ break;
+ }
+
+ return QmlGraphicsItem::sceneEventFilter(i, e);
+}
+
+/*!
+ \qmlproperty real Flickable::maximumFlickVelocity
+ This property holds the maximum velocity that the user can flick the view in pixels/second.
+
+ The default is 2000 pixels/s
+*/
+qreal QmlGraphicsFlickable::maximumFlickVelocity() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->maxVelocity;
+}
+
+void QmlGraphicsFlickable::setMaximumFlickVelocity(qreal v)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (v == d->maxVelocity)
+ return;
+ d->maxVelocity = v;
+}
+
+/*!
+ \qmlproperty real Flickable::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default is 500.
+*/
+qreal QmlGraphicsFlickable::flickDeceleration() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->deceleration;
+}
+
+void QmlGraphicsFlickable::setFlickDeceleration(qreal deceleration)
+{
+ Q_D(QmlGraphicsFlickable);
+ d->deceleration = deceleration;
+}
+
+/*!
+ \qmlproperty bool Flickable::flicking
+
+ This property holds whether the view is currently moving due to
+ the user flicking the view.
+*/
+bool QmlGraphicsFlickable::isFlicking() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->flicked;
+}
+
+/*!
+ \qmlproperty int Flickable::pressDelay
+
+ This property holds the time to delay (ms) delivering a press to
+ children of the Flickable. This can be useful where reacting
+ to a press before a flicking action has undesireable effects.
+
+ If the flickable is dragged/flicked before the delay times out
+ the press event will not be delivered. If the button is released
+ within the timeout, both the press and release will be delivered.
+*/
+int QmlGraphicsFlickable::pressDelay() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->pressDelay;
+}
+
+void QmlGraphicsFlickable::setPressDelay(int delay)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->pressDelay == delay)
+ return;
+ d->pressDelay = delay;
+}
+
+qreal QmlGraphicsFlickable::reportedVelocitySmoothing() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->reportedVelocitySmoothing;
+}
+
+void QmlGraphicsFlickable::setReportedVelocitySmoothing(qreal reportedVelocitySmoothing)
+{
+ Q_D(QmlGraphicsFlickable);
+ Q_ASSERT(reportedVelocitySmoothing >= 0);
+ if (reportedVelocitySmoothing == d->reportedVelocitySmoothing)
+ return;
+ d->reportedVelocitySmoothing = reportedVelocitySmoothing;
+ emit reportedVelocitySmoothingChanged(reportedVelocitySmoothing);
+}
+
+/*!
+ \qmlproperty bool Flickable::moving
+
+ This property holds whether the view is currently moving due to
+ the user either dragging or flicking the view.
+*/
+bool QmlGraphicsFlickable::isMoving() const
+{
+ Q_D(const QmlGraphicsFlickable);
+ return d->moving;
+}
+
+void QmlGraphicsFlickable::movementStarting()
+{
+ Q_D(QmlGraphicsFlickable);
+ if (!d->moving) {
+ d->moving = true;
+ emit movingChanged();
+ emit movementStarted();
+ }
+}
+
+void QmlGraphicsFlickable::movementEnding()
+{
+ Q_D(QmlGraphicsFlickable);
+ if (d->moving) {
+ d->moving = false;
+ emit movingChanged();
+ emit movementEnded();
+ }
+ if (d->flicked) {
+ d->flicked = false;
+ emit flickingChanged();
+ emit flickEnded();
+ }
+ d->horizontalVelocity.setValue(0);
+ d->verticalVelocity.setValue(0);
+}
+
+void QmlGraphicsFlickablePrivate::updateVelocity()
+{
+ Q_Q(QmlGraphicsFlickable);
+ emit q->horizontalVelocityChanged();
+ emit q->verticalVelocityChanged();
+}
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsFlickableVisibleArea)
+QML_DEFINE_TYPE(Qt,4,6,VisibleArea,QmlGraphicsFlickableVisibleArea)
+
+#include <qmlgraphicsflickable.moc>
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable_p.h b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
new file mode 100644
index 0000000..ea07da4
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSFLICKABLE_H
+#define QMLGRAPHICSFLICKABLE_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsFlickablePrivate;
+class QmlGraphicsFlickableVisibleArea;
+class Q_DECLARATIVE_EXPORT QmlGraphicsFlickable : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal viewportWidth READ viewportWidth WRITE setViewportWidth NOTIFY viewportWidthChanged)
+ Q_PROPERTY(qreal viewportHeight READ viewportHeight WRITE setViewportHeight NOTIFY viewportHeightChanged)
+ Q_PROPERTY(qreal viewportX READ viewportX WRITE setViewportX NOTIFY positionXChanged)
+ Q_PROPERTY(qreal viewportY READ viewportY WRITE setViewportY NOTIFY positionYChanged)
+
+ Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged)
+ Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
+ Q_PROPERTY(qreal reportedVelocitySmoothing READ reportedVelocitySmoothing WRITE setReportedVelocitySmoothing NOTIFY reportedVelocitySmoothingChanged)
+
+ Q_PROPERTY(bool overShoot READ overShoot WRITE setOverShoot)
+ Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity)
+ Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration)
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
+ Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
+ Q_PROPERTY(FlickDirection flickDirection READ flickDirection WRITE setFlickDirection NOTIFY flickDirectionChanged)
+
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
+ Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay)
+
+ Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atXBeginning READ isAtXBeginning NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYBeginning READ isAtYBeginning NOTIFY isAtBoundaryChanged)
+
+ Q_PROPERTY(QmlGraphicsFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
+
+ Q_PROPERTY(QmlList<QObject *>* flickableData READ flickableData)
+ Q_PROPERTY(QmlList<QmlGraphicsItem *>* flickableChildren READ flickableChildren)
+ Q_CLASSINFO("DefaultProperty", "flickableData")
+
+ Q_ENUMS(FlickDirection)
+
+public:
+ QmlGraphicsFlickable(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsFlickable();
+
+ QmlList<QObject *> *flickableData();
+ QmlList<QmlGraphicsItem *> *flickableChildren();
+
+ bool overShoot() const;
+ void setOverShoot(bool);
+
+ qreal viewportWidth() const;
+ void setViewportWidth(qreal);
+
+ qreal viewportHeight() const;
+ void setViewportHeight(qreal);
+
+ qreal viewportX() const;
+ void setViewportX(qreal pos);
+
+ qreal viewportY() const;
+ void setViewportY(qreal pos);
+
+ bool isMoving() const;
+ bool isFlicking() const;
+
+ int pressDelay() const;
+ void setPressDelay(int delay);
+
+ qreal reportedVelocitySmoothing() const;
+ void setReportedVelocitySmoothing(qreal);
+
+ qreal maximumFlickVelocity() const;
+ void setMaximumFlickVelocity(qreal);
+
+ qreal flickDeceleration() const;
+ void setFlickDeceleration(qreal);
+
+ bool isInteractive() const;
+ void setInteractive(bool);
+
+ qreal horizontalVelocity() const;
+ qreal verticalVelocity() const;
+
+ bool isAtXEnd() const;
+ bool isAtXBeginning() const;
+ bool isAtYEnd() const;
+ bool isAtYBeginning() const;
+
+ QmlGraphicsItem *viewport();
+
+ enum FlickDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
+ FlickDirection flickDirection() const;
+ void setFlickDirection(FlickDirection);
+
+Q_SIGNALS:
+ void viewportWidthChanged();
+ void viewportHeightChanged();
+ void positionXChanged();
+ void positionYChanged();
+ void movingChanged();
+ void flickingChanged();
+ void movementStarted();
+ void movementEnded();
+ void flickStarted();
+ void flickEnded();
+ void reportedVelocitySmoothingChanged(int);
+ void horizontalVelocityChanged();
+ void verticalVelocityChanged();
+ void isAtBoundaryChanged();
+ void pageChanged();
+ void flickDirectionChanged();
+ void interactiveChanged();
+
+protected:
+ virtual bool sceneEventFilter(QGraphicsItem *, QEvent *);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void wheelEvent(QGraphicsSceneWheelEvent *event);
+ void timerEvent(QTimerEvent *event);
+
+ QmlGraphicsFlickableVisibleArea *visibleArea();
+
+protected Q_SLOTS:
+ virtual void ticked();
+ void movementStarting();
+ void movementEnding();
+ void heightChange();
+ void widthChange();
+
+protected:
+ virtual qreal minXExtent() const;
+ virtual qreal minYExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual qreal maxYExtent() const;
+ qreal vWidth() const;
+ qreal vHeight() const;
+ virtual void viewportMoved();
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+
+ bool xflick() const;
+ bool yflick() const;
+ void cancelFlick();
+
+protected:
+ QmlGraphicsFlickable(QmlGraphicsFlickablePrivate &dd, QmlGraphicsItem *parent);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsFlickable)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsFlickable)
+ friend class QmlGraphicsFlickableVisibleArea;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsFlickable)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h b/src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h
new file mode 100644
index 0000000..ae164cc
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable_p_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSFLICKABLE_P_H
+#define QMLGRAPHICSFLICKABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsflickable_p.h"
+
+#include "qmlgraphicsitem_p.h"
+
+#include <qml.h>
+#include <qmltimeline_p_p.h>
+#include <qmlanimation_p_p.h>
+
+#include <qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsFlickableVisibleArea;
+class QmlGraphicsFlickablePrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsFlickable)
+
+public:
+ QmlGraphicsFlickablePrivate();
+ void init();
+ virtual void flickX(qreal velocity);
+ virtual void flickY(qreal velocity);
+ virtual void fixupX();
+ virtual void fixupY();
+ void updateBeginningEnd();
+
+ void captureDelayedPress(QGraphicsSceneMouseEvent *event);
+ void clearDelayedPress();
+
+ void setRoundedViewportX(qreal x);
+ void setRoundedViewportY(qreal y);
+
+public:
+ QmlGraphicsItem *viewport;
+ QmlTimeLineValueProxy<QmlGraphicsFlickablePrivate> _moveX;
+ QmlTimeLineValueProxy<QmlGraphicsFlickablePrivate> _moveY;
+ QmlTimeLine timeline;
+ qreal vWidth;
+ qreal vHeight;
+ bool overShoot : 1;
+ bool flicked : 1;
+ bool moving : 1;
+ bool stealMouse : 1;
+ bool pressed : 1;
+ bool atXEnd : 1;
+ bool atXBeginning : 1;
+ bool atYEnd : 1;
+ bool atYBeginning : 1;
+ bool interactive : 1;
+ QTime lastPosTime;
+ QPointF lastPos;
+ QPointF pressPos;
+ qreal pressX;
+ qreal pressY;
+ qreal velocityX;
+ qreal velocityY;
+ QTime pressTime;
+ QmlTimeLineEvent fixupXEvent;
+ QmlTimeLineEvent fixupYEvent;
+ qreal deceleration;
+ qreal maxVelocity;
+ QTime velocityTime;
+ QPointF lastFlickablePosition;
+ qreal reportedVelocitySmoothing;
+ qreal flickTargetX;
+ qreal flickTargetY;
+ QGraphicsSceneMouseEvent *delayedPressEvent;
+ QGraphicsItem *delayedPressTarget;
+ QBasicTimer delayedPressTimer;
+ int pressDelay;
+ int fixupDuration;
+
+ void updateVelocity();
+ struct Velocity : public QmlTimeLineValue
+ {
+ Velocity(QmlGraphicsFlickablePrivate *p)
+ : parent(p) {}
+ virtual void setValue(qreal v) {
+ QmlTimeLineValue::setValue(v);
+ parent->updateVelocity();
+ }
+ QmlGraphicsFlickablePrivate *parent;
+ };
+ Velocity horizontalVelocity;
+ Velocity verticalVelocity;
+ int vTime;
+ QmlTimeLine velocityTimeline;
+ QmlGraphicsFlickableVisibleArea *visibleArea;
+ QmlGraphicsFlickable::FlickDirection flickDirection;
+
+ void handleMousePressEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseMoveEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *);
+
+ // flickableData property
+ void data_removeAt(int);
+ int data_count() const;
+ void data_append(QObject *);
+ void data_insert(int, QObject *);
+ QObject *data_at(int) const;
+ void data_clear();
+
+ friend class QmlGraphicsFlickableVisibleArea;
+ QML_DECLARE_LIST_PROXY(QmlGraphicsFlickablePrivate, QObject *, data)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsflipable.cpp b/src/declarative/graphicsitems/qmlgraphicsflipable.cpp
new file mode 100644
index 0000000..ff8995b
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsflipable.cpp
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsflipable_p.h"
+
+#include "qmlgraphicsitem_p.h"
+
+#include <qmlinfo.h>
+
+#include <QtGui/qgraphicstransform.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,Flipable,QmlGraphicsFlipable)
+
+class QmlGraphicsFlipablePrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsFlipable)
+public:
+ QmlGraphicsFlipablePrivate() : current(QmlGraphicsFlipable::Front), front(0), back(0) {}
+
+ void updateSceneTransformFromParent();
+
+ QmlGraphicsFlipable::Side current;
+ QmlGraphicsItem *front;
+ QmlGraphicsItem *back;
+};
+
+/*!
+ \qmlclass Flipable QmlGraphicsFlipable
+ \brief The Flipable item provides a surface that can be flipped.
+ \inherits Item
+
+ Flipable allows you to specify a front and a back and then flip between those sides.
+
+ Here's an example that flips between the front and back sides when clicked:
+
+ \qml
+
+ Flipable {
+ id: flipable
+ width: 250; height: 250
+ property int angle: 0
+
+ transform: Rotation {
+ id: rotation
+ origin.x: flipable.width/2; origin.y: flipable.height/2
+ axis.x: 0; axis.y: 1; axis.z: 0 // rotate around y-axis
+ angle: flipable.angle
+ }
+
+ front: Image { source: "front.png" }
+ back: Image { source: "back.png" }
+
+ states: State {
+ name: "back"
+ PropertyChanges { target: flipable; angle: 180 }
+ }
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "angle"; duration: 2000 }
+ }
+
+ MouseRegion {
+ // change between default and 'back' states
+ onClicked: flipable.state = (flipable.state == 'back' ? '' : 'back')
+ anchors.fill: parent
+ }
+ }
+ \endqml
+
+ \image flipable.gif
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsFlipable
+ \brief The QmlGraphicsFlipable class provides a flipable surface.
+
+ \ingroup group_widgets
+
+ QmlGraphicsFlipable allows you to specify a front and a back, as well as an
+ axis for the flip.
+*/
+
+QmlGraphicsFlipable::QmlGraphicsFlipable(QmlGraphicsItem *parent)
+: QmlGraphicsItem(*(new QmlGraphicsFlipablePrivate), parent)
+{
+}
+
+QmlGraphicsFlipable::~QmlGraphicsFlipable()
+{
+}
+
+/*!
+ \qmlproperty Item Flipable::front
+ \qmlproperty Item Flipable::back
+
+ The front and back sides of the flipable.
+*/
+
+QmlGraphicsItem *QmlGraphicsFlipable::front()
+{
+ Q_D(const QmlGraphicsFlipable);
+ return d->front;
+}
+
+void QmlGraphicsFlipable::setFront(QmlGraphicsItem *front)
+{
+ Q_D(QmlGraphicsFlipable);
+ if (d->front) {
+ qmlInfo(this) << tr("front is a write-once property");
+ return;
+ }
+ d->front = front;
+ fxChildren()->append(d->front);
+ if (Back == d->current)
+ d->front->setOpacity(0.);
+}
+
+QmlGraphicsItem *QmlGraphicsFlipable::back()
+{
+ Q_D(const QmlGraphicsFlipable);
+ return d->back;
+}
+
+void QmlGraphicsFlipable::setBack(QmlGraphicsItem *back)
+{
+ Q_D(QmlGraphicsFlipable);
+ if (d->back) {
+ qmlInfo(this) << tr("back is a write-once property");
+ return;
+ }
+ d->back = back;
+ fxChildren()->append(d->back);
+ if (Front == d->current)
+ d->back->setOpacity(0.);
+}
+
+/*!
+ \qmlproperty enumeration Flipable::side
+
+ The side of the Flippable currently visible. Possible values are \c
+ Front and \c Back.
+*/
+QmlGraphicsFlipable::Side QmlGraphicsFlipable::side() const
+{
+ Q_D(const QmlGraphicsFlipable);
+ if (d->dirtySceneTransform)
+ const_cast<QmlGraphicsFlipablePrivate *>(d)->updateSceneTransformFromParent();
+
+ return d->current;
+}
+
+// determination on the currently visible side of the flipable
+// has to be done on the complete scene transform to give
+// correct results.
+void QmlGraphicsFlipablePrivate::updateSceneTransformFromParent()
+{
+ Q_Q(QmlGraphicsFlipable);
+
+ QmlGraphicsItemPrivate::updateSceneTransformFromParent();
+ QPointF p1(0, 0);
+ QPointF p2(1, 0);
+ QPointF p3(1, 1);
+
+ p1 = sceneTransform.map(p1);
+ p2 = sceneTransform.map(p2);
+ p3 = sceneTransform.map(p3);
+
+ qreal cross = (p1.x() - p2.x()) * (p3.y() - p2.y()) -
+ (p1.y() - p2.y()) * (p3.x() - p2.x());
+
+ QmlGraphicsFlipable::Side newSide;
+ if (cross > 0) {
+ newSide = QmlGraphicsFlipable::Back;
+ } else {
+ newSide = QmlGraphicsFlipable::Front;
+ }
+
+ if (newSide != current) {
+ current = newSide;
+ if (current == QmlGraphicsFlipable::Back) {
+ QTransform mat;
+ mat.translate(back->width()/2,back->height()/2);
+ if (back->width() && p1.x() >= p2.x())
+ mat.rotate(180, Qt::YAxis);
+ if (back->height() && p2.y() >= p3.y())
+ mat.rotate(180, Qt::XAxis);
+ mat.translate(-back->width()/2,-back->height()/2);
+ back->setTransform(mat);
+ }
+ if (front)
+ front->setOpacity((current==QmlGraphicsFlipable::Front)?1.:0.);
+ if (back)
+ back->setOpacity((current==QmlGraphicsFlipable::Back)?1.:0.);
+ emit q->sideChanged();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsflipable_p.h b/src/declarative/graphicsitems/qmlgraphicsflipable_p.h
new file mode 100644
index 0000000..c189786
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsflipable_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSFLIPABLE_H
+#define QMLGRAPHICSFLIPABLE_H
+
+#include "qmlgraphicsitem.h"
+
+#include <QtCore/QObject>
+#include <QtGui/QTransform>
+#include <QtGui/qvector3d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsFlipablePrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsFlipable : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(Side)
+ Q_PROPERTY(QmlGraphicsItem *front READ front WRITE setFront)
+ Q_PROPERTY(QmlGraphicsItem *back READ back WRITE setBack)
+ Q_PROPERTY(Side side READ side NOTIFY sideChanged)
+ //### flipAxis
+ //### flipRotation
+public:
+ QmlGraphicsFlipable(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsFlipable();
+
+ QmlGraphicsItem *front();
+ void setFront(QmlGraphicsItem *);
+
+ QmlGraphicsItem *back();
+ void setBack(QmlGraphicsItem *);
+
+ enum Side { Front, Back };
+ Side side() const;
+
+Q_SIGNALS:
+ void sideChanged();
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsFlipable)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsFlipable)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsFlipable)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSFLIPABLE_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp b/src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp
new file mode 100644
index 0000000..333b689
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsfocuspanel_p.h"
+
+#include <QtGui/qgraphicsscene.h>
+#include <QEvent>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,FocusPanel,QmlGraphicsFocusPanel)
+
+/*!
+ \qmlclass FocusPanel QmlGraphicsFocusPanel
+ \brief The FocusPanel item explicitly creates a focus panel.
+ \inherits Item
+
+ Focus panels assist in keyboard focus handling when building QML
+ applications. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsFocusPanel
+*/
+
+QmlGraphicsFocusPanel::QmlGraphicsFocusPanel(QmlGraphicsItem *parent) :
+ QmlGraphicsItem(parent)
+{
+ setFlag(ItemIsPanel);
+}
+
+QmlGraphicsFocusPanel::~QmlGraphicsFocusPanel()
+{
+}
+
+/*!
+ \qmlproperty bool FocusPanel::active
+
+ Sets whether the item is the active focus panel.
+*/
+
+bool QmlGraphicsFocusPanel::sceneEvent(QEvent *event)
+{
+ if (event->type() == QEvent::WindowActivate ||
+ event->type() == QEvent::WindowDeactivate)
+ emit activeChanged();
+ return QmlGraphicsItem::sceneEvent(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsfocuspanel_p.h b/src/declarative/graphicsitems/qmlgraphicsfocuspanel_p.h
new file mode 100644
index 0000000..4c5cc14
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsfocuspanel_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSFOCUSPANEL_H
+#define QMLGRAPHICSFOCUSPANEL_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsFocusPanel : public QmlGraphicsItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
+public:
+ QmlGraphicsFocusPanel(QmlGraphicsItem *parent=0);
+ virtual ~QmlGraphicsFocusPanel();
+
+Q_SIGNALS:
+ void activeChanged();
+
+protected:
+ bool sceneEvent(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsFocusPanel)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsFocusPanel)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSFOCUSPANEL_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp b/src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp
new file mode 100644
index 0000000..828756c
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsfocusscope_p.h"
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,FocusScope,QmlGraphicsFocusScope)
+
+/*!
+ \qmlclass FocusScope QmlGraphicsFocusScope
+ \brief The FocusScope object explicitly creates a focus scope.
+ \inherits Item
+
+ Focus scopes assist in keyboard focus handling when building reusable QML
+ components. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsFocusScope
+*/
+
+QmlGraphicsFocusScope::QmlGraphicsFocusScope(QmlGraphicsItem *parent) :
+ QmlGraphicsItem(parent)
+{
+ setFlag(QGraphicsItem::ItemIsFocusScope);
+}
+
+QmlGraphicsFocusScope::~QmlGraphicsFocusScope()
+{
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsfocusscope_p.h b/src/declarative/graphicsitems/qmlgraphicsfocusscope_p.h
new file mode 100644
index 0000000..0ea9da5
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsfocusscope_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSFOCUSSCOPE_H
+#define QMLGRAPHICSFOCUSSCOPE_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+//### set component root as focusscope
+class Q_DECLARATIVE_EXPORT QmlGraphicsFocusScope : public QmlGraphicsItem
+{
+ Q_OBJECT
+public:
+ QmlGraphicsFocusScope(QmlGraphicsItem *parent=0);
+ virtual ~QmlGraphicsFocusScope();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsFocusScope)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSFOCUSSCOPE_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer.cpp b/src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer.cpp
new file mode 100644
index 0000000..a5a7935
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsgraphicsobjectcontainer_p.h"
+
+#include "qmlgraphicsitem_p.h"
+
+#include <QGraphicsObject>
+#include <QGraphicsWidget>
+#include <QGraphicsSceneResizeEvent>
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsGraphicsObjectContainerPrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsGraphicsObjectContainer)
+
+public:
+ QmlGraphicsGraphicsObjectContainerPrivate() : QmlGraphicsItemPrivate(), graphicsObject(0), syncedResize(false)
+ { }
+
+ void _q_updateSize();
+
+ void setFiltering(bool on)
+ {
+ Q_Q(QmlGraphicsGraphicsObjectContainer);
+ if (graphicsObject && graphicsObject->isWidget()) {
+ if (!on) {
+ graphicsObject->removeEventFilter(q);
+ QObject::disconnect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize()));
+ QObject::disconnect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize()));
+ } else {
+ graphicsObject->installEventFilter(q);
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize()));
+ }
+ }
+ }
+
+
+ QGraphicsObject *graphicsObject;
+ bool syncedResize;
+};
+
+
+/*!
+ \qmlclass GraphicsObjectContainer QmlGraphicsGraphicsObjectContainer
+ \brief The GraphicsObjectContainer element allows you to add QGraphicsObjects into Fluid UI elements.
+
+ While any QObject based class can be exposed to QML, QmlGraphicsItem
+ provides a lot of important functionality, including anchors and proper
+ management of child items. GraphicsObjectContainer helps provide these
+ functions to other QGraphicsObjects, so that they can be used unaltered in
+ a QML scene. QGraphicsObjects, which are not QmlGraphicsItems, and which are
+ placed in a QML scene outside of a GraphicsObjectContainer, will not appear
+ on screen at all.
+
+ A GraphicsObjectContainer can have one element inside it, and it must be a
+ QGraphicsObject or subclass which has been exposed to the QML engine.
+ The graphics object inside the GraphicsObjectContainer can then be used
+ like any other item in QML with the exception of not being reparentable
+ and not having the standard properties of QML items (such as anchors).
+
+ As the contained object is positioned relative to the container, anchors
+ affecting the container item will affect the onscreen position of the
+ contained item. If synchronizedResizing is set to true, then anchors
+ affecting the container item's size will also affect the contained item's
+ size.
+
+ Example:
+ \code
+ import Qt 4.6
+ import MyApp 2.1 as Widgets
+ Rectangle{
+ id: rect
+ property alias widgetPropertyThree: widget.myThirdProperty;
+ GraphicsObjectContainer{
+ synchronizedResizing: true
+ anchors.margins: 10
+ anchors.fill: parent
+ Widgets.MyWidget{
+ myProperty: "A Value"
+ myOtherProperty: rect.color
+ }
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsGraphicsObjectContainer
+ \brief The QmlGraphicsGraphicsObjectContainer class allows you to add QGraphicsObjects into Fluid UI applications.
+*/
+
+QML_DEFINE_NOCREATE_TYPE(QGraphicsObject)
+QML_DEFINE_TYPE(Qt,4,6,GraphicsObjectContainer,QmlGraphicsGraphicsObjectContainer)
+
+QmlGraphicsGraphicsObjectContainer::QmlGraphicsGraphicsObjectContainer(QmlGraphicsItem *parent)
+: QmlGraphicsItem(*new QmlGraphicsGraphicsObjectContainerPrivate, parent)
+{
+}
+
+QmlGraphicsGraphicsObjectContainer::~QmlGraphicsGraphicsObjectContainer()
+{
+}
+
+QGraphicsObject *QmlGraphicsGraphicsObjectContainer::graphicsObject() const
+{
+ Q_D(const QmlGraphicsGraphicsObjectContainer);
+ return d->graphicsObject;
+}
+
+/*!
+ \qmlproperty QGraphicsObject GraphicsObjectContainer::graphicsObject
+ The QGraphicsObject associated with this element.
+*/
+void QmlGraphicsGraphicsObjectContainer::setGraphicsObject(QGraphicsObject *object)
+{
+ Q_D(QmlGraphicsGraphicsObjectContainer);
+ if (object == d->graphicsObject)
+ return;
+
+ //### remove previously set item?
+
+ d->setFiltering(false);
+
+ d->graphicsObject = object;
+
+ if (d->graphicsObject) {
+ d->graphicsObject->setParentItem(this);
+
+ if (d->syncedResize && d->graphicsObject->isWidget()) {
+ QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(d->graphicsObject);
+ QSizeF gwSize = gw->size(); //### should we use sizeHint?
+ QSizeF newSize = gwSize;
+ if (heightValid())
+ newSize.setHeight(height());
+ if (widthValid())
+ newSize.setWidth(width());
+ if (gwSize != newSize)
+ gw->resize(newSize);
+
+ gwSize = gw->size();
+ setImplicitWidth(gwSize.width());
+ setImplicitHeight(gwSize.height());
+
+ d->setFiltering(true);
+ }
+ }
+}
+
+QVariant QmlGraphicsGraphicsObjectContainer::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QmlGraphicsGraphicsObjectContainer);
+ if (change == ItemSceneHasChanged) {
+ QGraphicsObject *o = d->graphicsObject;
+ d->graphicsObject = 0;
+ setGraphicsObject(o);
+ }
+ return QmlGraphicsItem::itemChange(change, value);
+}
+
+bool QmlGraphicsGraphicsObjectContainer::eventFilter(QObject *watched, QEvent *e)
+{
+ Q_D(QmlGraphicsGraphicsObjectContainer);
+ if (watched == d->graphicsObject && e->type() == QEvent::GraphicsSceneResize) {
+ if (d->graphicsObject && d->graphicsObject->isWidget() && d->syncedResize) {
+ QSizeF newSize = static_cast<QGraphicsWidget*>(d->graphicsObject)->size();
+ setImplicitWidth(newSize.width());
+ setImplicitHeight(newSize.height());
+ }
+ }
+ return QmlGraphicsItem::eventFilter(watched, e);
+}
+
+/*!
+ \qmlproperty bool GraphicsObjectContainer::synchronizedResizing
+
+ This property determines whether or not the container and graphics object will synchronize their
+ sizes.
+
+ \note This property only applies when wrapping a QGraphicsWidget.
+
+ If synchronizedResizing is enabled, the container and widget will
+ synchronize their sizes as follows.
+ \list
+ \o If a size has been set on the container, the widget will be resized to the container.
+ Any changes in the container's size will be reflected in the widget.
+
+ \o \e Otherwise, the container will initially be sized to the preferred size of the widget.
+ Any changes to the container's size will be reflected in the widget, and any changes to the
+ widget's size will be reflected in the container.
+ \endlist
+*/
+bool QmlGraphicsGraphicsObjectContainer::synchronizedResizing() const
+{
+ Q_D(const QmlGraphicsGraphicsObjectContainer);
+ return d->syncedResize;
+}
+
+void QmlGraphicsGraphicsObjectContainer::setSynchronizedResizing(bool on)
+{
+ Q_D(QmlGraphicsGraphicsObjectContainer);
+ if (on == d->syncedResize)
+ return;
+
+ d->syncedResize = on;
+ d->setFiltering(on);
+}
+
+void QmlGraphicsGraphicsObjectContainerPrivate::_q_updateSize()
+{
+ if (!graphicsObject || !graphicsObject->isWidget() || !syncedResize)
+ return;
+
+ QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(graphicsObject);
+ const QSizeF newSize(width, height);
+ gw->resize(newSize);
+
+ //### will respecting the widgets min/max ever get us in trouble? (all other items always
+ // size to exactly what you tell them)
+ /*QSizeF constrainedSize = newSize.expandedTo(gw->minimumSize()).boundedTo(gw->maximumSize());
+ gw->resize(constrainedSize);
+ if (constrainedSize != newSize) {
+ setImplicitWidth(constrainedSize.width());
+ setImplicitHeight(constrainedSize.height());
+ }*/
+}
+
+#include <moc_qmlgraphicsgraphicsobjectcontainer_p.cpp>
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer_p.h b/src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer_p.h
new file mode 100644
index 0000000..1091145
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsgraphicsobjectcontainer_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSGRAPHICSOBJECTCONTAINER_H
+#define QMLGRAPHICSGRAPHICSOBJECTCONTAINER_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QGraphicsObject;
+class QmlGraphicsGraphicsObjectContainerPrivate;
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsGraphicsObjectContainer : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_CLASSINFO("DefaultProperty", "graphicsObject")
+ Q_PROPERTY(QGraphicsObject *graphicsObject READ graphicsObject WRITE setGraphicsObject)
+ Q_PROPERTY(bool synchronizedResizing READ synchronizedResizing WRITE setSynchronizedResizing)
+
+public:
+ QmlGraphicsGraphicsObjectContainer(QmlGraphicsItem *parent = 0);
+ ~QmlGraphicsGraphicsObjectContainer();
+
+ QGraphicsObject *graphicsObject() const;
+ void setGraphicsObject(QGraphicsObject *);
+
+ bool synchronizedResizing() const;
+ void setSynchronizedResizing(bool on);
+
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+ bool eventFilter(QObject *watched, QEvent *e);
+
+private:
+ Q_PRIVATE_SLOT(d_func(), void _q_updateSize())
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsGraphicsObjectContainer)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QGraphicsObject)
+QML_DECLARE_TYPE(QmlGraphicsGraphicsObjectContainer)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSGRAPHICSOBJECTCONTAINER_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsgridview.cpp b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
new file mode 100644
index 0000000..83911c0
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
@@ -0,0 +1,1761 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsgridview_p.h"
+
+#include "qmlgraphicsvisualitemmodel_p.h"
+#include "qmlgraphicsflickable_p_p.h"
+
+#include <qmleasefollow_p.h>
+
+#include <qlistmodelinterface_p.h>
+#include <QKeyEvent>
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsGridViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QmlGraphicsGridViewAttached(QObject *parent)
+ : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+ ~QmlGraphicsGridViewAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(QmlGraphicsGridView *view READ view CONSTANT)
+ QmlGraphicsGridView *view() { return m_view; }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ static QmlGraphicsGridViewAttached *properties(QObject *obj) {
+ QmlGraphicsGridViewAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QmlGraphicsGridViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+Q_SIGNALS:
+ void currentItemChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+
+public:
+ QmlGraphicsGridView *m_view;
+ bool m_isCurrent;
+ bool m_delayRemove;
+
+ static QHash<QObject*, QmlGraphicsGridViewAttached*> attachedProperties;
+};
+
+QHash<QObject*, QmlGraphicsGridViewAttached*> QmlGraphicsGridViewAttached::attachedProperties;
+
+
+//----------------------------------------------------------------------------
+
+class FxGridItem
+{
+public:
+ FxGridItem(QmlGraphicsItem *i, QmlGraphicsGridView *v) : item(i), view(v) {
+ attached = QmlGraphicsGridViewAttached::properties(item);
+ attached->m_view = view;
+ }
+ ~FxGridItem() {}
+
+ qreal rowPos() const { return (view->flow() == QmlGraphicsGridView::LeftToRight ? item->y() : item->x()); }
+ qreal colPos() const { return (view->flow() == QmlGraphicsGridView::LeftToRight ? item->x() : item->y()); }
+ qreal endRowPos() const {
+ return view->flow() == QmlGraphicsGridView::LeftToRight
+ ? item->y() + view->cellHeight() - 1
+ : item->x() + view->cellWidth() - 1;
+ }
+ void setPosition(qreal col, qreal row) {
+ if (view->flow() == QmlGraphicsGridView::LeftToRight) {
+ item->setPos(QPointF(col, row));
+ } else {
+ item->setPos(QPointF(row, col));
+ }
+ }
+
+ QmlGraphicsItem *item;
+ QmlGraphicsGridView *view;
+ QmlGraphicsGridViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QmlGraphicsGridViewPrivate : public QmlGraphicsFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsGridView)
+
+public:
+ QmlGraphicsGridViewPrivate()
+ : currentItem(0), flow(QmlGraphicsGridView::LeftToRight)
+ , visiblePos(0), visibleIndex(0) , currentIndex(-1)
+ , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1)
+ , highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
+ , bufferMode(NoBuffer)
+ , ownModel(false), wrap(false), autoHighlight(true)
+ , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
+ , deferredRelease(false) {}
+
+ void init();
+ void clear();
+ FxGridItem *createItem(int modelIndex);
+ void releaseItem(FxGridItem *item);
+ void refill(qreal from, qreal to, bool doBuffer=false);
+
+ void updateGrid();
+ void scheduleLayout();
+ void layout(bool removed=false);
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void updateCurrent(int modelIndex);
+
+ FxGridItem *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ qreal position() const {
+ Q_Q(const QmlGraphicsGridView);
+ return flow == QmlGraphicsGridView::LeftToRight ? q->viewportY() : q->viewportX();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QmlGraphicsGridView);
+ if (flow == QmlGraphicsGridView::LeftToRight)
+ q->setViewportY(pos);
+ else
+ q->setViewportX(pos);
+ }
+ int size() const {
+ Q_Q(const QmlGraphicsGridView);
+ return flow == QmlGraphicsGridView::LeftToRight ? q->height() : q->width();
+ }
+ qreal startPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
+ return pos;
+ }
+
+ qreal endPosition() const {
+ qreal pos = 0;
+ if (model && model->count())
+ pos = rowPosAt(model->count() - 1) + rowSize();
+ return pos;
+ }
+
+ bool isValid() const {
+ return model && model->count() && model->isValid();
+ }
+
+ int rowSize() const {
+ return flow == QmlGraphicsGridView::LeftToRight ? cellHeight : cellWidth;
+ }
+ int colSize() const {
+ return flow == QmlGraphicsGridView::LeftToRight ? cellWidth : cellHeight;
+ }
+
+ qreal colPosAt(int modelIndex) const {
+ if (FxGridItem *item = visibleItem(modelIndex))
+ return item->colPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = (visibleIndex - modelIndex) % columns;
+ int col = visibleItems.first()->colPos() / colSize();
+ col = (columns - count + col) % columns;
+ return col * colSize();
+ } else {
+ int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
+ return visibleItems.last()->colPos() - count * colSize();
+ }
+ } else {
+ return (modelIndex % columns) * colSize();
+ }
+ return 0;
+ }
+ qreal rowPosAt(int modelIndex) const {
+ if (FxGridItem *item = visibleItem(modelIndex))
+ return item->rowPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int firstCol = visibleItems.first()->colPos() / colSize();
+ int col = visibleIndex - modelIndex + (columns - firstCol - 1);
+ int rows = col / columns;
+ return visibleItems.first()->rowPos() - rows * rowSize();
+ } else {
+ int count = modelIndex - visibleItems.last()->index;
+ int col = visibleItems.last()->colPos() + count * colSize();
+ int rows = col / (columns * colSize());
+ return visibleItems.last()->rowPos() + rows * rowSize();
+ }
+ } else {
+ return (modelIndex / columns) * rowSize();
+ }
+ return 0;
+ }
+
+ FxGridItem *firstVisibleItem() const {
+ const qreal pos = position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ if (item->index != -1 && item->endRowPos() > pos)
+ return item;
+ }
+ return visibleItems.count() ? visibleItems.first() : 0;
+ }
+
+ // Map a model index to visibleItems list index.
+ // These may differ if removed items are still present in the visible list,
+ // e.g. doing a removal animation
+ int mapFromModel(int modelIndex) const {
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i + visibleIndex;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ for (int j = 0; j < visibleItems.count(); j++)
+ qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
+ qFatal("index %d %d %d", visibleIndex, i, listItem->index);
+ }
+ }
+ }
+
+ QGuard<QmlGraphicsVisualModel> model;
+ QVariant modelVariant;
+ QList<FxGridItem*> visibleItems;
+ QHash<QmlGraphicsItem*,int> unrequestedItems;
+ FxGridItem *currentItem;
+ QmlGraphicsGridView::Flow flow;
+ int visiblePos;
+ int visibleIndex;
+ int currentIndex;
+ int cellWidth;
+ int cellHeight;
+ int columns;
+ int requestedIndex;
+ QmlComponent *highlightComponent;
+ FxGridItem *highlight;
+ FxGridItem *trackedItem;
+ enum MovementReason { Other, SetIndex, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QmlEaseFollow *highlightXAnimator;
+ QmlEaseFollow *highlightYAnimator;
+ enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+ BufferMode bufferMode;
+
+ bool ownModel : 1;
+ bool wrap : 1;
+ bool autoHighlight : 1;
+ bool fixCurrentVisibility : 1;
+ bool lazyRelease : 1;
+ bool layoutScheduled : 1;
+ bool deferredRelease : 1;
+};
+
+void QmlGraphicsGridViewPrivate::init()
+{
+ Q_Q(QmlGraphicsGridView);
+ q->setFlag(QGraphicsItem::ItemIsFocusScope);
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(sizeChange()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(sizeChange()));
+ q->setFlickDirection(QmlGraphicsFlickable::VerticalFlick);
+}
+
+void QmlGraphicsGridViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visiblePos = 0;
+ visibleIndex = 0;
+ releaseItem(currentItem);
+ currentItem = 0;
+ createHighlight();
+ trackedItem = 0;
+}
+
+FxGridItem *QmlGraphicsGridViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QmlGraphicsGridView);
+ // create object
+ requestedIndex = modelIndex;
+ FxGridItem *listItem = 0;
+ if (QmlGraphicsItem *item = model->item(modelIndex, false)) {
+ listItem = new FxGridItem(item, q);
+ listItem->index = modelIndex;
+ // complete
+ model->completeItem();
+ listItem->item->setZValue(1);
+ listItem->item->setParent(q->viewport());
+ unrequestedItems.remove(listItem->item);
+ }
+ requestedIndex = 0;
+ return listItem;
+}
+
+
+void QmlGraphicsGridViewPrivate::releaseItem(FxGridItem *item)
+{
+ Q_Q(QmlGraphicsGridView);
+ if (!item || !model)
+ return;
+ if (trackedItem == item) {
+ QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ delete item;
+}
+
+void QmlGraphicsGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+{
+ Q_Q(QmlGraphicsGridView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+
+ qreal bufferFrom = from - buffer;
+ qreal bufferTo = to + buffer;
+ qreal fillFrom = from;
+ qreal fillTo = to;
+ if (doBuffer && (bufferMode & BufferAfter))
+ fillTo = bufferTo;
+ if (doBuffer && (bufferMode & BufferBefore))
+ fillFrom = bufferFrom;
+
+ bool changed = false;
+
+ int colPos = colPosAt(visibleIndex);
+ int rowPos = rowPosAt(visibleIndex);
+ int modelIndex = visibleIndex;
+ if (visibleItems.count()) {
+ rowPos = visibleItems.last()->rowPos();
+ colPos = visibleItems.last()->colPos() + colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+ int colNum = colPos / colSize();
+
+ FxGridItem *item = 0;
+
+ // Item creation and release is staggered in order to avoid
+ // creating/releasing multiple items in one frame
+ // while flicking (as much as possible).
+ while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
+// qDebug() << "refill: append item" << modelIndex;
+ if (!(item = createItem(modelIndex)))
+ break;
+ item->setPosition(colPos, rowPos);
+ visibleItems.append(item);
+ colPos += colSize();
+ colNum++;
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ colNum = 0;
+ rowPos += rowSize();
+ }
+ ++modelIndex;
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (visibleItems.count()) {
+ rowPos = visibleItems.first()->rowPos();
+ colPos = visibleItems.first()->colPos() - colSize();
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ rowPos -= rowSize();
+ }
+ }
+ colNum = colPos / colSize();
+ while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
+// qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+ if (!(item = createItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ item->setPosition(colPos, rowPos);
+ visibleItems.prepend(item);
+ colPos -= colSize();
+ colNum--;
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ colNum = columns-1;
+ rowPos -= rowSize();
+ }
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
+ while (visibleItems.count() > 1
+ && (item = visibleItems.first())
+ && item->endRowPos() < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1
+ && (item = visibleItems.last())
+ && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ deferredRelease = false;
+ } else {
+ deferredRelease = true;
+ }
+ if (changed) {
+ if (flow == QmlGraphicsGridView::LeftToRight)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
+ refill(from, to, true);
+ }
+ lazyRelease = false;
+}
+
+void QmlGraphicsGridViewPrivate::updateGrid()
+{
+ Q_Q(QmlGraphicsGridView);
+ columns = (int)qMax((flow == QmlGraphicsGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
+ if (isValid()) {
+ if (flow == QmlGraphicsGridView::LeftToRight)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QmlGraphicsGridViewPrivate::scheduleLayout()
+{
+ Q_Q(QmlGraphicsGridView);
+ if (!layoutScheduled) {
+ layoutScheduled = true;
+ QMetaObject::invokeMethod(q, "layout", Qt::QueuedConnection);
+ }
+}
+
+void QmlGraphicsGridViewPrivate::layout(bool removed)
+{
+ Q_Q(QmlGraphicsGridView);
+ layoutScheduled = false;
+ if (visibleItems.count()) {
+ qreal rowPos = visibleItems.first()->rowPos();
+ qreal colPos = visibleItems.first()->colPos();
+ int col = visibleIndex % columns;
+ if (colPos != col * colSize()) {
+ if (removed)
+ rowPos -= rowSize();
+ colPos = col * colSize();
+ visibleItems.first()->setPosition(colPos, rowPos);
+ }
+ for (int i = 1; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ item->setPosition(colPos, rowPos);
+ }
+ }
+ q->refill();
+ updateHighlight();
+ moveReason = Other;
+ if (flow == QmlGraphicsGridView::LeftToRight) {
+ q->setViewportHeight(endPosition() - startPosition());
+ fixupY();
+ } else {
+ q->setViewportWidth(endPosition() - startPosition());
+ fixupX();
+ }
+ updateUnrequestedPositions();
+}
+
+void QmlGraphicsGridViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QmlGraphicsGridView);
+ QHash<QmlGraphicsItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QmlGraphicsGridViewPrivate::updateUnrequestedPositions()
+{
+ QHash<QmlGraphicsItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ if (flow == QmlGraphicsGridView::LeftToRight) {
+ it.key()->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
+ } else {
+ it.key()->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
+ }
+ }
+}
+
+void QmlGraphicsGridViewPrivate::updateTrackedItem()
+{
+ Q_Q(QmlGraphicsGridView);
+ FxGridItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ FxGridItem *oldTracked = trackedItem;
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ }
+ if (trackedItem && trackedItem != oldTracked)
+ q->trackedPositionChanged();
+}
+
+void QmlGraphicsGridViewPrivate::createHighlight()
+{
+ Q_Q(QmlGraphicsGridView);
+ bool changed = false;
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ delete highlight->item;
+ delete highlight;
+ highlight = 0;
+ delete highlightXAnimator;
+ delete highlightYAnimator;
+ highlightXAnimator = 0;
+ highlightYAnimator = 0;
+ changed = true;
+ }
+
+ if (currentItem) {
+ QmlGraphicsItem *item = 0;
+ if (highlightComponent) {
+ QmlContext *highlightContext = new QmlContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ highlightContext->setParent(nobj);
+ item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QmlGraphicsItem;
+ item->setParent(q->viewport());
+ }
+ if (item) {
+ item->setParent(q->viewport());
+ highlight = new FxGridItem(item, q);
+ highlightXAnimator = new QmlEaseFollow(q);
+ highlightXAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("x")));
+ highlightXAnimator->setDuration(150);
+ highlightXAnimator->setEnabled(autoHighlight);
+ highlightYAnimator = new QmlEaseFollow(q);
+ highlightYAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("y")));
+ highlightYAnimator->setDuration(150);
+ highlightYAnimator->setEnabled(autoHighlight);
+ changed = true;
+ }
+ }
+ if (changed)
+ emit q->highlightChanged();
+}
+
+void QmlGraphicsGridViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ if (currentItem && autoHighlight && highlight && !moving) {
+ // auto-update highlight
+ highlightXAnimator->setSourceValue(currentItem->item->x());
+ highlightYAnimator->setSourceValue(currentItem->item->y());
+ highlight->item->setWidth(currentItem->item->width());
+ highlight->item->setHeight(currentItem->item->height());
+ }
+ updateTrackedItem();
+}
+
+void QmlGraphicsGridViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QmlGraphicsGridView);
+ if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
+ updateHighlight();
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+
+ FxGridItem *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ fixCurrentVisibility = true;
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ releaseItem(oldCurrentItem);
+}
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass GridView QmlGraphicsGridView
+ \inherits Flickable
+ \brief The GridView item provides a grid view of items provided by a model.
+
+ The model is typically provided by a QAbstractListModel "C++ model object",
+ but can also be created directly in QML.
+
+ The items are laid out top to bottom (vertically) or left to right (horizontally)
+ and may be flicked to scroll.
+
+ The below example creates a very simple grid, using a QML model.
+
+ \image gridview.png
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 3
+
+ The model is defined as a ListModel using QML:
+ \quotefile doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
+
+ In this case ListModel is a handy way for us to test our UI. In practice
+ the model would be implemented in C++, or perhaps via a SQL data source.
+*/
+QmlGraphicsGridView::QmlGraphicsGridView(QmlGraphicsItem *parent)
+ : QmlGraphicsFlickable(*(new QmlGraphicsGridViewPrivate), parent)
+{
+ Q_D(QmlGraphicsGridView);
+ d->init();
+}
+
+QmlGraphicsGridView::~QmlGraphicsGridView()
+{
+ Q_D(QmlGraphicsGridView);
+ d->clear();
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlattachedproperty bool GridView::isCurrentItem
+ This attched property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty GridView GridView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty bool GridView::delayRemove
+ This attached property holds whether the delegate may be destroyed.
+
+ It is attached to each instance of the delegate.
+
+ It is sometimes necessary to delay the destruction of an item
+ until an animation completes.
+
+ The example below ensures that the animation completes before
+ the item is removed from the grid.
+
+ \code
+ Component {
+ id: myDelegate
+ Item {
+ id: wrapper
+ GridView.onRemove: SequentialAnimation {
+ PropertyAction { target: wrapper.GridView; property: "delayRemove"; value: true }
+ NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing: "easeInOutQuad" }
+ PropertyAction { target: wrapper.GridView; property: "delayRemove"; value: false }
+ }
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \qmlattachedsignal GridView::onAdd()
+ This attached handler is called immediately after an item is added to the view.
+*/
+
+/*!
+ \qmlattachedsignal GridView::onRemove()
+ This attached handler is called immediately before an item is removed from the view.
+*/
+
+
+/*!
+ \qmlproperty model GridView::model
+ This property holds the model providing data for the grid.
+
+ The model provides a set of data that is used to create the items
+ for the view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass, a VisualModel, or a simple list.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QmlGraphicsGridView::model() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->modelVariant;
+}
+
+void QmlGraphicsGridView::setModel(const QVariant &model)
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QmlGraphicsItem*)), this, SLOT(destroyingItem(QmlGraphicsItem*)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QmlGraphicsVisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QmlGraphicsVisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ if (isComponentComplete()) {
+ refill();
+ if (d->currentIndex >= d->model->count() || d->currentIndex < 0) {
+ setCurrentIndex(0);
+ } else {
+ d->moveReason = QmlGraphicsGridViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ }
+ }
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QmlGraphicsItem*)), this, SLOT(destroyingItem(QmlGraphicsItem*)));
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty component GridView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ Note that the GridView will layout the items based on the size of the root item
+ in the delegate.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 0
+*/
+QmlComponent *QmlGraphicsGridView::delegate() const
+{
+ Q_D(const QmlGraphicsGridView);
+ if (d->model) {
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QmlGraphicsGridView::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QmlGraphicsGridView);
+ if (delegate == this->delegate())
+ return;
+
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model)) {
+ dataModel->setDelegate(delegate);
+ if (isComponentComplete()) {
+ refill();
+ d->moveReason = QmlGraphicsGridViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ }
+ }
+}
+
+/*!
+ \qmlproperty int GridView::currentIndex
+ \qmlproperty Item GridView::currentItem
+
+ \c currentIndex holds the index of the current item.
+ \c currentItem is the current item. Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QmlGraphicsGridView::currentIndex() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->currentIndex;
+}
+
+void QmlGraphicsGridView::setCurrentIndex(int index)
+{
+ Q_D(QmlGraphicsGridView);
+ if (isComponentComplete() && d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) {
+ d->moveReason = QmlGraphicsGridViewPrivate::SetIndex;
+ cancelFlick();
+ d->updateCurrent(index);
+ } else {
+ d->currentIndex = index;
+ }
+}
+
+QmlGraphicsItem *QmlGraphicsGridView::currentItem()
+{
+ Q_D(QmlGraphicsGridView);
+ if (!d->currentItem)
+ return 0;
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty Item GridView::highlightItem
+
+ \c highlightItem holds the highlight item, which was created
+ from the \l highlight component.
+
+ The highlightItem is managed by the view unless
+ \l highlightFollowsCurrentItem is set to false.
+
+ \sa highlight, highlightFollowsCurrentItem
+*/
+QmlGraphicsItem *QmlGraphicsGridView::highlightItem()
+{
+ Q_D(QmlGraphicsGridView);
+ if (!d->highlight)
+ return 0;
+ return d->highlight->item;
+}
+
+/*!
+ \qmlproperty int GridView::count
+ This property holds the number of items in the view.
+*/
+int QmlGraphicsGridView::count() const
+{
+ Q_D(const QmlGraphicsGridView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty component GridView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each view.
+ The geometry of the resultant component instance will be managed by the view
+ so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
+
+ The below example demonstrates how to make a simple highlight:
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 1
+
+ \sa highlightItem, highlightFollowsCurrentItem
+*/
+QmlComponent *QmlGraphicsGridView::highlight() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->highlightComponent;
+}
+
+void QmlGraphicsGridView::setHighlight(QmlComponent *highlight)
+{
+ Q_D(QmlGraphicsGridView);
+ if (highlight != d->highlightComponent) {
+ d->highlightComponent = highlight;
+ d->updateCurrent(d->currentIndex);
+ }
+}
+
+/*!
+ \qmlproperty bool GridView::highlightFollowsCurrentItem
+ This property sets whether the highlight is managed by the view.
+
+ If highlightFollowsCurrentItem is true, the highlight will be moved smoothly
+ to follow the current item. If highlightFollowsCurrentItem is false, the
+ highlight will not be moved by the view, and must be implemented
+ by the highlight component, for example:
+
+ \code
+ Component {
+ id: myHighlight
+ Rectangle {
+ id: wrapper; color: "lightsteelblue"; radius: 4; width: 320; height: 60 >
+ y: SpringFollow { source: Wrapper.GridView.view.currentItem.y; spring: 3; damping: 0.2 }
+ x: SpringFollow { source: Wrapper.GridView.view.currentItem.x; spring: 3; damping: 0.2 }
+ }
+ }
+ \endcode
+*/
+bool QmlGraphicsGridView::highlightFollowsCurrentItem() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->autoHighlight;
+}
+
+void QmlGraphicsGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->autoHighlight != autoHighlight) {
+ d->autoHighlight = autoHighlight;
+ if (d->highlightXAnimator) {
+ d->highlightXAnimator->setEnabled(d->autoHighlight);
+ d->highlightYAnimator->setEnabled(d->autoHighlight);
+ }
+ d->updateHighlight();
+ }
+}
+
+/*!
+ \qmlproperty enumeration GridView::flow
+ This property holds the flow of the grid.
+
+ Possible values are \c LeftToRight (default) and \c TopToBottom.
+
+ If \a flow is \c LeftToRight, the view will scroll vertically.
+ If \a flow is \c TopToBottom, the view will scroll horizontally.
+*/
+QmlGraphicsGridView::Flow QmlGraphicsGridView::flow() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->flow;
+}
+
+void QmlGraphicsGridView::setFlow(Flow flow)
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->flow != flow) {
+ d->flow = flow;
+ if (d->flow == LeftToRight) {
+ setViewportWidth(-1);
+ setFlickDirection(QmlGraphicsFlickable::VerticalFlick);
+ } else {
+ setViewportHeight(-1);
+ setFlickDirection(QmlGraphicsFlickable::HorizontalFlick);
+ }
+ d->clear();
+ d->updateGrid();
+ refill();
+ d->updateCurrent(d->currentIndex);
+ }
+}
+
+/*!
+ \qmlproperty bool GridView::keyNavigationWraps
+ This property holds whether the grid wraps key navigation
+
+ If this property is true then key presses to move off of one end of the grid will cause the
+ selection to jump to the other side.
+*/
+bool QmlGraphicsGridView::isWrapEnabled() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->wrap;
+}
+
+void QmlGraphicsGridView::setWrapEnabled(bool wrap)
+{
+ Q_D(QmlGraphicsGridView);
+ d->wrap = wrap;
+}
+
+/*!
+ \qmlproperty int GridView::cacheBuffer
+ This property holds the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the view
+ and below the bottom of the view to cache. Setting this value can make
+ scrolling the view smoother at the expense of additional memory usage.
+*/
+int QmlGraphicsGridView::cacheBuffer() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->buffer;
+}
+
+void QmlGraphicsGridView::setCacheBuffer(int buffer)
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->buffer != buffer) {
+ d->buffer = buffer;
+ if (isComponentComplete())
+ refill();
+ }
+}
+
+/*!
+ \qmlproperty int GridView::cellWidth
+ \qmlproperty int GridView::cellHeight
+
+ These properties holds the width and height of each cell in the grid
+
+ The default cell size is 100x100.
+*/
+int QmlGraphicsGridView::cellWidth() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->cellWidth;
+}
+
+void QmlGraphicsGridView::setCellWidth(int cellWidth)
+{
+ Q_D(QmlGraphicsGridView);
+ if (cellWidth != d->cellWidth && cellWidth > 0) {
+ d->cellWidth = qMax(1, cellWidth);
+ d->updateGrid();
+ emit cellWidthChanged();
+ d->layout();
+ }
+}
+
+int QmlGraphicsGridView::cellHeight() const
+{
+ Q_D(const QmlGraphicsGridView);
+ return d->cellHeight;
+}
+
+void QmlGraphicsGridView::setCellHeight(int cellHeight)
+{
+ Q_D(QmlGraphicsGridView);
+ if (cellHeight != d->cellHeight && cellHeight > 0) {
+ d->cellHeight = qMax(1, cellHeight);
+ d->updateGrid();
+ emit cellHeightChanged();
+ d->layout();
+ }
+}
+
+void QmlGraphicsGridView::sizeChange()
+{
+ Q_D(QmlGraphicsGridView);
+ if (isComponentComplete()) {
+ d->updateGrid();
+ d->layout();
+ }
+}
+
+void QmlGraphicsGridView::viewportMoved()
+{
+ Q_D(QmlGraphicsGridView);
+ QmlGraphicsFlickable::viewportMoved();
+ d->lazyRelease = true;
+ if (d->flicked) {
+ if (yflick()) {
+ if (d->velocityY > 0)
+ d->bufferMode = QmlGraphicsGridViewPrivate::BufferBefore;
+ else if (d->velocityY < 0)
+ d->bufferMode = QmlGraphicsGridViewPrivate::BufferAfter;
+ }
+
+ if (xflick()) {
+ if (d->velocityX > 0)
+ d->bufferMode = QmlGraphicsGridViewPrivate::BufferBefore;
+ else if (d->velocityX < 0)
+ d->bufferMode = QmlGraphicsGridViewPrivate::BufferAfter;
+ }
+ }
+ refill();
+}
+
+qreal QmlGraphicsGridView::minYExtent() const
+{
+ Q_D(const QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::TopToBottom)
+ return QmlGraphicsFlickable::minYExtent();
+ return -d->startPosition();
+}
+
+qreal QmlGraphicsGridView::maxYExtent() const
+{
+ Q_D(const QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::TopToBottom)
+ return QmlGraphicsFlickable::maxYExtent();
+ qreal extent = -(d->endPosition() - height());
+ const qreal minY = minYExtent();
+ if (extent > minY)
+ extent = minY;
+ return extent;
+}
+
+qreal QmlGraphicsGridView::minXExtent() const
+{
+ Q_D(const QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::LeftToRight)
+ return QmlGraphicsFlickable::minXExtent();
+ return -d->startPosition();
+}
+
+qreal QmlGraphicsGridView::maxXExtent() const
+{
+ Q_D(const QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::LeftToRight)
+ return QmlGraphicsFlickable::maxXExtent();
+ qreal extent = -(d->endPosition() - width());
+ const qreal minX = minXExtent();
+ if (extent > minX)
+ extent = minX;
+ return extent;
+}
+
+void QmlGraphicsGridView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsGridView);
+ QmlGraphicsFlickable::keyPressEvent(event);
+ if (event->isAccepted())
+ return;
+ if (d->model && d->model->count() && d->interactive) {
+ d->moveReason = QmlGraphicsGridViewPrivate::SetIndex;
+ int oldCurrent = currentIndex();
+ switch (event->key()) {
+ case Qt::Key_Up:
+ moveCurrentIndexUp();
+ break;
+ case Qt::Key_Down:
+ moveCurrentIndexDown();
+ break;
+ case Qt::Key_Left:
+ moveCurrentIndexLeft();
+ break;
+ case Qt::Key_Right:
+ moveCurrentIndexRight();
+ break;
+ default:
+ break;
+ }
+ if (oldCurrent != currentIndex()) {
+ event->accept();
+ return;
+ }
+ }
+ d->moveReason = QmlGraphicsGridViewPrivate::Other;
+ event->ignore();
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexUp()
+
+ Move the currentIndex up one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end.
+*/
+void QmlGraphicsGridView::moveCurrentIndexUp()
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::LeftToRight) {
+ if (currentIndex() >= d->columns || d->wrap) {
+ int index = currentIndex() - d->columns;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ }
+ } else {
+ if (currentIndex() > 0 || d->wrap) {
+ int index = currentIndex() - 1;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ }
+ }
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexDown()
+
+ Move the currentIndex down one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end.
+*/
+void QmlGraphicsGridView::moveCurrentIndexDown()
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::LeftToRight) {
+ if (currentIndex() < d->model->count() - d->columns || d->wrap) {
+ int index = currentIndex()+d->columns;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ }
+ } else {
+ if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ int index = currentIndex() + 1;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ }
+ }
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexLeft()
+
+ Move the currentIndex left one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end.
+*/
+void QmlGraphicsGridView::moveCurrentIndexLeft()
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::LeftToRight) {
+ if (currentIndex() > 0 || d->wrap) {
+ int index = currentIndex() - 1;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ }
+ } else {
+ if (currentIndex() >= d->columns || d->wrap) {
+ int index = currentIndex() - d->columns;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ }
+ }
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexRight()
+
+ Move the currentIndex right one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end.
+*/
+void QmlGraphicsGridView::moveCurrentIndexRight()
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->flow == QmlGraphicsGridView::LeftToRight) {
+ if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ int index = currentIndex() + 1;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ }
+ } else {
+ if (currentIndex() < d->model->count() - d->columns || d->wrap) {
+ int index = currentIndex()+d->columns;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ }
+ }
+}
+
+void QmlGraphicsGridView::positionViewAtIndex(int index)
+{
+ Q_D(QmlGraphicsGridView);
+ if (!d->isValid() || index < 0 || index >= d->model->count())
+ return;
+
+ qreal maxExtent = d->flow == QmlGraphicsGridView::LeftToRight ? -maxYExtent() : -maxXExtent();
+ FxGridItem *item = d->visibleItem(index);
+ if (item) {
+ // Already created - just move to top of view
+ int pos = qMin(item->rowPos(), maxExtent);
+ d->setPosition(pos);
+ } else {
+ int pos = d->rowPosAt(index);
+ // save the currently visible items in case any of them end up visible again
+ QList<FxGridItem*> oldVisible = d->visibleItems;
+ d->visibleItems.clear();
+ d->visibleIndex = index - index % d->columns;
+ d->setPosition(pos);
+ // setPosition() will cause refill. Adjust if we have moved beyond range
+ if (d->position() > maxExtent)
+ d->setPosition(maxExtent);
+ // now release the reference to all the old visible items.
+ for (int i = 0; i < oldVisible.count(); ++i)
+ d->releaseItem(oldVisible.at(i));
+ }
+}
+
+
+void QmlGraphicsGridView::componentComplete()
+{
+ Q_D(QmlGraphicsGridView);
+ QmlGraphicsFlickable::componentComplete();
+ d->updateGrid();
+ refill();
+ if (d->currentIndex < 0)
+ d->updateCurrent(0);
+ else
+ d->updateCurrent(d->currentIndex);
+}
+
+void QmlGraphicsGridView::trackedPositionChanged()
+{
+ Q_D(QmlGraphicsGridView);
+ if (!d->trackedItem || !d->currentItem)
+ return;
+ if (!isFlicking() && !d->moving && d->moveReason == QmlGraphicsGridViewPrivate::SetIndex) {
+ const qreal viewPos = d->position();
+ if (d->trackedItem->rowPos() < viewPos && d->currentItem->rowPos() < viewPos) {
+ d->setPosition(d->currentItem->rowPos() < d->trackedItem->rowPos() ? d->trackedItem->rowPos() : d->currentItem->rowPos());
+ } else if (d->trackedItem->endRowPos() > viewPos + d->size()
+ && d->currentItem->endRowPos() > viewPos + d->size()) {
+ qreal pos;
+ if (d->trackedItem->endRowPos() < d->currentItem->endRowPos()) {
+ pos = d->trackedItem->endRowPos() - d->size();
+ if (d->rowSize() > d->size())
+ pos = d->trackedItem->rowPos();
+ } else {
+ pos = d->currentItem->endRowPos() - d->size();
+ if (d->rowSize() > d->size())
+ pos = d->currentItem->rowPos();
+ }
+ d->setPosition(pos);
+ }
+ }
+}
+
+void QmlGraphicsGridView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QmlGraphicsGridView);
+ if (!d->visibleItems.count() || d->model->count() <= 1) {
+ refill();
+ d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
+ emit countChanged();
+ return;
+ }
+
+ int index = d->mapFromModel(modelIndex);
+ if (index == -1) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ // Special case of appending an item to the model.
+ index = d->visibleIndex + d->visibleItems.count();
+ } else {
+ if (modelIndex <= d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem->index >= modelIndex)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+ }
+
+ // At least some of the added items will be visible
+ int insertCount = count;
+ if (index < d->visibleIndex) {
+ insertCount -= d->visibleIndex - index;
+ index = d->visibleIndex;
+ modelIndex = d->visibleIndex;
+ }
+
+ index -= d->visibleIndex;
+ int to = d->buffer+d->position()+d->size()-1;
+ int colPos, rowPos;
+ if (index < d->visibleItems.count()) {
+ colPos = d->visibleItems.at(index)->colPos();
+ rowPos = d->visibleItems.at(index)->rowPos();
+ } else {
+ // appending items to visible list
+ colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
+ rowPos = d->visibleItems.at(index-1)->rowPos();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ }
+
+ QList<FxGridItem*> added;
+ int i = 0;
+ while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
+ FxGridItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(colPos, rowPos);
+ added.append(item);
+ colPos += d->colSize();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ ++index;
+ ++i;
+ }
+ if (i < insertCount) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index) {
+ d->releaseItem(d->visibleItems.takeLast());
+ }
+ }
+
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
+ }
+ }
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxGridItem *listItem = d->visibleItems.at(index);
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+ d->layout();
+ emit countChanged();
+}
+
+void QmlGraphicsGridView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QmlGraphicsGridView);
+ bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
+ bool removedVisible = false;
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ if (item->index < modelIndex)
+ removedVisible = true;
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ removedVisible = true;
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (currentRemoved) {
+ // current item has been removed.
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (removedVisible) {
+ if (d->visibleItems.isEmpty()) {
+ d->visibleIndex = 0;
+ d->setPosition(0);
+ refill();
+ } else {
+ // Correct the positioning of the items
+ d->scheduleLayout();
+ }
+ }
+
+ emit countChanged();
+}
+
+void QmlGraphicsGridView::layout()
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->layoutScheduled)
+ d->layout();
+}
+
+void QmlGraphicsGridView::destroyRemoved()
+{
+ Q_D(QmlGraphicsGridView);
+ for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxGridItem *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->layout();
+}
+
+void QmlGraphicsGridView::itemsMoved(int from, int to, int count)
+{
+ Q_D(QmlGraphicsGridView);
+ QHash<int,FxGridItem*> moved;
+
+ bool removedBeforeVisible = false;
+ FxGridItem *firstItem = d->firstVisibleItem();
+
+ if (from < to && from < d->visibleIndex && to > d->visibleIndex)
+ removedBeforeVisible = true;
+
+ QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem *item = *it;
+ if (item->index >= from && item->index < from + count) {
+ // take the items that are moving
+ item->index += (to-from);
+ moved.insert(item->index, item);
+ it = d->visibleItems.erase(it);
+ if (item->rowPos() < firstItem->rowPos())
+ removedBeforeVisible = true;
+ } else {
+ if (item->index > from && item->index != -1) {
+ // move everything after the moved items.
+ item->index -= count;
+ if (item->index < d->visibleIndex)
+ d->visibleIndex = item->index;
+ } else if (item->index != -1) {
+ removedBeforeVisible = true;
+ }
+ ++it;
+ }
+ }
+
+ int remaining = count;
+ int endIndex = d->visibleIndex;
+ it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem *item = *it;
+ if (remaining && item->index >= to && item->index < to + count) {
+ // place items in the target position, reusing any existing items
+ FxGridItem *movedItem = moved.take(item->index);
+ if (!movedItem)
+ movedItem = d->createItem(item->index);
+ it = d->visibleItems.insert(it, movedItem);
+ ++it;
+ --remaining;
+ } else {
+ if (item->index != -1) {
+ if (item->index >= to) {
+ // update everything after the moved items.
+ item->index += count;
+ }
+ endIndex = item->index;
+ }
+ ++it;
+ }
+ }
+
+ // If we have moved items to the end of the visible items
+ // then add any existing moved items that we have
+ while (FxGridItem *item = moved.take(endIndex+1)) {
+ d->visibleItems.append(item);
+ ++endIndex;
+ }
+
+ // Whatever moved items remain are no longer visible items.
+ while (moved.count())
+ d->releaseItem(moved.take(moved.begin().key()));
+
+ d->layout(removedBeforeVisible);
+}
+
+void QmlGraphicsGridView::createdItem(int index, QmlGraphicsItem *item)
+{
+ Q_D(QmlGraphicsGridView);
+ item->setParentItem(this);
+ if (d->requestedIndex != index) {
+ item->setParentItem(this);
+ d->unrequestedItems.insert(item, index);
+ if (d->flow == QmlGraphicsGridView::LeftToRight) {
+ item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
+ } else {
+ item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
+ }
+ }
+}
+
+void QmlGraphicsGridView::destroyingItem(QmlGraphicsItem *item)
+{
+ Q_D(QmlGraphicsGridView);
+ d->unrequestedItems.remove(item);
+}
+
+
+void QmlGraphicsGridView::refill()
+{
+ Q_D(QmlGraphicsGridView);
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+
+QmlGraphicsGridViewAttached *QmlGraphicsGridView::qmlAttachedProperties(QObject *obj)
+{
+ return QmlGraphicsGridViewAttached::properties(obj);
+}
+
+QML_DEFINE_TYPE(Qt, 4,6, GridView, QmlGraphicsGridView)
+
+QT_END_NAMESPACE
+
+#include <qmlgraphicsgridview.moc>
diff --git a/src/declarative/graphicsitems/qmlgraphicsgridview_p.h b/src/declarative/graphicsitems/qmlgraphicsgridview_p.h
new file mode 100644
index 0000000..d2ef70e
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsgridview_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSGRIDVIEW_H
+#define QMLGRAPHICSGRIDVIEW_H
+
+#include "qmlgraphicsflickable_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlGraphicsVisualModel;
+class QmlGraphicsGridViewAttached;
+class QmlGraphicsGridViewPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsGridView : public QmlGraphicsFlickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsGridView)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QmlGraphicsItem *currentItem READ currentItem NOTIFY currentIndexChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+ Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight)
+ Q_PROPERTY(QmlGraphicsItem *highlightItem READ highlightItem NOTIFY highlightChanged)
+ Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem)
+
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow)
+ Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer)
+ Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
+ Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ QmlGraphicsGridView(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsGridView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QmlGraphicsItem *currentItem();
+ QmlGraphicsItem *highlightItem();
+ int count() const;
+
+ QmlComponent *highlight() const;
+ void setHighlight(QmlComponent *highlight);
+
+ bool highlightFollowsCurrentItem() const;
+ void setHighlightFollowsCurrentItem(bool);
+
+ Q_ENUMS(Flow)
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ int cellWidth() const;
+ void setCellWidth(int);
+
+ int cellHeight() const;
+ void setCellHeight(int);
+
+ static QmlGraphicsGridViewAttached *qmlAttachedProperties(QObject *);
+
+public Q_SLOTS:
+ void moveCurrentIndexUp();
+ void moveCurrentIndexDown();
+ void moveCurrentIndexLeft();
+ void moveCurrentIndexRight();
+ void positionViewAtIndex(int index);
+
+Q_SIGNALS:
+ void countChanged();
+ void currentIndexChanged();
+ void cellWidthChanged();
+ void cellHeightChanged();
+ void highlightChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void destroyRemoved();
+ void createdItem(int index, QmlGraphicsItem *item);
+ void destroyingItem(QmlGraphicsItem *item);
+ void sizeChange();
+ void layout();
+
+private:
+ void refill();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsGridView)
+QML_DECLARE_TYPEINFO(QmlGraphicsGridView, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsimage.cpp b/src/declarative/graphicsitems/qmlgraphicsimage.cpp
new file mode 100644
index 0000000..7e63c8b
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsimage.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsimage_p.h"
+#include "qmlgraphicsimage_p_p.h"
+
+#include <QKeyEvent>
+#include <QPainter>
+
+QT_BEGIN_NAMESPACE
+
+
+QML_DEFINE_TYPE(Qt,4,6,Image,QmlGraphicsImage)
+
+/*!
+ \qmlclass Image QmlGraphicsImage
+ \brief The Image element allows you to add bitmaps to a scene.
+ \inherits Item
+
+ The Image element supports untransformed, stretched and tiled.
+
+ For an explanation of stretching and tiling, see the fillMode property description.
+
+ Examples:
+ \table
+ \row
+ \o \image declarative-qtlogo1.png
+ \o Untransformed
+ \qml
+ Image { source: "pics/qtlogo.png" }
+ \endqml
+ \row
+ \o \image declarative-qtlogo2.png
+ \o fillMode: Stretch (default)
+ \qml
+ Image {
+ width: 160
+ height: 160
+ source: "pics/qtlogo.png"
+ }
+ \endqml
+ \row
+ \o \image declarative-qtlogo3.png
+ \o fillMode: Tile
+ \qml
+ Image {
+ fillMode: Image.Tile
+ width: 160; height: 160
+ source: "pics/qtlogo.png"
+ }
+ \endqml
+ \row
+ \o \image declarative-qtlogo6.png
+ \o fillMode: TileVertically
+ \qml
+ Image {
+ fillMode: Image.TileVertically
+ width: 160; height: 160
+ source: "pics/qtlogo.png"
+ }
+ \endqml
+ \row
+ \o \image declarative-qtlogo5.png
+ \o fillMode: TileHorizontally
+ \qml
+ Image {
+ fillMode: Image.TileHorizontally
+ width: 160; height: 160
+ source: "pics/qtlogo.png"
+ }
+ \endqml
+ \endtable
+ */
+
+/*!
+ \internal
+ \class QmlGraphicsImage Image
+ \brief The QmlGraphicsImage class provides an image item that you can add to a QmlView.
+
+ \ingroup group_coreitems
+
+ Example:
+ \qml
+ Image { source: "pics/star.png" }
+ \endqml
+
+ A QmlGraphicsImage object can be instantiated in Qml using the tag \l Image.
+*/
+
+QmlGraphicsImage::QmlGraphicsImage(QmlGraphicsItem *parent)
+ : QmlGraphicsImageBase(*(new QmlGraphicsImagePrivate), parent)
+{
+ connect(this, SIGNAL(sourceChanged(QUrl)), this, SLOT(updatePaintedGeometry()));
+}
+
+QmlGraphicsImage::QmlGraphicsImage(QmlGraphicsImagePrivate &dd, QmlGraphicsItem *parent)
+ : QmlGraphicsImageBase(dd, parent)
+{
+}
+
+QmlGraphicsImage::~QmlGraphicsImage()
+{
+}
+
+void QmlGraphicsImage::setSource(const QUrl &url)
+{
+ QmlGraphicsImageBase::setSource(url);
+ updatePaintedGeometry();
+}
+
+/*!
+ \qmlproperty QPixmap Image::pixmap
+
+ This property holds the QPixmap image to display.
+
+ This is useful for displaying images provided by a C++ implementation,
+ for example, a model may provide a data role of type QPixmap.
+*/
+
+QPixmap QmlGraphicsImage::pixmap() const
+{
+ Q_D(const QmlGraphicsImage);
+ return d->pix;
+}
+
+void QmlGraphicsImage::setPixmap(const QPixmap &pix)
+{
+ Q_D(QmlGraphicsImage);
+ if (!d->url.isEmpty())
+ return;
+ d->setPixmap(pix);
+}
+
+void QmlGraphicsImagePrivate::setPixmap(const QPixmap &pixmap)
+{
+ Q_Q(QmlGraphicsImage);
+ pix = pixmap;
+
+ q->setImplicitWidth(pix.width());
+ q->setImplicitHeight(pix.height());
+ status = pix.isNull() ? QmlGraphicsImageBase::Null : QmlGraphicsImageBase::Ready;
+
+ q->update();
+ emit q->pixmapChanged();
+}
+
+/*!
+ \qmlproperty enumeration Image::fillMode
+
+ Set this property to define what happens when the image set for the item is smaller
+ than the size of the item.
+
+ \list
+ \o Stretch - the image is scaled to fit
+ \o PreserveAspectFit - the image is scaled uniformly to fit without cropping
+ \o PreserveAspectCrop - the image is scaled uniformly to fill, cropping if necessary
+ \o Tile - the image is duplicated horizontally and vertically
+ \o TileVertically - the image is stretched horizontally and tiled vertically
+ \o TileHorizontally - the image is stretched vertically and tiled horizontally
+ \endlist
+
+ \image declarative-image_fillMode.gif
+*/
+QmlGraphicsImage::FillMode QmlGraphicsImage::fillMode() const
+{
+ Q_D(const QmlGraphicsImage);
+ return d->fillMode;
+}
+
+void QmlGraphicsImage::setFillMode(FillMode mode)
+{
+ Q_D(QmlGraphicsImage);
+ if (d->fillMode == mode)
+ return;
+ d->fillMode = mode;
+ update();
+ updatePaintedGeometry();
+ emit fillModeChanged();
+}
+
+qreal QmlGraphicsImage::paintedWidth() const
+{
+ Q_D(const QmlGraphicsImage);
+ return d->paintedWidth;
+}
+
+qreal QmlGraphicsImage::paintedHeight() const
+{
+ Q_D(const QmlGraphicsImage);
+ return d->paintedHeight;
+}
+
+/*!
+ \qmlproperty enum Image::status
+
+ This property holds the status of image loading. It can be one of:
+ \list
+ \o Null - no image has been set
+ \o Ready - the image has been loaded
+ \o Loading - the image is currently being loaded
+ \o Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real Image::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+/*!
+ \qmlproperty bool Image::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+void QmlGraphicsImage::updatePaintedGeometry()
+{
+ Q_D(QmlGraphicsImage);
+
+ if (d->fillMode == PreserveAspectFit) {
+ qreal widthScale = width() / qreal(d->pix.width());
+ qreal heightScale = height() / qreal(d->pix.height());
+ if (!d->pix.width() || !d->pix.height())
+ return;
+ if (widthScale <= heightScale) {
+ d->paintedWidth = width();
+ d->paintedHeight = widthScale * qreal(d->pix.height());
+ } else if(heightScale < widthScale) {
+ d->paintedWidth = heightScale * qreal(d->pix.width());
+ d->paintedHeight = height();
+ }
+ } else {
+ d->paintedWidth = width();
+ d->paintedHeight = height();
+ }
+ emit paintedGeometryChanged();
+}
+
+void QmlGraphicsImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QmlGraphicsImageBase::geometryChanged(newGeometry, oldGeometry);
+ updatePaintedGeometry();
+}
+
+/*!
+ \qmlproperty url Image::source
+
+ Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
+
+ The URL may be absolute, or relative to the URL of the component.
+*/
+
+void QmlGraphicsImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QmlGraphicsImage);
+ if (d->pix.isNull())
+ return;
+
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+
+ if (width() != d->pix.width() || height() != d->pix.height()) {
+ if (d->fillMode >= Tile) {
+ if (d->fillMode == Tile)
+ p->drawTiledPixmap(QRectF(0,0,width(),height()), d->pix);
+ else if (d->fillMode == TileVertically)
+ p->drawTiledPixmap(QRectF(0,0,d->pix.width(),height()), d->pix);
+ else
+ p->drawTiledPixmap(QRectF(0,0,width(),d->pix.height()), d->pix);
+ } else {
+ qreal widthScale = width() / qreal(d->pix.width());
+ qreal heightScale = height() / qreal(d->pix.height());
+
+ QTransform scale;
+
+ if (d->fillMode == PreserveAspectFit) {
+ if (widthScale <= heightScale) {
+ heightScale = widthScale;
+ scale.translate(0, (height() - heightScale * d->pix.height()) / 2);
+ } else if(heightScale < widthScale) {
+ widthScale = heightScale;
+ scale.translate((width() - widthScale * d->pix.width()) / 2, 0);
+ }
+ } else if (d->fillMode == PreserveAspectCrop) {
+ if (widthScale < heightScale) {
+ widthScale = heightScale;
+ scale.translate((width() - widthScale * d->pix.width()) / 2, 0);
+ } else if(heightScale < widthScale) {
+ heightScale = widthScale;
+ scale.translate(0, (height() - heightScale * d->pix.height()) / 2);
+ }
+ }
+ if (clip()) {
+ p->save();
+ p->setClipRect(boundingRect(), Qt::IntersectClip);
+ }
+ scale.scale(widthScale, heightScale);
+ QTransform old = p->transform();
+ p->setWorldTransform(scale * old);
+ p->drawPixmap(0, 0, d->pix);
+ p->setWorldTransform(old);
+ if (clip()) {
+ p->restore();
+ }
+ }
+ } else {
+ p->drawPixmap(0, 0, d->pix);
+ }
+
+ if (d->smooth) {
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsimage_p.h b/src/declarative/graphicsitems/qmlgraphicsimage_p.h
new file mode 100644
index 0000000..dde5d79
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsimage_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSIMAGE_H
+#define QMLGRAPHICSIMAGE_H
+
+#include "qmlgraphicsimagebase_p.h"
+
+#include <QtNetwork/qnetworkreply.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsImagePrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsImage : public QmlGraphicsImageBase
+{
+ Q_OBJECT
+ Q_ENUMS(FillMode)
+
+ Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap NOTIFY pixmapChanged DESIGNABLE false)
+ Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
+ Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged)
+ Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged)
+
+public:
+ QmlGraphicsImage(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsImage();
+
+ enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally };
+ FillMode fillMode() const;
+ void setFillMode(FillMode);
+
+ QPixmap pixmap() const;
+ void setPixmap(const QPixmap &);
+
+ qreal paintedWidth() const;
+ qreal paintedHeight() const;
+
+ void setSource(const QUrl &url);
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+Q_SIGNALS:
+ void fillModeChanged();
+ void paintedGeometryChanged();
+
+protected:
+ QmlGraphicsImage(QmlGraphicsImagePrivate &dd, QmlGraphicsItem *parent);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+
+protected Q_SLOTS:
+ void updatePaintedGeometry();
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsImage)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsImage)
+};
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QmlGraphicsImage)
+QT_END_HEADER
+
+#endif // QMLGRAPHICSIMAGE_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h b/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h
new file mode 100644
index 0000000..3a5acca
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSIMAGE_P_H
+#define QMLGRAPHICSIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem_p.h"
+#include "qmlgraphicsimagebase_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsImagePrivate : public QmlGraphicsImageBasePrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsImage)
+
+public:
+ QmlGraphicsImagePrivate()
+ : fillMode(QmlGraphicsImage::Stretch), paintedWidth(0), paintedHeight(0)
+ {
+ }
+
+ QmlGraphicsImage::FillMode fillMode;
+ qreal paintedWidth;
+ qreal paintedHeight;
+ void setPixmap(const QPixmap &pix);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSIMAGE_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
new file mode 100644
index 0000000..08617ac
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsimagebase_p.h"
+#include "qmlgraphicsimagebase_p_p.h"
+
+#include <qmlengine.h>
+#include <qmlpixmapcache_p.h>
+
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+QmlGraphicsImageBase::QmlGraphicsImageBase(QmlGraphicsImageBasePrivate &dd, QmlGraphicsItem *parent)
+ : QmlGraphicsItem(dd, parent)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+}
+
+QmlGraphicsImageBase::~QmlGraphicsImageBase()
+{
+ Q_D(QmlGraphicsImageBase);
+ if (d->pendingPixmapCache)
+ QmlPixmapCache::cancel(d->url, this);
+}
+
+QmlGraphicsImageBase::Status QmlGraphicsImageBase::status() const
+{
+ Q_D(const QmlGraphicsImageBase);
+ return d->status;
+}
+
+
+qreal QmlGraphicsImageBase::progress() const
+{
+ Q_D(const QmlGraphicsImageBase);
+ return d->progress;
+}
+
+QUrl QmlGraphicsImageBase::source() const
+{
+ Q_D(const QmlGraphicsImageBase);
+ return d->url;
+}
+
+void QmlGraphicsImageBase::setSource(const QUrl &url)
+{
+ Q_D(QmlGraphicsImageBase);
+ //equality is fairly expensive, so we bypass for simple, common case
+ if ((d->url.isEmpty() == url.isEmpty()) && url == d->url)
+ return;
+
+ if (d->pendingPixmapCache) {
+ QmlPixmapCache::cancel(d->url, this);
+ d->pendingPixmapCache = false;
+ }
+
+ d->url = url;
+ if (d->progress != 0.0) {
+ d->progress = 0.0;
+ emit progressChanged(d->progress);
+ }
+
+ if (url.isEmpty()) {
+ d->pix = QPixmap();
+ d->status = Null;
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit pixmapChanged();
+ update();
+ } else {
+ d->status = Loading;
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->pix);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url);
+ d->pendingPixmapCache = true;
+
+ static int replyDownloadProgress = -1;
+ static int replyFinished = -1;
+ static int thisRequestProgress = -1;
+ static int thisRequestFinished = -1;
+ if (replyDownloadProgress == -1) {
+ replyDownloadProgress =
+ QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished =
+ QmlPixmapReply::staticMetaObject.indexOfSignal("finished()");
+ thisRequestProgress =
+ QmlGraphicsImageBase::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
+ thisRequestFinished =
+ QmlGraphicsImageBase::staticMetaObject.indexOfSlot("requestFinished()");
+ }
+
+ QMetaObject::connect(reply, replyFinished, this,
+ thisRequestFinished, Qt::DirectConnection);
+ QMetaObject::connect(reply, replyDownloadProgress, this,
+ thisRequestProgress, Qt::DirectConnection);
+ } else {
+ //### should be unified with requestFinished
+ if (status == QmlPixmapReply::Ready) {
+ setImplicitWidth(d->pix.width());
+ setImplicitHeight(d->pix.height());
+
+ if (d->status == Loading)
+ d->status = Ready;
+ } else {
+ d->status = Error;
+ }
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit progressChanged(d->progress);
+ emit pixmapChanged();
+ update();
+ }
+ }
+
+ emit statusChanged(d->status);
+}
+
+void QmlGraphicsImageBase::requestFinished()
+{
+ Q_D(QmlGraphicsImageBase);
+
+ d->pendingPixmapCache = false;
+
+ if (QmlPixmapCache::get(d->url, &d->pix) != QmlPixmapReply::Ready)
+ d->status = Error;
+ setImplicitWidth(d->pix.width());
+ setImplicitHeight(d->pix.height());
+
+ if (d->status == Loading)
+ d->status = Ready;
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit progressChanged(1.0);
+ emit pixmapChanged();
+ update();
+}
+
+void QmlGraphicsImageBase::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QmlGraphicsImageBase);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsimagebase_p.h b/src/declarative/graphicsitems/qmlgraphicsimagebase_p.h
new file mode 100644
index 0000000..61ea975
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsimagebase_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSIMAGEBASE_H
+#define QMLGRAPHICSIMAGEBASE_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsImageBasePrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsImageBase : public QmlGraphicsItem
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+
+public:
+ ~QmlGraphicsImageBase();
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ QUrl source() const;
+ virtual void setSource(const QUrl &url);
+
+Q_SIGNALS:
+ void sourceChanged(const QUrl &);
+ void statusChanged(Status);
+ void progressChanged(qreal progress);
+ void pixmapChanged();
+
+protected:
+ QmlGraphicsImageBase(QmlGraphicsImageBasePrivate &dd, QmlGraphicsItem *parent);
+
+private Q_SLOTS:
+ virtual void requestFinished();
+ void requestProgress(qint64,qint64);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsImageBase)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsImageBase)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSIMAGEBASE_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsimagebase_p_p.h b/src/declarative/graphicsitems/qmlgraphicsimagebase_p_p.h
new file mode 100644
index 0000000..44b2332
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsimagebase_p_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSIMAGEBASE_P_H
+#define QMLGRAPHICSIMAGEBASE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem_p.h"
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+class QmlGraphicsImageBasePrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsImageBase)
+
+public:
+ QmlGraphicsImageBasePrivate()
+ : status(QmlGraphicsImageBase::Null),
+ progress(0.0),
+ pendingPixmapCache(false)
+ {
+ }
+
+ QPixmap pix;
+ QmlGraphicsImageBase::Status status;
+ QUrl url;
+ qreal progress;
+ bool pendingPixmapCache;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
new file mode 100644
index 0000000..8973cb4
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
@@ -0,0 +1,3099 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsitem_p.h"
+#include "qmlgraphicsitem.h"
+
+#include "qmlgraphicsevents_p_p.h"
+
+#include <qfxperf_p_p.h>
+#include <qmlengine.h>
+#include <qmlopenmetaobject_p.h>
+#include <qmlstate_p.h>
+#include <qmlview.h>
+#include <qmlstategroup_p.h>
+#include <qmlcomponent.h>
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QGraphicsSceneMouseEvent>
+#include <QtCore/qnumeric.h>
+#include <QtScript/qscriptengine.h>
+#include <QtGui/qgraphicstransform.h>
+#include <QtGui/qgraphicseffect.h>
+#include <qlistmodelinterface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef FLT_MAX
+#define FLT_MAX 1E+37
+#endif
+
+QML_DEFINE_TYPE(Qt,4,6,Item,QmlGraphicsItem)
+
+QML_DEFINE_NOCREATE_TYPE(QGraphicsTransform);
+QML_DEFINE_TYPE(Qt,4,6,Scale,QGraphicsScale)
+QML_DEFINE_TYPE(Qt,4,6,Rotation,QGraphicsRotation)
+
+#include "qmlgraphicseffects.cpp"
+
+/*!
+ \qmlclass Transform QGraphicsTransform
+ \brief The Transform elements provide a way of building advanced transformations on Items.
+
+ The Transform elements let you create and control advanced transformations that can be configured
+ independently using specialized properties.
+
+ You can assign any number of Transform elements to an Item. Each Transform is applied in order,
+ one at a time, to the Item it's assigned to.
+
+ \sa Rotation, Scale
+*/
+
+/*!
+ \qmlclass Scale QGraphicsScale
+ \brief The Scale object provides a way to scale an Item.
+
+ The Scale object gives more control over scaling than using Item's scale property. Specifically,
+ it allows a different scale for the x and y axes, and allows the scale to be relative to an
+ arbitrary point.
+
+ The following example scales the X axis of the Rectangle, relative to its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty real Scale::origin.x
+ \qmlproperty real Scale::origin.y
+
+ The point that the item is scaled from (i.e., the point that stays fixed relative to the parent as
+ the rest of the item grows). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real Scale::xScale
+
+ The scaling factor for the X axis.
+*/
+
+/*!
+ \qmlproperty real Scale::yScale
+
+ The scaling factor for the Y axis.
+*/
+
+/*!
+ \qmlclass Rotation QGraphicsRotation
+ \brief The Rotation object provides a way to rotate an Item.
+
+ The Rotation object gives more control over rotation than using Item's rotation property.
+ Specifically, it allows (z axis) rotation to be relative to an arbitrary point.
+
+ The following example rotates a Rectangle around its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
+ }
+ \endqml
+
+ Rotation also provides a way to specify 3D-like rotations for Items. For these types of
+ rotations you must specify the axis to rotate around in addition to the origin point.
+
+ The following example shows various 3D-like rotations applied to an \l Image.
+ \snippet doc/src/snippets/declarative/rotation.qml 0
+
+ \image axisrotation.png
+*/
+
+/*!
+ \qmlproperty real Rotation::origin.x
+ \qmlproperty real Rotation::origin.y
+
+ The origin point of the rotation (i.e., the point that stays fixed relative to the parent as
+ the rest of the item rotates). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real Rotation::axis.x
+ \qmlproperty real Rotation::axis.y
+ \qmlproperty real Rotation::axis.z
+
+ The axis to rotate around. For simple (2D) rotation around a point, you do not need to specify an axis,
+ as the default axis is the z axis (\c{ axis { x: 0; y: 0; z: 1 } }).
+
+ For a typical 3D-like rotation you will usually specify both the origin and the axis.
+
+ \image 3d-rotation-axis.png
+*/
+
+/*!
+ \qmlproperty real Rotation::angle
+
+ The angle to rotate, in degrees clockwise.
+*/
+
+
+/*!
+ \group group_animation
+ \title Animation
+*/
+
+/*!
+ \group group_coreitems
+ \title Basic Items
+*/
+
+/*!
+ \group group_effects
+ \title Effects
+*/
+
+/*!
+ \group group_layouts
+ \title Layouts
+*/
+
+/*!
+ \group group_states
+ \title States and Transitions
+*/
+
+/*!
+ \group group_utility
+ \title Utility
+*/
+
+/*!
+ \group group_views
+ \title Views
+*/
+
+/*!
+ \group group_widgets
+ \title Widgets
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsContents
+ \ingroup group_utility
+ \brief The QmlGraphicsContents class gives access to the height and width of an item's contents.
+
+*/
+
+QmlGraphicsContents::QmlGraphicsContents() : m_x(0), m_y(0), m_width(0), m_height(0)
+{
+}
+
+/*!
+ \qmlproperty real Item::childrenRect.x
+ \qmlproperty real Item::childrenRect.y
+ \qmlproperty real Item::childrenRect.width
+ \qmlproperty real Item::childrenRect.height
+
+ The childrenRect properties allow an item access to the geometry of its
+ children. This property is useful if you have an item that needs to be
+ sized to fit its children.
+*/
+
+QRectF QmlGraphicsContents::rectF() const
+{
+ return QRectF(m_x, m_y, m_width, m_height);
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QmlGraphicsContents::calcHeight()
+{
+ qreal oldy = m_y;
+ qreal oldheight = m_height;
+
+ qreal top = FLT_MAX;
+ qreal bottom = 0;
+
+ QList<QGraphicsItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(children.at(i));
+ if(!child)//### Should this be ignoring non-QmlGraphicsItem graphicsobjects?
+ continue;
+ qreal y = child->y();
+ if (y + child->height() > bottom)
+ bottom = y + child->height();
+ if (y < top)
+ top = y;
+ }
+ if (!children.isEmpty())
+ m_y = top;
+ m_height = qMax(bottom - top, qreal(0.0));
+
+ if (m_height != oldheight || m_y != oldy)
+ emit rectChanged();
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QmlGraphicsContents::calcWidth()
+{
+ qreal oldx = m_x;
+ qreal oldwidth = m_width;
+
+ qreal left = FLT_MAX;
+ qreal right = 0;
+
+ QList<QGraphicsItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(children.at(i));
+ if(!child)//### Should this be ignoring non-QmlGraphicsItem graphicsobjects?
+ continue;
+ qreal x = child->x();
+ if (x + child->width() > right)
+ right = x + child->width();
+ if (x < left)
+ left = x;
+ }
+ if (!children.isEmpty())
+ m_x = left;
+ m_width = qMax(right - left, qreal(0.0));
+
+ if (m_width != oldwidth || m_x != oldx)
+ emit rectChanged();
+}
+
+void QmlGraphicsContents::setItem(QmlGraphicsItem *item)
+{
+ m_item = item;
+
+ QList<QGraphicsItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(children.at(i));
+ if(!child)//### Should this be ignoring non-QmlGraphicsItem graphicsobjects?
+ continue;
+ connect(child, SIGNAL(heightChanged()), this, SLOT(calcHeight()));
+ connect(child, SIGNAL(yChanged()), this, SLOT(calcHeight()));
+ connect(child, SIGNAL(widthChanged()), this, SLOT(calcWidth()));
+ connect(child, SIGNAL(xChanged()), this, SLOT(calcWidth()));
+ connect(this, SIGNAL(rectChanged()), m_item, SIGNAL(childrenRectChanged()));
+ }
+
+ calcHeight();
+ calcWidth();
+}
+
+/*
+ Key filters can be installed on a QmlGraphicsItem, but not removed. Currently they
+ are only used by attached objects (which are only destroyed on Item
+ destruction), so this isn't a problem. If in future this becomes any form
+ of public API, they will have to support removal too.
+*/
+class QmlGraphicsItemKeyFilter
+{
+public:
+ QmlGraphicsItemKeyFilter(QmlGraphicsItem * = 0);
+ virtual ~QmlGraphicsItemKeyFilter();
+
+ virtual void keyPressed(QKeyEvent *event);
+ virtual void keyReleased(QKeyEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *event);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ virtual void componentComplete();
+
+private:
+ QmlGraphicsItemKeyFilter *m_next;
+};
+
+QmlGraphicsItemKeyFilter::QmlGraphicsItemKeyFilter(QmlGraphicsItem *item)
+: m_next(0)
+{
+ QmlGraphicsItemPrivate *p =
+ item?static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(item)):0;
+ if (p) {
+ m_next = p->keyHandler;
+ p->keyHandler = this;
+ }
+}
+
+QmlGraphicsItemKeyFilter::~QmlGraphicsItemKeyFilter()
+{
+}
+
+void QmlGraphicsItemKeyFilter::keyPressed(QKeyEvent *event)
+{
+ if (m_next) m_next->keyPressed(event);
+}
+
+void QmlGraphicsItemKeyFilter::keyReleased(QKeyEvent *event)
+{
+ if (m_next) m_next->keyReleased(event);
+}
+
+void QmlGraphicsItemKeyFilter::inputMethodEvent(QInputMethodEvent *event)
+{
+ if (m_next) m_next->inputMethodEvent(event);
+}
+
+QVariant QmlGraphicsItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ if (m_next) return m_next->inputMethodQuery(query);
+ return QVariant();
+}
+
+void QmlGraphicsItemKeyFilter::componentComplete()
+{
+ if (m_next) m_next->componentComplete();
+}
+
+
+/*!
+ \qmlclass KeyNavigation
+ \brief The KeyNavigation attached property supports key navigation by arrow keys.
+
+ It is common in key-based UIs to use arrow keys to navigate
+ between focussed items. The KeyNavigation property provides a
+ convenient way of specifying which item will gain focus
+ when an arrow key is pressed. The following example provides
+ key navigation for a 2x2 grid of items.
+
+ \code
+ Grid {
+ columns: 2
+ width: 100; height: 100
+ Rectangle {
+ id: item1
+ focus: true
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.right: item2
+ KeyNavigation.down: item3
+ }
+ Rectangle {
+ id: item2
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.left: item1
+ KeyNavigation.down: item4
+ }
+ Rectangle {
+ id: item3
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.right: item4
+ KeyNavigation.up: item1
+ }
+ Rectangle {
+ id: item4
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.left: item3
+ KeyNavigation.up: item2
+ }
+ }
+ \endcode
+
+ KeyNavigation receives key events after the item it is attached to.
+ If the item accepts an arrow key event, the KeyNavigation
+ attached property will not receive an event for that key.
+
+ If an item has been set for a direction and the KeyNavigation
+ attached property receives the corresponding
+ key press and release events, the events will be accepted by
+ KeyNaviagtion and will not propagate any further.
+
+ \sa {Keys}{Keys attached property}
+*/
+
+/*!
+ \qmlproperty Item KeyNavigation::left
+ \qmlproperty Item KeyNavigation::right
+ \qmlproperty Item KeyNavigation::up
+ \qmlproperty Item KeyNavigation::down
+
+ These properties hold the item to assign focus to
+ when Key_Left, Key_Right, Key_Up or Key_Down are
+ pressed.
+*/
+
+class QmlGraphicsKeyNavigationAttachedPrivate : public QObjectPrivate
+{
+public:
+ QmlGraphicsKeyNavigationAttachedPrivate()
+ : QObjectPrivate(), left(0), right(0), up(0), down(0) {}
+
+ QmlGraphicsItem *left;
+ QmlGraphicsItem *right;
+ QmlGraphicsItem *up;
+ QmlGraphicsItem *down;
+};
+
+class QmlGraphicsKeyNavigationAttached : public QObject, public QmlGraphicsItemKeyFilter
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlGraphicsKeyNavigationAttached)
+
+ Q_PROPERTY(QmlGraphicsItem *left READ left WRITE setLeft NOTIFY changed)
+ Q_PROPERTY(QmlGraphicsItem *right READ right WRITE setRight NOTIFY changed)
+ Q_PROPERTY(QmlGraphicsItem *up READ up WRITE setUp NOTIFY changed)
+ Q_PROPERTY(QmlGraphicsItem *down READ down WRITE setDown NOTIFY changed)
+public:
+ QmlGraphicsKeyNavigationAttached(QObject * = 0);
+
+ QmlGraphicsItem *left() const;
+ void setLeft(QmlGraphicsItem *);
+ QmlGraphicsItem *right() const;
+ void setRight(QmlGraphicsItem *);
+ QmlGraphicsItem *up() const;
+ void setUp(QmlGraphicsItem *);
+ QmlGraphicsItem *down() const;
+ void setDown(QmlGraphicsItem *);
+
+ static QmlGraphicsKeyNavigationAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void changed();
+
+private:
+ virtual void keyPressed(QKeyEvent *event);
+ virtual void keyReleased(QKeyEvent *event);
+};
+
+QmlGraphicsKeyNavigationAttached::QmlGraphicsKeyNavigationAttached(QObject *parent)
+: QObject(*(new QmlGraphicsKeyNavigationAttachedPrivate), parent),
+ QmlGraphicsItemKeyFilter(qobject_cast<QmlGraphicsItem*>(parent))
+{
+}
+
+QmlGraphicsKeyNavigationAttached *
+QmlGraphicsKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
+{
+ return new QmlGraphicsKeyNavigationAttached(obj);
+}
+
+QmlGraphicsItem *QmlGraphicsKeyNavigationAttached::left() const
+{
+ Q_D(const QmlGraphicsKeyNavigationAttached);
+ return d->left;
+}
+
+void QmlGraphicsKeyNavigationAttached::setLeft(QmlGraphicsItem *i)
+{
+ Q_D(QmlGraphicsKeyNavigationAttached);
+ d->left = i;
+ emit changed();
+}
+
+QmlGraphicsItem *QmlGraphicsKeyNavigationAttached::right() const
+{
+ Q_D(const QmlGraphicsKeyNavigationAttached);
+ return d->right;
+}
+
+void QmlGraphicsKeyNavigationAttached::setRight(QmlGraphicsItem *i)
+{
+ Q_D(QmlGraphicsKeyNavigationAttached);
+ d->right = i;
+ emit changed();
+}
+
+QmlGraphicsItem *QmlGraphicsKeyNavigationAttached::up() const
+{
+ Q_D(const QmlGraphicsKeyNavigationAttached);
+ return d->up;
+}
+
+void QmlGraphicsKeyNavigationAttached::setUp(QmlGraphicsItem *i)
+{
+ Q_D(QmlGraphicsKeyNavigationAttached);
+ d->up = i;
+ emit changed();
+}
+
+QmlGraphicsItem *QmlGraphicsKeyNavigationAttached::down() const
+{
+ Q_D(const QmlGraphicsKeyNavigationAttached);
+ return d->down;
+}
+
+void QmlGraphicsKeyNavigationAttached::setDown(QmlGraphicsItem *i)
+{
+ Q_D(QmlGraphicsKeyNavigationAttached);
+ d->down = i;
+ emit changed();
+}
+
+void QmlGraphicsKeyNavigationAttached::keyPressed(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsKeyNavigationAttached);
+
+ event->ignore();
+
+ switch(event->key()) {
+ case Qt::Key_Left:
+ if (d->left) {
+ d->left->setFocus(true);
+ event->accept();
+ }
+ break;
+ case Qt::Key_Right:
+ if (d->right) {
+ d->right->setFocus(true);
+ event->accept();
+ }
+ break;
+ case Qt::Key_Up:
+ if (d->up) {
+ d->up->setFocus(true);
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (d->down) {
+ d->down->setFocus(true);
+ event->accept();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!event->isAccepted()) QmlGraphicsItemKeyFilter::keyPressed(event);
+}
+
+void QmlGraphicsKeyNavigationAttached::keyReleased(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsKeyNavigationAttached);
+
+ event->ignore();
+
+ switch(event->key()) {
+ case Qt::Key_Left:
+ if (d->left) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Right:
+ if (d->right) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Up:
+ if (d->up) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (d->down) {
+ event->accept();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!event->isAccepted()) QmlGraphicsItemKeyFilter::keyReleased(event);
+}
+
+/*!
+ \qmlclass Keys
+ \brief The Keys attached property provides key handling to Items.
+
+ All visual primitives support key handling via the \e Keys
+ attached property. Keys can be handled via the \e onPressed
+ and \e onReleased signal properties.
+
+ The signal properties have a \l KeyEvent parameter, named
+ \e event which contains details of the event. If a key is
+ handled \e event.accepted should be set to true to prevent the
+ event from propagating up the item heirarchy.
+
+ \code
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Left) {
+ console.log("move left");
+ event.accepted = true;
+ }
+ }
+ }
+ \endcode
+
+ Some keys may alternatively be handled via specific signal properties,
+ for example \e onSelectPressed. These handlers automatically set
+ \e event.accepted to true.
+
+ \code
+ Item {
+ focus: true
+ Keys.onLeftPressed: console.log("move left")
+ }
+ \endcode
+
+ See \l {Qt::Key}{Qt.Key} for the list of keyboard codes.
+
+ \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
+*/
+
+/*!
+ \qmlproperty bool Keys::enabled
+
+ This flags enables key handling if true (default); otherwise
+ no key handlers will be called.
+*/
+
+/*!
+ \qmlproperty List<Object> Keys::forwardTo
+
+ This property provides a way to forward key presses, key releases, and keyboard input
+ coming from input methods to other items. This can be useful when you want
+ one item to handle some keys (e.g. the up and down arrow keys), and another item to
+ handle other keys (e.g. the left and right arrow keys). Once an item that has been
+ forwarded keys accepts the event it is no longer forwarded to items later in the
+ list.
+
+ This example forwards key events to two lists:
+ \qml
+ ListView { id: list1 ... }
+ ListView { id: list2 ... }
+ Keys.forwardTo: [list1, list2]
+ focus: true
+ \endqml
+*/
+
+/*!
+ \qmlsignal Keys::onPressed(event)
+
+ This handler is called when a key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onReleased(event)
+
+ This handler is called when a key has been released. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit0Pressed(event)
+
+ This handler is called when the digit '0' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit1Pressed(event)
+
+ This handler is called when the digit '1' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit2Pressed(event)
+
+ This handler is called when the digit '2' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit3Pressed(event)
+
+ This handler is called when the digit '3' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit4Pressed(event)
+
+ This handler is called when the digit '4' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit5Pressed(event)
+
+ This handler is called when the digit '5' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit6Pressed(event)
+
+ This handler is called when the digit '6' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit7Pressed(event)
+
+ This handler is called when the digit '7' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit8Pressed(event)
+
+ This handler is called when the digit '8' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit9Pressed(event)
+
+ This handler is called when the digit '9' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onLeftPressed(event)
+
+ This handler is called when the Left arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onRightPressed(event)
+
+ This handler is called when the Right arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onUpPressed(event)
+
+ This handler is called when the Up arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDownPressed(event)
+
+ This handler is called when the Down arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onAsteriskPressed(event)
+
+ This handler is called when the Asterisk '*' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onEscapePressed(event)
+
+ This handler is called when the Escape key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onReturnPressed(event)
+
+ This handler is called when the Return key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onEnterPressed(event)
+
+ This handler is called when the Enter key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDeletePressed(event)
+
+ This handler is called when the Delete key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onSpacePressed(event)
+
+ This handler is called when the Space key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onBackPressed(event)
+
+ This handler is called when the Back key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onCancelPressed(event)
+
+ This handler is called when the Cancel key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onSelectPressed(event)
+
+ This handler is called when the Select key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onYesPressed(event)
+
+ This handler is called when the Yes key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onNoPressed(event)
+
+ This handler is called when the No key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext1Pressed(event)
+
+ This handler is called when the Context1 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext2Pressed(event)
+
+ This handler is called when the Context2 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext3Pressed(event)
+
+ This handler is called when the Context3 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext4Pressed(event)
+
+ This handler is called when the Context4 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onCallPressed(event)
+
+ This handler is called when the Call key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onHangupPressed(event)
+
+ This handler is called when the Hangup key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onFlipPressed(event)
+
+ This handler is called when the Flip key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onMenuPressed(event)
+
+ This handler is called when the Menu key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onVolumeUpPressed(event)
+
+ This handler is called when the VolumeUp key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onVolumeDownPressed(event)
+
+ This handler is called when the VolumeDown key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+
+class QmlGraphicsKeysAttachedPrivate : public QObjectPrivate
+{
+public:
+ QmlGraphicsKeysAttachedPrivate()
+ : QObjectPrivate(), inPress(false), inRelease(false)
+ , inIM(false), enabled(true), imeItem(0), item(0)
+ {}
+
+ bool isConnected(const char *signalName);
+
+ QGraphicsItem *finalFocusProxy(QGraphicsItem *item) const
+ {
+ QGraphicsItem *fp;
+ while ((fp = item->focusProxy()))
+ item = fp;
+ return item;
+ }
+
+ //loop detection
+ bool inPress:1;
+ bool inRelease:1;
+ bool inIM:1;
+
+ bool enabled : 1;
+
+ QGraphicsItem *imeItem;
+ QList<QmlGraphicsItem *> targets;
+ QmlGraphicsItem *item;
+};
+
+class QmlGraphicsKeysAttached : public QObject, public QmlGraphicsItemKeyFilter
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlGraphicsKeysAttached)
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QList<QmlGraphicsItem *> *forwardTo READ forwardTo)
+
+public:
+ QmlGraphicsKeysAttached(QObject *parent=0);
+ ~QmlGraphicsKeysAttached();
+
+ bool enabled() const { Q_D(const QmlGraphicsKeysAttached); return d->enabled; }
+ void setEnabled(bool enabled) {
+ Q_D(QmlGraphicsKeysAttached);
+ if (enabled != d->enabled) {
+ d->enabled = enabled;
+ emit enabledChanged();
+ }
+ }
+
+ QList<QmlGraphicsItem *> *forwardTo() {
+ Q_D(QmlGraphicsKeysAttached);
+ return &d->targets;
+ }
+
+ virtual void componentComplete();
+
+ static QmlGraphicsKeysAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void enabledChanged();
+ void pressed(QmlGraphicsKeyEvent *event);
+ void released(QmlGraphicsKeyEvent *event);
+ void digit0Pressed(QmlGraphicsKeyEvent *event);
+ void digit1Pressed(QmlGraphicsKeyEvent *event);
+ void digit2Pressed(QmlGraphicsKeyEvent *event);
+ void digit3Pressed(QmlGraphicsKeyEvent *event);
+ void digit4Pressed(QmlGraphicsKeyEvent *event);
+ void digit5Pressed(QmlGraphicsKeyEvent *event);
+ void digit6Pressed(QmlGraphicsKeyEvent *event);
+ void digit7Pressed(QmlGraphicsKeyEvent *event);
+ void digit8Pressed(QmlGraphicsKeyEvent *event);
+ void digit9Pressed(QmlGraphicsKeyEvent *event);
+
+ void leftPressed(QmlGraphicsKeyEvent *event);
+ void rightPressed(QmlGraphicsKeyEvent *event);
+ void upPressed(QmlGraphicsKeyEvent *event);
+ void downPressed(QmlGraphicsKeyEvent *event);
+
+ void asteriskPressed(QmlGraphicsKeyEvent *event);
+ void numberSignPressed(QmlGraphicsKeyEvent *event);
+ void escapePressed(QmlGraphicsKeyEvent *event);
+ void returnPressed(QmlGraphicsKeyEvent *event);
+ void enterPressed(QmlGraphicsKeyEvent *event);
+ void deletePressed(QmlGraphicsKeyEvent *event);
+ void spacePressed(QmlGraphicsKeyEvent *event);
+ void backPressed(QmlGraphicsKeyEvent *event);
+ void cancelPressed(QmlGraphicsKeyEvent *event);
+ void selectPressed(QmlGraphicsKeyEvent *event);
+ void yesPressed(QmlGraphicsKeyEvent *event);
+ void noPressed(QmlGraphicsKeyEvent *event);
+ void context1Pressed(QmlGraphicsKeyEvent *event);
+ void context2Pressed(QmlGraphicsKeyEvent *event);
+ void context3Pressed(QmlGraphicsKeyEvent *event);
+ void context4Pressed(QmlGraphicsKeyEvent *event);
+ void callPressed(QmlGraphicsKeyEvent *event);
+ void hangupPressed(QmlGraphicsKeyEvent *event);
+ void flipPressed(QmlGraphicsKeyEvent *event);
+ void menuPressed(QmlGraphicsKeyEvent *event);
+ void volumeUpPressed(QmlGraphicsKeyEvent *event);
+ void volumeDownPressed(QmlGraphicsKeyEvent *event);
+
+private:
+ virtual void keyPressed(QKeyEvent *event);
+ virtual void keyReleased(QKeyEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+ const QByteArray keyToSignal(int key) {
+ QByteArray keySignal;
+ if (key >= Qt::Key_0 && key <= Qt::Key_9) {
+ keySignal = "digit0Pressed";
+ keySignal[5] = '0' + (key - Qt::Key_0);
+ } else {
+ int i = 0;
+ while (sigMap[i].key && sigMap[i].key != key)
+ ++i;
+ keySignal = sigMap[i].sig;
+ }
+ return keySignal;
+ }
+
+ struct SigMap {
+ int key;
+ const char *sig;
+ };
+
+ static const SigMap sigMap[];
+};
+
+const QmlGraphicsKeysAttached::SigMap QmlGraphicsKeysAttached::sigMap[] = {
+ { Qt::Key_Left, "leftPressed" },
+ { Qt::Key_Right, "rightPressed" },
+ { Qt::Key_Up, "upPressed" },
+ { Qt::Key_Down, "downPressed" },
+ { Qt::Key_Asterisk, "asteriskPressed" },
+ { Qt::Key_NumberSign, "numberSignPressed" },
+ { Qt::Key_Escape, "escapePressed" },
+ { Qt::Key_Return, "returnPressed" },
+ { Qt::Key_Enter, "enterPressed" },
+ { Qt::Key_Delete, "deletePressed" },
+ { Qt::Key_Space, "spacePressed" },
+ { Qt::Key_Back, "backPressed" },
+ { Qt::Key_Cancel, "cancelPressed" },
+ { Qt::Key_Select, "selectPressed" },
+ { Qt::Key_Yes, "yesPressed" },
+ { Qt::Key_No, "noPressed" },
+ { Qt::Key_Context1, "context1Pressed" },
+ { Qt::Key_Context2, "context2Pressed" },
+ { Qt::Key_Context3, "context3Pressed" },
+ { Qt::Key_Context4, "context4Pressed" },
+ { Qt::Key_Call, "callPressed" },
+ { Qt::Key_Hangup, "hangupPressed" },
+ { Qt::Key_Flip, "flipPressed" },
+ { Qt::Key_Menu, "menuPressed" },
+ { Qt::Key_VolumeUp, "volumeUpPressed" },
+ { Qt::Key_VolumeDown, "volumeDownPressed" },
+ { 0, 0 }
+};
+
+bool QmlGraphicsKeysAttachedPrivate::isConnected(const char *signalName)
+{
+ return isSignalConnected(signalIndex(signalName));
+}
+
+QmlGraphicsKeysAttached::QmlGraphicsKeysAttached(QObject *parent)
+: QObject(*(new QmlGraphicsKeysAttachedPrivate), parent),
+ QmlGraphicsItemKeyFilter(qobject_cast<QmlGraphicsItem*>(parent))
+{
+ Q_D(QmlGraphicsKeysAttached);
+ d->item = qobject_cast<QmlGraphicsItem*>(parent);
+}
+
+QmlGraphicsKeysAttached::~QmlGraphicsKeysAttached()
+{
+}
+
+void QmlGraphicsKeysAttached::componentComplete()
+{
+ Q_D(QmlGraphicsKeysAttached);
+ if (d->item) {
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *targetItem = d->finalFocusProxy(d->targets.at(ii));
+ if (targetItem && (targetItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ d->item->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ break;
+ }
+ }
+ }
+}
+
+void QmlGraphicsKeysAttached::keyPressed(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsKeysAttached);
+ if (!d->enabled || d->inPress) {
+ event->ignore();
+ return;
+ }
+
+ // first process forwards
+ if (d->item && d->item->scene()) {
+ d->inPress = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i) {
+ d->item->scene()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->inPress = false;
+ return;
+ }
+ }
+ }
+ d->inPress = false;
+ }
+
+ QmlGraphicsKeyEvent ke(*event);
+ QByteArray keySignal = keyToSignal(event->key());
+ if (!keySignal.isEmpty()) {
+ keySignal += "(QmlGraphicsKeyEvent*)";
+ if (d->isConnected(keySignal)) {
+ // If we specifically handle a key then default to accepted
+ ke.setAccepted(true);
+ int idx = QmlGraphicsKeysAttached::staticMetaObject.indexOfSignal(keySignal);
+ metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QmlGraphicsKeyEvent*, &ke));
+ }
+ }
+ if (!ke.isAccepted())
+ emit pressed(&ke);
+ event->setAccepted(ke.isAccepted());
+
+ if (!event->isAccepted()) QmlGraphicsItemKeyFilter::keyPressed(event);
+}
+
+void QmlGraphicsKeysAttached::keyReleased(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsKeysAttached);
+ if (!d->enabled || d->inRelease) {
+ event->ignore();
+ return;
+ }
+
+ if (d->item && d->item->scene()) {
+ d->inRelease = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i) {
+ d->item->scene()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->inRelease = false;
+ return;
+ }
+ }
+ }
+ d->inRelease = false;
+ }
+
+ QmlGraphicsKeyEvent ke(*event);
+ emit released(&ke);
+ event->setAccepted(ke.isAccepted());
+
+ if (!event->isAccepted()) QmlGraphicsItemKeyFilter::keyReleased(event);
+}
+
+void QmlGraphicsKeysAttached::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QmlGraphicsKeysAttached);
+ if (d->item && !d->inIM && d->item->scene()) {
+ d->inIM = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ d->item->scene()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->imeItem = i;
+ d->inIM = false;
+ return;
+ }
+ }
+ }
+ d->inIM = false;
+ }
+ if (!event->isAccepted()) QmlGraphicsItemKeyFilter::inputMethodEvent(event);
+}
+
+class QmlGraphicsItemAccessor : public QGraphicsItem
+{
+public:
+ QVariant doInputMethodQuery(Qt::InputMethodQuery query) const {
+ return QGraphicsItem::inputMethodQuery(query);
+ }
+};
+
+QVariant QmlGraphicsKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QmlGraphicsKeysAttached);
+ if (d->item) {
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod) && i == d->imeItem) { //### how robust is i == d->imeItem check?
+ QVariant v = static_cast<QmlGraphicsItemAccessor *>(i)->doInputMethodQuery(query);
+ if (v.userType() == QVariant::RectF)
+ v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
+ return v;
+ }
+ }
+ }
+ return QmlGraphicsItemKeyFilter::inputMethodQuery(query);
+}
+
+QmlGraphicsKeysAttached *QmlGraphicsKeysAttached::qmlAttachedProperties(QObject *obj)
+{
+ return new QmlGraphicsKeysAttached(obj);
+}
+
+/*!
+ \class QmlGraphicsItem
+ \brief The QmlGraphicsItem class provides the most basic of all visual items in QML.
+
+ All visual items in Qt Declarative inherit from QmlGraphicsItem. Although QmlGraphicsItem
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ You can subclass QmlGraphicsItem to provide your own custom visual item that inherits
+ these features.
+*/
+
+/*!
+ \qmlclass Item QmlGraphicsItem
+ \brief The Item is the most basic of all visual items in QML.
+
+ All visual items in Qt Declarative inherit from Item. Although Item
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ Item is also useful for grouping items together.
+
+ \qml
+ Item {
+ Image {
+ source: "tile.png"
+ }
+ Image {
+ x: 80
+ width: 100
+ height: 100
+ source: "tile.png"
+ }
+ Image {
+ x: 190
+ width: 100
+ height: 100
+ fillMode: Image.Tile
+ source: "tile.png"
+ }
+ }
+ \endqml
+
+ \section1 Identity
+
+ Each item has an "id" - the identifier of the Item.
+
+ The identifier can be used in bindings and other expressions to
+ refer to the item. For example:
+
+ \qml
+ Text { id: myText; ... }
+ Text { text: myText.text }
+ \endqml
+
+ The identifier is available throughout to the \l {components}{component}
+ where it is declared. The identifier must be unique in the component.
+
+ The id should not be thought of as a "property" - it makes no sense
+ to write \c myText.id, for example.
+
+ \section1 Key Handling
+
+ Key handling is available to all Item-based visual elements via the \l {Keys}{Keys}
+ attached property. The \e Keys attached property provides basic handlers such
+ as \l {Keys::onPressed}{onPressed} and \l {Keys::onReleased}{onReleased},
+ as well as handlers for specific keys, such as
+ \l {Keys::onCancelPressed}{onCancelPressed}. The example below
+ assigns \l {qmlfocus}{focus} to the item and handles
+ the Left key via the general \e onPressed handler and the Select key via the
+ onSelectPressed handler:
+
+ \qml
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Left) {
+ console.log("move left");
+ event.accepted = true;
+ }
+ }
+ Keys.onSelectPressed: console.log("Selected");
+ }
+ \endqml
+
+ See the \l {Keys}{Keys} attached property for detailed documentation.
+
+ \ingroup group_coreitems
+*/
+
+/*!
+ \property QmlGraphicsItem::baseline
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::effect
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::focus
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::wantsFocus
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::transformOrigin
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::childrenRectChanged()
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::baselineOffsetChanged()
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::widthChanged()
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::heightChanged()
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::stateChanged(const QString &state)
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::parentChanged()
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::childrenChanged()
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::focusChanged()
+ \internal
+*/
+
+/*!
+ \fn void QmlGraphicsItem::wantsFocusChanged()
+ \internal
+*/
+
+// ### Must fix
+struct RegisterAnchorLineAtStartup {
+ RegisterAnchorLineAtStartup() {
+ qRegisterMetaType<QmlGraphicsAnchorLine>("QmlGraphicsAnchorLine");
+ }
+};
+static RegisterAnchorLineAtStartup registerAnchorLineAtStartup;
+
+
+/*!
+ \fn QmlGraphicsItem::QmlGraphicsItem(QmlGraphicsItem *parent)
+
+ Constructs a QmlGraphicsItem with the given \a parent.
+*/
+QmlGraphicsItem::QmlGraphicsItem(QmlGraphicsItem* parent)
+ : QGraphicsObject(*(new QmlGraphicsItemPrivate), parent, 0)
+{
+ Q_D(QmlGraphicsItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+QmlGraphicsItem::QmlGraphicsItem(QmlGraphicsItemPrivate &dd, QmlGraphicsItem *parent)
+ : QGraphicsObject(dd, parent, 0)
+{
+ Q_D(QmlGraphicsItem);
+ d->init(parent);
+}
+
+/*!
+ Destroys the QmlGraphicsItem.
+*/
+QmlGraphicsItem::~QmlGraphicsItem()
+{
+ Q_D(QmlGraphicsItem);
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ QmlGraphicsAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
+ if (anchor)
+ anchor->clearItem(this);
+ }
+ if (!d->parent || (parentItem() && !parentItem()->QGraphicsItem::d_ptr->inDestructor)) {
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ QmlGraphicsAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
+ if (anchor && anchor->item && anchor->item->parentItem() != this) //child will be deleted anyway
+ anchor->updateOnComplete();
+ }
+ }
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QmlGraphicsItemPrivate::Destroyed)
+ change.listener->itemDestroyed(this);
+ }
+ d->changeListeners.clear();
+ delete d->_anchorLines; d->_anchorLines = 0;
+ delete d->_anchors; d->_anchors = 0;
+ delete d->_stateGroup; d->_stateGroup = 0;
+}
+
+/*!
+ \qmlproperty enum Item::transformOrigin
+ This property holds the origin point around which scale and rotation transform.
+
+ Nine transform origins are available, as shown in the image below.
+
+ \image declarative-transformorigin.png
+
+ This example rotates an image around its bottom-right corner.
+ \qml
+ Image {
+ source: "myimage.png"
+ transformOrigin: Item.BottomRight
+ rotate: 45
+ }
+ \endqml
+
+ The default transform origin is \c Center.
+*/
+
+/*!
+ \qmlproperty Item Item::parent
+ This property holds the parent of the item.
+*/
+
+/*!
+ \property QmlGraphicsItem::parent
+ This property holds the parent of the item.
+*/
+void QmlGraphicsItem::setParentItem(QmlGraphicsItem *parent)
+{
+ QmlGraphicsItem *oldParent = parentItem();
+ if (parent == oldParent || !parent) return;
+
+ Q_D(QmlGraphicsItem);
+ QObject::setParent(parent);
+ d->setParentItemHelper(parent, /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+ if (oldParent)
+ emit oldParent->childrenChanged();
+ emit parentChanged();
+}
+
+/*!
+ \fn void QmlGraphicsItem::setParent(QmlGraphicsItem *parent)
+ \overload
+ Sets both the parent object and parent item to \a parent. This
+ function avoids the programming error of calling setParent()
+ when you mean setParentItem().
+*/
+
+/*!
+ Returns the QmlGraphicsItem parent of this item.
+*/
+QmlGraphicsItem *QmlGraphicsItem::parentItem() const
+{
+ return qobject_cast<QmlGraphicsItem *>(QGraphicsObject::parentItem());
+}
+
+/*!
+ \qmlproperty list<Item> Item::children
+ \qmlproperty list<Object> Item::resources
+
+ The children property contains the list of visual children of this item.
+ The resources property contains non-visual resources that you want to
+ reference by name.
+
+ Generally you can rely on Item's default property to handle all this for
+ you, but it can come in handy in some cases.
+
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Component {
+ id: myComponent
+ Text {}
+ }
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \property QmlGraphicsItem::children
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::resources
+ \internal
+*/
+
+/*!
+ Returns true if construction of the QML component is complete; otherwise
+ returns false.
+
+ It is often desireable to delay some processing until the component is
+ completed.
+
+ \sa componentComplete()
+*/
+bool QmlGraphicsItem::isComponentComplete() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->_componentComplete;
+}
+
+/*!
+ \property QmlGraphicsItem::anchors
+ \internal
+*/
+
+/*! \internal */
+QmlGraphicsAnchors *QmlGraphicsItem::anchors()
+{
+ Q_D(QmlGraphicsItem);
+ return d->anchors();
+}
+
+void QmlGraphicsItemPrivate::data_removeAt(int)
+{
+ // ###
+}
+
+int QmlGraphicsItemPrivate::data_count() const
+{
+ // ###
+ return 0;
+}
+
+void QmlGraphicsItemPrivate::data_append(QObject *o)
+{
+ Q_Q(QmlGraphicsItem);
+ QmlGraphicsItem *i = qobject_cast<QmlGraphicsItem *>(o);
+ if (i)
+ q->fxChildren()->append(i);
+ else
+ resources_append(o);
+}
+
+void QmlGraphicsItemPrivate::data_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QmlGraphicsItemPrivate::data_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QmlGraphicsItemPrivate::data_clear()
+{
+ // ###
+}
+
+void QmlGraphicsItemPrivate::resources_removeAt(int)
+{
+ // ###
+}
+
+int QmlGraphicsItemPrivate::resources_count() const
+{
+ Q_Q(const QmlGraphicsItem);
+ return q->children().count();
+}
+
+void QmlGraphicsItemPrivate::resources_append(QObject *o)
+{
+ Q_Q(QmlGraphicsItem);
+ o->setParent(q);
+}
+
+void QmlGraphicsItemPrivate::resources_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QmlGraphicsItemPrivate::resources_at(int idx) const
+{
+ Q_Q(const QmlGraphicsItem);
+ QObjectList children = q->children();
+ if (idx < children.count())
+ return children.at(idx);
+ else
+ return 0;
+}
+
+void QmlGraphicsItemPrivate::resources_clear()
+{
+ // ###
+}
+
+void QmlGraphicsItemPrivate::children_removeAt(int)
+{
+ // ###
+}
+
+int QmlGraphicsItemPrivate::children_count() const
+{
+ Q_Q(const QmlGraphicsItem);
+ return q->childItems().count();
+}
+
+void QmlGraphicsItemPrivate::children_append(QmlGraphicsItem *i)
+{
+ Q_Q(QmlGraphicsItem);
+ i->setParentItem(q);
+}
+
+void QmlGraphicsItemPrivate::children_insert(int, QmlGraphicsItem *)
+{
+ // ###
+}
+
+QmlGraphicsItem *QmlGraphicsItemPrivate::children_at(int idx) const
+{
+ Q_Q(const QmlGraphicsItem);
+ QList<QGraphicsItem *> children = q->childItems();
+ if (idx < children.count())
+ return qobject_cast<QmlGraphicsItem *>(children.at(idx));
+ else
+ return 0;
+}
+
+void QmlGraphicsItemPrivate::children_clear()
+{
+ // ###
+}
+
+
+void QmlGraphicsItemPrivate::transform_removeAt(int i)
+{
+ if (!transformData)
+ return;
+ transformData->graphicsTransforms.removeAt(i);
+ dirtySceneTransform = 1;
+}
+
+int QmlGraphicsItemPrivate::transform_count() const
+{
+ return transformData ? transformData->graphicsTransforms.size() : 0;
+}
+
+void QmlGraphicsItemPrivate::transform_append(QGraphicsTransform *item)
+{
+ appendGraphicsTransform(item);
+}
+
+void QmlGraphicsItemPrivate::transform_insert(int, QGraphicsTransform *)
+{
+ // ###
+}
+
+QGraphicsTransform *QmlGraphicsItemPrivate::transform_at(int idx) const
+{
+ if (!transformData)
+ return 0;
+ return transformData->graphicsTransforms.at(idx);
+}
+
+void QmlGraphicsItemPrivate::transform_clear()
+{
+ if (!transformData)
+ return;
+ Q_Q(QmlGraphicsItem);
+ q->setTransformations(QList<QGraphicsTransform *>());
+}
+
+/*!
+ \qmlproperty list<Object> Item::data
+ \default
+
+ The data property is allows you to freely mix visual children and resources
+ of an item. If you assign a visual item to the data list it becomes
+ a child and if you assign any other object type, it is added as a resource.
+
+ So you can write:
+ \qml
+ Item {
+ Text {}
+ Rectangle {}
+ Script {}
+ }
+ \endqml
+
+ instead of:
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Script {}
+ ]
+ }
+ \endqml
+
+ data is a behind-the-scenes property: you should never need to explicitly
+ specify it.
+ */
+
+/*!
+ \property QmlGraphicsItem::data
+ \internal
+*/
+
+/*! \internal */
+QmlList<QObject *> *QmlGraphicsItem::data()
+{
+ Q_D(QmlGraphicsItem);
+ return &d->data;
+}
+
+/*!
+ \property QmlGraphicsItem::childrenRect
+ \brief The geometry of an item's children.
+
+ childrenRect provides an easy way to access the (collective) position and size of the item's children.
+*/
+QRectF QmlGraphicsItem::childrenRect()
+{
+ Q_D(QmlGraphicsItem);
+ if (!d->_contents) {
+ d->_contents = new QmlGraphicsContents;
+ d->_contents->setParent(this);
+ d->_contents->setItem(this);
+ }
+ return d->_contents->rectF();
+}
+
+bool QmlGraphicsItem::clip() const
+{
+ return flags() & ItemClipsChildrenToShape;
+}
+
+void QmlGraphicsItem::setClip(bool c)
+{
+ setFlag(ItemClipsChildrenToShape, c);
+}
+
+/*!
+ \qmlproperty real Item::x
+ \qmlproperty real Item::y
+ \qmlproperty real Item::width
+ \qmlproperty real Item::height
+
+ Defines the item's position and size relative to its parent.
+
+ \qml
+ Item { x: 100; y: 100; width: 100; height: 100 }
+ \endqml
+ */
+
+/*!
+ \property QmlGraphicsItem::width
+
+ Defines the item's width relative to its parent.
+ */
+
+/*!
+ \property QmlGraphicsItem::height
+
+ Defines the item's height relative to its parent.
+ */
+
+/*!
+ \qmlproperty real Item::z
+
+ Sets the stacking order of the item. By default the stacking order is 0.
+
+ Items with a higher stacking value are drawn on top of items with a
+ lower stacking order. Items with the same stacking value are drawn
+ bottom up in the order they appear. Items with a negative stacking
+ value are drawn under their parent's content.
+
+ The following example shows the various effects of stacking order.
+
+ \table
+ \row
+ \o \image declarative-item_stacking1.png
+ \o Same \c z - later children above earlier children:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking2.png
+ \o Higher \c z on top:
+ \qml
+ Item {
+ Rectangle {
+ z: 1
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking3.png
+ \o Same \c z - children above parents:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking4.png
+ \o Lower \c z below:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ z: -1
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+ */
+
+/*!
+ \qmlproperty bool Item::visible
+
+ Whether the item is visible. By default this is true.
+
+ \note visible is not linked to actual visibility; if an item
+ moves off screen, or the opacity changes to 0, this will
+ not affect the visible property.
+*/
+
+
+/*!
+ This function is called to handle this item's changes in
+ geometry from \a oldGeometry to \a newGeometry. If the two
+ geometries are the same, it doesn't do anything.
+ */
+void QmlGraphicsItem::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QmlGraphicsItem);
+
+ if (d->_anchors)
+ d->_anchors->d_func()->updateMe();
+
+ if (transformOrigin() != QmlGraphicsItem::TopLeft)
+ setTransformOriginPoint(d->computeTransformOrigin());
+
+ if (newGeometry.x() != oldGeometry.x())
+ emit xChanged();
+ if (newGeometry.width() != oldGeometry.width())
+ emit widthChanged();
+ if (newGeometry.y() != oldGeometry.y())
+ emit yChanged();
+ if (newGeometry.height() != oldGeometry.height())
+ emit heightChanged();
+
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QmlGraphicsItemPrivate::Geometry)
+ change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
+ }
+}
+
+void QmlGraphicsItemPrivate::removeItemChangeListener(QmlGraphicsItemChangeListener *listener, ChangeTypes types)
+{
+ ChangeListener change(listener, types);
+ changeListeners.removeOne(change);
+}
+
+/*! \internal */
+void QmlGraphicsItem::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsItem);
+ if (d->keyHandler)
+ d->keyHandler->keyPressed(event);
+ else
+ event->ignore();
+}
+
+/*! \internal */
+void QmlGraphicsItem::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsItem);
+ if (d->keyHandler)
+ d->keyHandler->keyReleased(event);
+ else
+ event->ignore();
+}
+
+/*! \internal */
+void QmlGraphicsItem::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QmlGraphicsItem);
+ if (d->keyHandler)
+ d->keyHandler->inputMethodEvent(event);
+ else
+ event->ignore();
+}
+
+/*! \internal */
+QVariant QmlGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QmlGraphicsItem);
+ QVariant v;
+ if (d->keyHandler)
+ v = d->keyHandler->inputMethodQuery(query);
+
+ if (!v.isValid())
+ v = QGraphicsObject::inputMethodQuery(query);
+
+ return v;
+}
+
+/*!
+ \internal
+*/
+QmlGraphicsAnchorLine QmlGraphicsItem::left() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->anchorLines()->left;
+}
+
+/*!
+ \internal
+*/
+QmlGraphicsAnchorLine QmlGraphicsItem::right() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->anchorLines()->right;
+}
+
+/*!
+ \internal
+*/
+QmlGraphicsAnchorLine QmlGraphicsItem::horizontalCenter() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->anchorLines()->hCenter;
+}
+
+/*!
+ \internal
+*/
+QmlGraphicsAnchorLine QmlGraphicsItem::top() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->anchorLines()->top;
+}
+
+/*!
+ \internal
+*/
+QmlGraphicsAnchorLine QmlGraphicsItem::bottom() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->anchorLines()->bottom;
+}
+
+/*!
+ \internal
+*/
+QmlGraphicsAnchorLine QmlGraphicsItem::verticalCenter() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->anchorLines()->vCenter;
+}
+
+
+/*!
+ \internal
+*/
+QmlGraphicsAnchorLine QmlGraphicsItem::baseline() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->anchorLines()->baseline;
+}
+
+/*!
+ \property QmlGraphicsItem::top
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::bottom
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::left
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::right
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::horizontalCenter
+ \internal
+*/
+
+/*!
+ \property QmlGraphicsItem::verticalCenter
+ \internal
+*/
+
+/*!
+ \qmlproperty AnchorLine Item::top
+ \qmlproperty AnchorLine Item::bottom
+ \qmlproperty AnchorLine Item::left
+ \qmlproperty AnchorLine Item::right
+ \qmlproperty AnchorLine Item::horizontalCenter
+ \qmlproperty AnchorLine Item::verticalCenter
+ \qmlproperty AnchorLine Item::baseline
+
+ The anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \qmlproperty AnchorLine Item::anchors.top
+ \qmlproperty AnchorLine Item::anchors.bottom
+ \qmlproperty AnchorLine Item::anchors.left
+ \qmlproperty AnchorLine Item::anchors.right
+ \qmlproperty AnchorLine Item::anchors.horizontalCenter
+ \qmlproperty AnchorLine Item::anchors.verticalCenter
+ \qmlproperty AnchorLine Item::anchors.baseline
+
+ \qmlproperty Item Item::anchors.fill
+ \qmlproperty Item Item::anchors.centerIn
+
+ \qmlproperty real Item::anchors.margins
+ \qmlproperty real Item::anchors.topMargin
+ \qmlproperty real Item::anchors.bottomMargin
+ \qmlproperty real Item::anchors.leftMargin
+ \qmlproperty real Item::anchors.rightMargin
+ \qmlproperty real Item::anchors.horizontalCenterOffset
+ \qmlproperty real Item::anchors.verticalCenterOffset
+ \qmlproperty real Item::anchors.baselineOffset
+
+ Anchors provide a way to position an item by specifying its
+ relationship with other items.
+
+ Margins apply to top, bottom, left, right, and fill anchors.
+ The margins property can be used to set all of the various margins at once, to the same value.
+
+ Offsets apply for horizontal center, vertical center, and baseline anchors.
+
+ \table
+ \row
+ \o \image declarative-anchors_example.png
+ \o Text anchored to Image, horizontally centered and vertically below, with a margin.
+ \qml
+ Image { id: pic; ... }
+ Text {
+ id: label
+ anchors.horizontalCenter: pic.horizontalCenter
+ anchors.top: pic.bottom
+ anchors.topMargin: 5
+ ...
+ }
+ \endqml
+ \row
+ \o \image declarative-anchors_example2.png
+ \o
+ Left of Text anchored to right of Image, with a margin. The y
+ property of both defaults to 0.
+
+ \qml
+ Image { id: pic; ... }
+ Text {
+ id: label
+ anchors.left: pic.right
+ anchors.leftMargin: 5
+ ...
+ }
+ \endqml
+ \endtable
+
+ anchors.fill provides a convenient way for one item to have the
+ same geometry as another item, and is equivalent to connecting all
+ four directional anchors.
+
+ \note You can only anchor an item to siblings or a parent.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QmlGraphicsItem::baselineOffset
+ \brief The position of the item's baseline in local coordinates.
+
+ The baseline of a Text item is the imaginary line on which the text
+ sits. Controls containing text usually set their baseline to the
+ baseline of their text.
+
+ For non-text items, a default baseline offset of 0 is used.
+*/
+qreal QmlGraphicsItem::baselineOffset() const
+{
+ Q_D(const QmlGraphicsItem);
+ if (!d->_baselineOffset.isValid()) {
+ return 0.0;
+ } else
+ return d->_baselineOffset;
+}
+
+void QmlGraphicsItem::setBaselineOffset(qreal offset)
+{
+ Q_D(QmlGraphicsItem);
+ if (offset == d->_baselineOffset)
+ return;
+
+ d->_baselineOffset = offset;
+ emit baselineOffsetChanged();
+
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QmlGraphicsItemPrivate::Geometry) {
+ QmlGraphicsAnchorsPrivate *anchor = change.listener->anchorPrivate();
+ if (anchor)
+ anchor->updateVerticalAnchors();
+ }
+ }
+}
+
+/*!
+ \qmlproperty real Item::rotation
+ This property holds the rotation of the item in degrees clockwise.
+
+ This specifies how many degrees to rotate the item around its transformOrigin.
+ The default rotation is 0 degrees (i.e. not rotated at all).
+
+ \table
+ \row
+ \o \image declarative-rotation.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ rotation: 30
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*!
+ \qmlproperty real Item::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's transformOrigin.
+
+ \table
+ \row
+ \o \image declarative-scale.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ scale: 1.4
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*!
+ \qmlproperty real Item::opacity
+
+ The opacity of the item. Opacity is specified as a number between 0
+ (fully transparent) and 1 (fully opaque). The default is 1.
+
+ Opacity is an \e inherited attribute. That is, the opacity is
+ also applied individually to child items. In almost all cases this
+ is what you want. If you can spot the issue in the following
+ example, you might need to use an \l Opacity effect instead.
+
+ \table
+ \row
+ \o \image declarative-item_opacity1.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_opacity2.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ opacity: 0.5
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*!
+ Returns a value indicating whether mouse input should
+ remain with this item exclusively.
+
+ \sa setKeepMouseGrab()
+ */
+bool QmlGraphicsItem::keepMouseGrab() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->_keepMouse;
+}
+
+/*!
+ The flag indicating whether the mouse should remain
+ with this item is set to \a keep.
+
+ This is useful for items that wish to grab and keep mouse
+ interaction following a predefined gesture. For example,
+ an item that is interested in horizontal mouse movement
+ may set keepMouseGrab to true once a threshold has been
+ exceeded. Once keepMouseGrab has been set to true, filtering
+ items will not react to mouse events.
+
+ If the item does not indicate that it wishes to retain mouse grab,
+ a filtering item may steal the grab. For example, Flickable may attempt
+ to steal a mouse grab if it detects that the user has begun to
+ move the viewport.
+
+ \sa keepMouseGrab()
+ */
+void QmlGraphicsItem::setKeepMouseGrab(bool keep)
+{
+ Q_D(QmlGraphicsItem);
+ d->_keepMouse = keep;
+}
+
+/*!
+ \internal
+
+ This function emits the \e focusChanged signal.
+
+ Subclasses overriding this function should call up
+ to their base class.
+*/
+void QmlGraphicsItem::focusChanged(bool flag)
+{
+ Q_UNUSED(flag);
+ emit focusChanged();
+}
+
+/*! \internal */
+QmlList<QmlGraphicsItem *> *QmlGraphicsItem::fxChildren()
+{
+ Q_D(QmlGraphicsItem);
+ return &(d->children);
+}
+
+/*! \internal */
+QmlList<QObject *> *QmlGraphicsItem::resources()
+{
+ Q_D(QmlGraphicsItem);
+ return &(d->resources);
+}
+
+/*!
+ \qmlproperty list<State> Item::states
+ This property holds a list of states defined by the item.
+
+ \qml
+ Item {
+ states: [
+ State { ... },
+ State { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {qmlstate}{States}
+*/
+
+/*!
+ \property QmlGraphicsItem::states
+ \internal
+*/
+/*! \internal */
+QmlList<QmlState *>* QmlGraphicsItem::states()
+{
+ Q_D(QmlGraphicsItem);
+ return d->states()->statesProperty();
+}
+
+/*!
+ \qmlproperty list<Transition> Item::transitions
+ This property holds a list of transitions defined by the item.
+
+ \qml
+ Item {
+ transitions: [
+ Transition { ... },
+ Transition { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {state-transitions}{Transitions}
+*/
+
+/*!
+ \property QmlGraphicsItem::transitions
+ \internal
+*/
+
+/*! \internal */
+QmlList<QmlTransition *>* QmlGraphicsItem::transitions()
+{
+ Q_D(QmlGraphicsItem);
+ return d->states()->transitionsProperty();
+}
+
+/*
+ \qmlproperty list<Filter> Item::filter
+ This property holds a list of graphical filters to be applied to the item.
+
+ \l {Filter}{Filters} include things like \l {Blur}{blurring}
+ the item, or giving it a \l Reflection. Some
+ filters may not be available on all canvases; if a filter is not
+ available on a certain canvas, it will simply not be applied for
+ that canvas (but the QML will still be considered valid).
+
+ \qml
+ Item {
+ filter: [
+ Blur { ... },
+ Relection { ... }
+ ...
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool Item::clip
+ This property holds whether clipping is enabled.
+
+ if clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \property QmlGraphicsItem::clip
+ This property holds whether clipping is enabled.
+
+ if clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \qmlproperty string Item::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ Script {
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ }
+ \endqml
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {qmlstates}{States}
+*/
+
+/*!
+ \property QmlGraphicsItem::state
+ \internal
+*/
+
+/*! \internal */
+QString QmlGraphicsItem::state() const
+{
+ Q_D(const QmlGraphicsItem);
+ if (!d->_stateGroup)
+ return QString();
+ else
+ return d->_stateGroup->state();
+}
+
+/*! \internal */
+void QmlGraphicsItem::setState(const QString &state)
+{
+ Q_D(QmlGraphicsItem);
+ d->states()->setState(state);
+}
+
+/*!
+ \qmlproperty list<Transform> Item::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+
+/*!
+ \property QmlGraphicsItem::transform
+ \internal
+*/
+
+/*! \internal */
+QmlList<QGraphicsTransform *>* QmlGraphicsItem::transform()
+{
+ Q_D(QmlGraphicsItem);
+ return &(d->transform);
+}
+
+/*!
+ \internal
+
+ classBegin() is called when the item is constructed, but its
+ properties have not yet been set.
+
+ \sa componentComplete(), isComponentComplete()
+*/
+void QmlGraphicsItem::classBegin()
+{
+ Q_D(QmlGraphicsItem);
+ d->_componentComplete = false;
+ if (d->_stateGroup)
+ d->_stateGroup->classBegin();
+ if (d->_anchors)
+ d->_anchors->classBegin();
+}
+
+/*!
+ \internal
+
+ componentComplete() is called when all items in the component
+ have been constructed. It is often desireable to delay some
+ processing until the component is complete an all bindings in the
+ component have been resolved.
+*/
+void QmlGraphicsItem::componentComplete()
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::ItemComponentComplete> cc;
+#endif
+
+ Q_D(QmlGraphicsItem);
+ d->_componentComplete = true;
+ if (d->_stateGroup)
+ d->_stateGroup->componentComplete();
+ if (d->_anchors) {
+ d->_anchors->componentComplete();
+ d->_anchors->d_func()->updateOnComplete();
+ }
+ if (d->keyHandler)
+ d->keyHandler->componentComplete();
+}
+
+QmlStateGroup *QmlGraphicsItemPrivate::states()
+{
+ Q_Q(QmlGraphicsItem);
+ if (!_stateGroup) {
+ _stateGroup = new QmlStateGroup;
+ if (!_componentComplete)
+ _stateGroup->classBegin();
+ QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)),
+ q, SIGNAL(stateChanged(QString)));
+ }
+
+ return _stateGroup;
+}
+
+QmlGraphicsItemPrivate::AnchorLines::AnchorLines(QmlGraphicsItem *q)
+{
+ left.item = q;
+ left.anchorLine = QmlGraphicsAnchorLine::Left;
+ right.item = q;
+ right.anchorLine = QmlGraphicsAnchorLine::Right;
+ hCenter.item = q;
+ hCenter.anchorLine = QmlGraphicsAnchorLine::HCenter;
+ top.item = q;
+ top.anchorLine = QmlGraphicsAnchorLine::Top;
+ bottom.item = q;
+ bottom.anchorLine = QmlGraphicsAnchorLine::Bottom;
+ vCenter.item = q;
+ vCenter.anchorLine = QmlGraphicsAnchorLine::VCenter;
+ baseline.item = q;
+ baseline.anchorLine = QmlGraphicsAnchorLine::Baseline;
+}
+
+QPointF QmlGraphicsItemPrivate::computeTransformOrigin() const
+{
+ Q_Q(const QmlGraphicsItem);
+
+ QRectF br = q->boundingRect();
+
+ switch(origin) {
+ default:
+ case QmlGraphicsItem::TopLeft:
+ return QPointF(0, 0);
+ case QmlGraphicsItem::Top:
+ return QPointF(br.width() / 2., 0);
+ case QmlGraphicsItem::TopRight:
+ return QPointF(br.width(), 0);
+ case QmlGraphicsItem::Left:
+ return QPointF(0, br.height() / 2.);
+ case QmlGraphicsItem::Center:
+ return QPointF(br.width() / 2., br.height() / 2.);
+ case QmlGraphicsItem::Right:
+ return QPointF(br.width(), br.height() / 2.);
+ case QmlGraphicsItem::BottomLeft:
+ return QPointF(0, br.height());
+ case QmlGraphicsItem::Bottom:
+ return QPointF(br.width() / 2., br.height());
+ case QmlGraphicsItem::BottomRight:
+ return QPointF(br.width(), br.height());
+ }
+}
+
+/*! \internal */
+bool QmlGraphicsItem::sceneEvent(QEvent *event)
+{
+ bool rv = QGraphicsItem::sceneEvent(event);
+
+ if (event->type() == QEvent::FocusIn ||
+ event->type() == QEvent::FocusOut) {
+ focusChanged(hasFocus());
+ }
+
+ return rv;
+}
+
+/*! \internal */
+QVariant QmlGraphicsItem::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ Q_D(const QmlGraphicsItem);
+ switch (change) {
+ case ItemParentHasChanged:
+ emit parentChanged();
+ break;
+ case ItemChildAddedChange:
+ case ItemChildRemovedChange:
+ emit childrenChanged();
+ break;
+ case ItemVisibleHasChanged: {
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QmlGraphicsItemPrivate::Visibility) {
+ change.listener->itemVisibilityChanged(this);
+ }
+ }
+ }
+ break;
+ case ItemOpacityHasChanged: {
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QmlGraphicsItemPrivate::Opacity) {
+ change.listener->itemOpacityChanged(this);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+/*! \internal */
+QRectF QmlGraphicsItem::boundingRect() const
+{
+ Q_D(const QmlGraphicsItem);
+ return QRectF(0, 0, d->width, d->height);
+}
+
+/*!
+ \enum QmlGraphicsItem::TransformOrigin
+
+ Controls the point about which simple transforms like scale apply.
+
+ \value TopLeft The top-left corner of the item.
+ \value Top The center point of the top of the item.
+ \value TopRight The top-right corner of the item.
+ \value Left The left most point of the vertical middle.
+ \value Center The center of the item.
+ \value Right The right most point of the vertical middle.
+ \value BottomLeft The bottom-left corner of the item.
+ \value Bottom The center point of the bottom of the item.
+ \value BottomRight The bottom-right corner of the item.
+*/
+
+/*!
+ Returns the current transform origin.
+*/
+QmlGraphicsItem::TransformOrigin QmlGraphicsItem::transformOrigin() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->origin;
+}
+
+/*!
+ Set the transform \a origin.
+*/
+void QmlGraphicsItem::setTransformOrigin(TransformOrigin origin)
+{
+ Q_D(QmlGraphicsItem);
+ if (origin != d->origin) {
+ d->origin = origin;
+ QGraphicsItem::setTransformOriginPoint(d->computeTransformOrigin());
+ emit transformOriginChanged(d->origin);
+ }
+}
+
+/*!
+ \property QmlGraphicsItem::smooth
+ \brief whether the item is smoothly transformed.
+
+ This property is provided purely for the purpose of optimization. Turning
+ smooth transforms off is faster, but looks worse; turning smooth
+ transformations on is slower, but looks better.
+
+ By default smooth transformations are off.
+*/
+
+/*!
+ Returns true if the item should be drawn with antialiasing and
+ smooth pixmap filtering, false otherwise.
+
+ The default is false.
+
+ \sa setSmooth()
+*/
+bool QmlGraphicsItem::smooth() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->smooth;
+}
+
+/*!
+ Sets whether the item should be drawn with antialiasing and
+ smooth pixmap filtering to \a smooth.
+
+ \sa smooth()
+*/
+void QmlGraphicsItem::setSmooth(bool smooth)
+{
+ Q_D(QmlGraphicsItem);
+ if (d->smooth == smooth)
+ return;
+ d->smooth = smooth;
+ update();
+}
+
+qreal QmlGraphicsItem::width() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->width;
+}
+
+void QmlGraphicsItem::setWidth(qreal w)
+{
+ Q_D(QmlGraphicsItem);
+ if (qIsNaN(w))
+ return;
+
+ d->widthValid = true;
+ if (d->width == w)
+ return;
+
+ qreal oldWidth = d->width;
+
+ prepareGeometryChange();
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+void QmlGraphicsItem::resetWidth()
+{
+ Q_D(QmlGraphicsItem);
+ d->widthValid = false;
+ setImplicitWidth(implicitWidth());
+}
+
+/*!
+ Returns the width of the item that is implied by other properties that determine the content.
+*/
+qreal QmlGraphicsItem::implicitWidth() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->implicitWidth;
+}
+
+/*!
+ Sets the implied width of the item to \a w.
+ This is the width implied by other properties that determine the content.
+*/
+void QmlGraphicsItem::setImplicitWidth(qreal w)
+{
+ Q_D(QmlGraphicsItem);
+ d->implicitWidth = w;
+ if (d->width == w || widthValid())
+ return;
+
+ qreal oldWidth = d->width;
+
+ prepareGeometryChange();
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+/*!
+ Returns whether the width property has been set explicitly.
+*/
+bool QmlGraphicsItem::widthValid() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->widthValid;
+}
+
+qreal QmlGraphicsItem::height() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->height;
+}
+
+void QmlGraphicsItem::setHeight(qreal h)
+{
+ Q_D(QmlGraphicsItem);
+ if (qIsNaN(h))
+ return;
+
+ d->heightValid = true;
+ if (d->height == h)
+ return;
+
+ qreal oldHeight = d->height;
+
+ prepareGeometryChange();
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+void QmlGraphicsItem::resetHeight()
+{
+ Q_D(QmlGraphicsItem);
+ d->heightValid = false;
+ setImplicitHeight(implicitHeight());
+}
+
+/*!
+ Returns the height of the item that is implied by other properties that determine the content.
+*/
+qreal QmlGraphicsItem::implicitHeight() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->implicitHeight;
+}
+
+/*!
+ Sets the implied height of the item to \a h.
+ This is the height implied by other properties that determine the content.
+*/
+void QmlGraphicsItem::setImplicitHeight(qreal h)
+{
+ Q_D(QmlGraphicsItem);
+ d->implicitHeight = h;
+ if (d->height == h || heightValid())
+ return;
+
+ qreal oldHeight = d->height;
+
+ prepareGeometryChange();
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+/*!
+ Returns whether the height property has been set explicitly.
+*/
+bool QmlGraphicsItem::heightValid() const
+{
+ Q_D(const QmlGraphicsItem);
+ return d->heightValid;
+}
+
+/*!
+ \qmlproperty bool Item::wantsFocus
+
+ This property indicates whether the item has has an active focus request.
+
+ \sa {qmlfocus}{Keyboard Focus}
+*/
+
+/*! \internal */
+bool QmlGraphicsItem::wantsFocus() const
+{
+ return focusItem() != 0;
+}
+
+/*!
+ \qmlproperty bool Item::focus
+ This property indicates whether the item has keyboard input focus. Set this
+ property to true to request focus.
+
+ \sa {qmlfocus}{Keyboard Focus}
+*/
+
+/*! \internal */
+bool QmlGraphicsItem::hasFocus() const
+{
+ return QGraphicsItem::hasFocus();
+}
+
+/*! \internal */
+void QmlGraphicsItem::setFocus(bool focus)
+{
+ if (focus)
+ QGraphicsItem::setFocus(Qt::OtherFocusReason);
+ else
+ QGraphicsItem::clearFocus();
+}
+
+/*!
+ \reimp
+ \internal
+*/
+void QmlGraphicsItem::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
+{
+}
+
+/*!
+ \reimp
+ \internal
+*/
+bool QmlGraphicsItem::event(QEvent *ev)
+{
+ return QGraphicsObject::event(ev);
+}
+
+QDebug operator<<(QDebug debug, QmlGraphicsItem *item)
+{
+ if (!item) {
+ debug << "QmlGraphicsItem(0)";
+ return debug;
+ }
+
+ debug << item->metaObject()->className() << "(this =" << ((void*)item)
+ << ", parent =" << ((void*)item->parentItem())
+ << ", geometry =" << QRectF(item->pos(), QSizeF(item->width(), item->height()))
+ << ", z =" << item->zValue() << ')';
+ return debug;
+}
+
+int QmlGraphicsItemPrivate::consistentTime = -1;
+void QmlGraphicsItemPrivate::setConsistentTime(int t)
+{
+ consistentTime = t;
+}
+
+QTime QmlGraphicsItemPrivate::currentTime()
+{
+ if (consistentTime == -1)
+ return QTime::currentTime();
+ else
+ return QTime(0, 0).addMSecs(consistentTime);
+}
+
+void QmlGraphicsItemPrivate::start(QTime &t)
+{
+ t = currentTime();
+}
+
+int QmlGraphicsItemPrivate::elapsed(QTime &t)
+{
+ int n = t.msecsTo(currentTime());
+ if (n < 0) // passed midnight
+ n += 86400 * 1000;
+ return n;
+}
+
+int QmlGraphicsItemPrivate::restart(QTime &t)
+{
+ QTime time = currentTime();
+ int n = t.msecsTo(time);
+ if (n < 0) // passed midnight
+ n += 86400*1000;
+ t = time;
+ return n;
+}
+
+#include <qmlgraphicsitem.moc>
+#include <moc_qmlgraphicsitem.cpp>
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsKeysAttached)
+QML_DECLARE_TYPEINFO(QmlGraphicsKeysAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DEFINE_TYPE(Qt,4,6,Keys,QmlGraphicsKeysAttached)
+QML_DECLARE_TYPE(QmlGraphicsKeyNavigationAttached)
+QML_DECLARE_TYPEINFO(QmlGraphicsKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DEFINE_TYPE(Qt,4,6,KeyNavigation,QmlGraphicsKeyNavigationAttached)
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.h b/src/declarative/graphicsitems/qmlgraphicsitem.h
new file mode 100644
index 0000000..8ae2d5c
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsitem.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSITEM_H
+#define QMLGRAPHICSITEM_H
+
+#include <qml.h>
+#include <qmlcomponent.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qgraphicstransform.h>
+#include <QtGui/qfont.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlState;
+class QmlGraphicsAnchorLine;
+class QmlTransition;
+class QmlGraphicsKeyEvent;
+class QmlGraphicsAnchors;
+class QmlGraphicsItemPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsItem : public QGraphicsObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QmlGraphicsItem * parent READ parentItem WRITE setParentItem NOTIFY parentChanged DESIGNABLE false FINAL)
+ Q_PROPERTY(QmlList<QObject *> *data READ data DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlGraphicsItem *>* children READ fxChildren DESIGNABLE false NOTIFY childrenChanged)
+ Q_PROPERTY(QmlList<QObject *>* resources READ resources DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlState *>* states READ states DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitions DESIGNABLE false)
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
+ Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
+ Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL)
+ Q_PROPERTY(QmlGraphicsAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
+ Q_PROPERTY(QmlGraphicsAnchorLine left READ left CONSTANT FINAL)
+ Q_PROPERTY(QmlGraphicsAnchorLine right READ right CONSTANT FINAL)
+ Q_PROPERTY(QmlGraphicsAnchorLine horizontalCenter READ horizontalCenter CONSTANT FINAL)
+ Q_PROPERTY(QmlGraphicsAnchorLine top READ top CONSTANT FINAL)
+ Q_PROPERTY(QmlGraphicsAnchorLine bottom READ bottom CONSTANT FINAL)
+ Q_PROPERTY(QmlGraphicsAnchorLine verticalCenter READ verticalCenter CONSTANT FINAL)
+ Q_PROPERTY(QmlGraphicsAnchorLine baseline READ baseline CONSTANT FINAL)
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
+ Q_PROPERTY(bool clip READ clip WRITE setClip) // ### move to QGI/QGO, NOTIFY
+ Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL)
+ Q_PROPERTY(bool wantsFocus READ wantsFocus NOTIFY wantsFocusChanged)
+ Q_PROPERTY(QmlList<QGraphicsTransform *>* transform READ transform DESIGNABLE false FINAL)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin NOTIFY transformOriginChanged)
+ Q_PROPERTY(bool smooth READ smooth WRITE setSmooth)
+ Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect)
+ Q_ENUMS(TransformOrigin)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ enum TransformOrigin {
+ TopLeft, Top, TopRight,
+ Left, Center, Right,
+ BottomLeft, Bottom, BottomRight
+ };
+
+ QmlGraphicsItem(QmlGraphicsItem *parent = 0);
+ virtual ~QmlGraphicsItem();
+
+ QmlGraphicsItem *parentItem() const;
+ void setParentItem(QmlGraphicsItem *parent);
+ void setParent(QmlGraphicsItem *parent) { setParentItem(parent); }
+
+ QmlList<QObject *> *data();
+ QmlList<QmlGraphicsItem *> *fxChildren();
+ QmlList<QObject *> *resources();
+
+ QmlGraphicsAnchors *anchors();
+ QRectF childrenRect();
+
+ bool clip() const;
+ void setClip(bool);
+
+ QmlList<QmlState *>* states();
+ QmlList<QmlTransition *>* transitions();
+
+ QString state() const;
+ void setState(const QString &);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);
+
+ QmlList<QGraphicsTransform *> *transform();
+
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+ qreal implicitWidth() const;
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+ qreal implicitHeight() const;
+
+ TransformOrigin transformOrigin() const;
+ void setTransformOrigin(TransformOrigin);
+
+ bool smooth() const;
+ void setSmooth(bool);
+
+ QRectF boundingRect() const;
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+ bool wantsFocus() const;
+ bool hasFocus() const;
+ void setFocus(bool);
+
+ bool keepMouseGrab() const;
+ void setKeepMouseGrab(bool);
+
+ QmlGraphicsAnchorLine left() const;
+ QmlGraphicsAnchorLine right() const;
+ QmlGraphicsAnchorLine horizontalCenter() const;
+ QmlGraphicsAnchorLine top() const;
+ QmlGraphicsAnchorLine bottom() const;
+ QmlGraphicsAnchorLine verticalCenter() const;
+ QmlGraphicsAnchorLine baseline() const;
+
+Q_SIGNALS:
+ void widthChanged();
+ void heightChanged();
+ void childrenChanged();
+ void childrenRectChanged();
+ void baselineOffsetChanged();
+ void stateChanged(const QString &);
+ void focusChanged();
+ void wantsFocusChanged();
+ void parentChanged();
+ void transformOriginChanged(TransformOrigin);
+
+protected:
+ bool isComponentComplete() const;
+ virtual bool sceneEvent(QEvent *);
+ virtual bool event(QEvent *);
+ virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
+
+ void setImplicitWidth(qreal);
+ bool widthValid() const; // ### better name?
+ void setImplicitHeight(qreal);
+ bool heightValid() const; // ### better name?
+
+ virtual void classBegin();
+ virtual void componentComplete();
+ virtual void focusChanged(bool);
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+protected:
+ QmlGraphicsItem(QmlGraphicsItemPrivate &dd, QmlGraphicsItem *parent = 0);
+
+private:
+ friend class QmlStatePrivate;
+ friend class QmlGraphicsAnchors;
+ Q_DISABLE_COPY(QmlGraphicsItem)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsItem)
+};
+
+template<typename T>
+ T qobject_cast(QGraphicsObject *o)
+{
+ QObject *obj = o;
+ return qobject_cast<T>(obj);
+}
+
+// ### move to QGO
+template<typename T>
+T qobject_cast(QGraphicsItem *item)
+{
+ if (!item) return 0;
+ QObject *o = item->toGraphicsObject();
+ return qobject_cast<T>(o);
+}
+
+QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, QmlGraphicsItem *item);
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsItem)
+QML_DECLARE_TYPE(QGraphicsTransform)
+QML_DECLARE_TYPE(QGraphicsScale)
+QML_DECLARE_TYPE(QGraphicsRotation)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSITEM_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem_p.h b/src/declarative/graphicsitems/qmlgraphicsitem_p.h
new file mode 100644
index 0000000..1741808
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsitem_p.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSITEM_P_H
+#define QMLGRAPHICSITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem.h"
+
+#include "qmlgraphicsanchors_p.h"
+#include "qmlgraphicsanchors_p_p.h"
+#include "qmlgraphicsitemchangelistener_p.h"
+#include <private/qpodvector_p.h>
+
+#include "../util/qmlstate_p.h"
+#include "../util/qmlnullablevalue_p_p.h"
+#include <qml.h>
+#include <qmlcontext.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qdebug.h>
+
+#include <private/qgraphicsitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+class QmlGraphicsItemKeyFilter;
+
+//### merge into private?
+class QmlGraphicsContents : public QObject
+{
+ Q_OBJECT
+public:
+ QmlGraphicsContents();
+
+ QRectF rectF() const;
+
+ void setItem(QmlGraphicsItem *item);
+
+public Q_SLOTS:
+ void calcHeight();
+ void calcWidth();
+
+Q_SIGNALS:
+ void rectChanged();
+
+private:
+ QmlGraphicsItem *m_item;
+ qreal m_x;
+ qreal m_y;
+ qreal m_width;
+ qreal m_height;
+};
+
+class QmlGraphicsItemPrivate : public QGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsItem)
+
+public:
+ QmlGraphicsItemPrivate()
+ : _anchors(0), _contents(0),
+ _baselineOffset(0),
+ _anchorLines(0),
+ _stateGroup(0), origin(QmlGraphicsItem::Center),
+ widthValid(false), heightValid(false),
+ _componentComplete(true), _keepMouse(false),
+ smooth(false), keyHandler(0),
+ width(0), height(0), implicitWidth(0), implicitHeight(0)
+ {
+ QGraphicsItemPrivate::acceptedMouseButtons = 0;
+ QGraphicsItemPrivate::flags = QGraphicsItem::GraphicsItemFlags(
+ QGraphicsItem::ItemHasNoContents
+ | QGraphicsItem::ItemIsFocusable
+ | QGraphicsItem::ItemNegativeZStacksBehindParent);
+
+ }
+
+ void init(QmlGraphicsItem *parent)
+ {
+ Q_Q(QmlGraphicsItem);
+
+ if (parent)
+ q->setParentItem(parent);
+ _baselineOffset.invalidate();
+ mouseSetsFocus = false;
+ }
+
+ QString _id;
+
+ // data property
+ void data_removeAt(int);
+ int data_count() const;
+ void data_append(QObject *);
+ void data_insert(int, QObject *);
+ QObject *data_at(int) const;
+ void data_clear();
+ QML_DECLARE_LIST_PROXY(QmlGraphicsItemPrivate, QObject *, data)
+
+ // resources property
+ void resources_removeAt(int);
+ int resources_count() const;
+ void resources_append(QObject *);
+ void resources_insert(int, QObject *);
+ QObject *resources_at(int) const;
+ void resources_clear();
+ QML_DECLARE_LIST_PROXY(QmlGraphicsItemPrivate, QObject *, resources)
+
+ // children property
+ void children_removeAt(int);
+ int children_count() const;
+ void children_append(QmlGraphicsItem *);
+ void children_insert(int, QmlGraphicsItem *);
+ QmlGraphicsItem *children_at(int) const;
+ void children_clear();
+ QML_DECLARE_LIST_PROXY(QmlGraphicsItemPrivate, QmlGraphicsItem *, children)
+
+ // transform property
+ void transform_removeAt(int);
+ int transform_count() const;
+ void transform_append(QGraphicsTransform *);
+ void transform_insert(int, QGraphicsTransform *);
+ QGraphicsTransform *transform_at(int) const;
+ void transform_clear();
+ QML_DECLARE_LIST_PROXY(QmlGraphicsItemPrivate, QGraphicsTransform *, transform)
+
+ QmlGraphicsAnchors *anchors() {
+ if (!_anchors) {
+ Q_Q(QmlGraphicsItem);
+ _anchors = new QmlGraphicsAnchors(q);
+ if (!_componentComplete)
+ _anchors->classBegin();
+ }
+ return _anchors;
+ }
+ QmlGraphicsAnchors *_anchors;
+ QmlGraphicsContents *_contents;
+
+ QmlNullableValue<qreal> _baselineOffset;
+
+ struct AnchorLines {
+ AnchorLines(QmlGraphicsItem *);
+ QmlGraphicsAnchorLine left;
+ QmlGraphicsAnchorLine right;
+ QmlGraphicsAnchorLine hCenter;
+ QmlGraphicsAnchorLine top;
+ QmlGraphicsAnchorLine bottom;
+ QmlGraphicsAnchorLine vCenter;
+ QmlGraphicsAnchorLine baseline;
+ };
+ mutable AnchorLines *_anchorLines;
+ AnchorLines *anchorLines() const {
+ Q_Q(const QmlGraphicsItem);
+ if (!_anchorLines) _anchorLines =
+ new AnchorLines(const_cast<QmlGraphicsItem *>(q));
+ return _anchorLines;
+ }
+
+ enum ChangeType {
+ Geometry = 0x01,
+ SiblingOrder = 0x02,
+ Visibility = 0x04,
+ Opacity = 0x08,
+ Destroyed = 0x10
+ };
+
+ Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
+
+ struct ChangeListener {
+ ChangeListener(QmlGraphicsItemChangeListener *l, QmlGraphicsItemPrivate::ChangeTypes t) : listener(l), types(t) {}
+ QmlGraphicsItemChangeListener *listener;
+ QmlGraphicsItemPrivate::ChangeTypes types;
+ bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; }
+ };
+
+ void addItemChangeListener(QmlGraphicsItemChangeListener *listener, ChangeTypes types) {
+ changeListeners.append(ChangeListener(listener, types));
+ }
+ void removeItemChangeListener(QmlGraphicsItemChangeListener *, ChangeTypes types);
+ QPODVector<ChangeListener,4> changeListeners;
+
+ QmlStateGroup *states();
+ QmlStateGroup *_stateGroup;
+
+ QmlGraphicsItem::TransformOrigin origin:4;
+ bool widthValid:1;
+ bool heightValid:1;
+ bool _componentComplete:1;
+ bool _keepMouse:1;
+ bool smooth:1;
+
+ QmlGraphicsItemKeyFilter *keyHandler;
+
+ qreal width;
+ qreal height;
+ qreal implicitWidth;
+ qreal implicitHeight;
+
+ QPointF computeTransformOrigin() const;
+
+ virtual void setPosHelper(const QPointF &pos)
+ {
+ Q_Q(QmlGraphicsItem);
+ QRectF oldGeometry(this->pos.x(), this->pos.y(), width, height);
+ QGraphicsItemPrivate::setPosHelper(pos);
+ q->geometryChanged(QRectF(this->pos.x(), this->pos.y(), width, height), oldGeometry);
+ }
+
+ // Reimplemented from QGraphicsItemPrivate
+ virtual void subFocusItemChange()
+ {
+ emit q_func()->wantsFocusChanged();
+ }
+
+ // Reimplemented from QGraphicsItemPrivate
+ virtual void siblingOrderChange()
+ {
+ Q_Q(QmlGraphicsItem);
+ for(int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QmlGraphicsItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QmlGraphicsItemPrivate::SiblingOrder) {
+ change.listener->itemSiblingOrderChanged(q);
+ }
+ }
+ }
+
+ static int consistentTime;
+ static QTime currentTime();
+ static void Q_DECLARATIVE_EXPORT setConsistentTime(int t);
+ static void start(QTime &);
+ static int elapsed(QTime &);
+ static int restart(QTime &);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlGraphicsItemPrivate::ChangeTypes);
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSITEM_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h b/src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h
new file mode 100644
index 0000000..f430df0
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSITEMCHANGELISTENER
+#define QMLGRAPHICSITEMCHANGELISTENER
+
+//
+// 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 <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRectF;
+class QmlGraphicsItem;
+class QmlGraphicsAnchorsPrivate;
+class QmlGraphicsItemChangeListener
+{
+public:
+ virtual void itemGeometryChanged(QmlGraphicsItem *, const QRectF &, const QRectF &) {}
+ virtual void itemSiblingOrderChanged(QmlGraphicsItem *) {}
+ virtual void itemVisibilityChanged(QmlGraphicsItem *) {}
+ virtual void itemOpacityChanged(QmlGraphicsItem *) {}
+ virtual void itemDestroyed(QmlGraphicsItem *) {}
+ virtual QmlGraphicsAnchorsPrivate *anchorPrivate() { return 0; }
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSITEMCHANGELISTENER
diff --git a/src/declarative/graphicsitems/qmlgraphicslayoutitem.cpp b/src/declarative/graphicsitems/qmlgraphicslayoutitem.cpp
new file mode 100644
index 0000000..7227eb0
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicslayoutitem.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicslayoutitem_p.h"
+
+#include <QDebug>
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,LayoutItem,QmlGraphicsLayoutItem)
+
+/*!
+ \qmlclass LayoutItem QmlGraphicsLayoutItem
+ \brief The LayoutItem element allows you to place your Fluid UI elements inside a classical Qt layout.
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsLayoutItem
+ \brief The QmlGraphicsLayoutItem class allows you to place your Fluid UI elements inside a classical Qt layout.
+*/
+
+
+/*!
+ \qmlproperty QSizeF LayoutItem::maximumSize
+
+ The maximumSize property can be set to specify the maximum desired size of this LayoutItem
+*/
+
+/*!
+ \qmlproperty QSizeF LayoutItem::minimumSize
+
+ The minimumSize property can be set to specify the minimum desired size of this LayoutItem
+*/
+
+/*!
+ \qmlproperty QSizeF LayoutItem::preferredSize
+
+ The preferredSize property can be set to specify the preferred size of this LayoutItem
+*/
+
+QmlGraphicsLayoutItem::QmlGraphicsLayoutItem(QmlGraphicsItem* parent)
+ : QmlGraphicsItem(parent), m_maximumSize(INT_MAX,INT_MAX), m_minimumSize(0,0), m_preferredSize(0,0)
+{
+ setGraphicsItem(this);
+}
+
+void QmlGraphicsLayoutItem::setGeometry(const QRectF & rect)
+{
+ setX(rect.x());
+ setY(rect.y());
+ setWidth(rect.width());
+ setHeight(rect.height());
+}
+
+QSizeF QmlGraphicsLayoutItem::sizeHint(Qt::SizeHint w, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint);
+ if(w == Qt::MinimumSize){
+ return m_minimumSize;
+ }else if(w == Qt::MaximumSize){
+ return m_maximumSize;
+ }else{
+ return m_preferredSize;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicslayoutitem_p.h b/src/declarative/graphicsitems/qmlgraphicslayoutitem_p.h
new file mode 100644
index 0000000..3278b63
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicslayoutitem_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSGRAPHICSLAYOUTITEM_H
+#define QMLGRAPHICSGRAPHICSLAYOUTITEM_H
+#include "qmlgraphicsitem.h"
+
+#include <QGraphicsLayoutItem>
+#include <QSizeF>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsLayoutItem : public QmlGraphicsItem, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+ Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize NOTIFY maximumSizeChanged)
+ Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize NOTIFY minimumSizeChanged)
+ Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize NOTIFY preferredSizeChanged)
+public:
+ QmlGraphicsLayoutItem(QmlGraphicsItem* parent=0);
+
+ QSizeF maximumSize() const { return m_maximumSize; }
+ void setMaximumSize(const QSizeF &s) { if(s==m_maximumSize) return; m_maximumSize = s; emit maximumSizeChanged(); }
+
+ QSizeF minimumSize() const { return m_minimumSize; }
+ void setMinimumSize(const QSizeF &s) { if(s==m_minimumSize) return; m_minimumSize = s; emit minimumSizeChanged(); }
+
+ QSizeF preferredSize() const { return m_preferredSize; }
+ void setPreferredSize(const QSizeF &s) { if(s==m_preferredSize) return; m_preferredSize = s; emit preferredSizeChanged(); }
+
+ virtual void setGeometry(const QRectF & rect);
+protected:
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+Q_SIGNALS:
+ void maximumSizeChanged();
+ void minimumSizeChanged();
+ void preferredSizeChanged();
+
+private:
+ QSizeF m_maximumSize;
+ QSizeF m_minimumSize;
+ QSizeF m_preferredSize;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsLayoutItem)
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
new file mode 100644
index 0000000..d0b3739
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
@@ -0,0 +1,2748 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicslistview_p.h"
+
+#include "qmlgraphicsflickable_p_p.h"
+#include "qmlgraphicsvisualitemmodel_p.h"
+
+#include <qmleasefollow_p.h>
+#include <qmlexpression.h>
+#include <qmlengine.h>
+
+#include <qlistmodelinterface_p.h>
+#include <QKeyEvent>
+
+QT_BEGIN_NAMESPACE
+
+void QmlGraphicsViewSection::setProperty(const QString &property)
+{
+ if (property != m_property) {
+ m_property = property;
+ emit changed();
+ }
+}
+
+void QmlGraphicsViewSection::setCriteria(QmlGraphicsViewSection::SectionCriteria criteria)
+{
+ if (criteria != m_criteria) {
+ m_criteria = criteria;
+ emit changed();
+ }
+}
+
+void QmlGraphicsViewSection::setDelegate(QmlComponent *delegate)
+{
+ if (delegate != m_delegate) {
+ m_delegate = delegate;
+ emit delegateChanged();
+ }
+}
+
+QString QmlGraphicsViewSection::sectionString(const QString &value)
+{
+ if (m_criteria == FirstCharacter)
+ return value.isEmpty() ? QString() : value.at(0);
+ else
+ return value;
+}
+
+class QmlGraphicsListViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QmlGraphicsListViewAttached(QObject *parent)
+ : QObject(parent), m_view(0), m_isCurrent(false), m_delayRemove(false) {}
+ ~QmlGraphicsListViewAttached() {}
+
+ Q_PROPERTY(QmlGraphicsListView *view READ view CONSTANT)
+ QmlGraphicsListView *view() { return m_view; }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(QString prevSection READ prevSection NOTIFY prevSectionChanged)
+ QString prevSection() const { return m_prevSection; }
+ void setPrevSection(const QString &sect) {
+ if (m_prevSection != sect) {
+ m_prevSection = sect;
+ emit prevSectionChanged();
+ }
+ }
+
+ Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
+ QString section() const { return m_section; }
+ void setSection(const QString &sect) {
+ if (m_section != sect) {
+ m_section = sect;
+ emit sectionChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+Q_SIGNALS:
+ void currentItemChanged();
+ void sectionChanged();
+ void prevSectionChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+
+public:
+ QmlGraphicsListView *m_view;
+ bool m_isCurrent;
+ mutable QString m_section;
+ QString m_prevSection;
+ bool m_delayRemove;
+};
+
+//----------------------------------------------------------------------------
+
+class FxListItem
+{
+public:
+ FxListItem(QmlGraphicsItem *i, QmlGraphicsListView *v) : item(i), section(0), view(v) {
+ attached = static_cast<QmlGraphicsListViewAttached*>(qmlAttachedPropertiesObject<QmlGraphicsListView>(item));
+ if (attached)
+ attached->m_view = view;
+ }
+ ~FxListItem() {}
+ qreal position() const {
+ if (section)
+ return (view->orientation() == QmlGraphicsListView::Vertical ? section->y() : section->x());
+ else
+ return (view->orientation() == QmlGraphicsListView::Vertical ? item->y() : item->x());
+ }
+ int size() const {
+ if (section)
+ return (view->orientation() == QmlGraphicsListView::Vertical ? item->height()+section->height() : item->width()+section->height());
+ else
+ return (view->orientation() == QmlGraphicsListView::Vertical ? item->height() : item->width());
+ }
+ qreal endPosition() const {
+ return (view->orientation() == QmlGraphicsListView::Vertical
+ ? item->y() + (item->height() > 0 ? item->height() : 1)
+ : item->x() + (item->width() > 0 ? item->width() : 1)) - 1;
+ }
+ void setPosition(qreal pos) {
+ if (view->orientation() == QmlGraphicsListView::Vertical) {
+ if (section) {
+ section->setY(pos);
+ pos += section->height();
+ }
+ item->setY(pos);
+ } else {
+ if (section) {
+ section->setX(pos);
+ pos += section->width();
+ }
+ item->setX(pos);
+ }
+ }
+
+ QmlGraphicsItem *item;
+ QmlGraphicsItem *section;
+ QmlGraphicsListView *view;
+ QmlGraphicsListViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QmlGraphicsListViewPrivate : public QmlGraphicsFlickablePrivate, private QmlGraphicsItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsListView)
+
+public:
+ QmlGraphicsListViewPrivate()
+ : currentItem(0), orient(QmlGraphicsListView::Vertical)
+ , visiblePos(0), visibleIndex(0)
+ , averageSize(100.0), currentIndex(-1), requestedIndex(-1)
+ , highlightRangeStart(0), highlightRangeEnd(0)
+ , highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
+ , sectionCriteria(0), spacing(0.0)
+ , highlightMoveSpeed(400), highlightResizeSpeed(400), highlightRange(QmlGraphicsListView::NoHighlightRange)
+ , snapMode(QmlGraphicsListView::NoSnap), overshootDist(0.0)
+ , footerComponent(0), footer(0), headerComponent(0), header(0)
+ , bufferMode(NoBuffer)
+ , ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false)
+ , correctFlick(true), inFlickCorrection(false), lazyRelease(false)
+ , deferredRelease(false), minExtentDirty(true), maxExtentDirty(true)
+ {}
+
+ void init();
+ void clear();
+ FxListItem *createItem(int modelIndex);
+ void releaseItem(FxListItem *item);
+
+ FxListItem *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ FxListItem *firstVisibleItem() const {
+ const qreal pos = position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ if (item->index != -1 && item->endPosition() > pos)
+ return item;
+ }
+ return visibleItems.count() ? visibleItems.first() : 0;
+ }
+
+ FxListItem *nextVisibleItem() const {
+ const qreal pos = position();
+ bool foundFirst = false;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ if (item->index != -1) {
+ if (foundFirst)
+ return item;
+ else if (item->position() < pos && item->endPosition() > pos)
+ foundFirst = true;
+ }
+ }
+ return 0;
+ }
+
+ qreal position() const {
+ Q_Q(const QmlGraphicsListView);
+ return orient == QmlGraphicsListView::Vertical ? q->viewportY() : q->viewportX();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QmlGraphicsListView);
+ if (orient == QmlGraphicsListView::Vertical)
+ q->setViewportY(pos);
+ else
+ q->setViewportX(pos);
+ }
+ qreal size() const {
+ Q_Q(const QmlGraphicsListView);
+ return orient == QmlGraphicsListView::Vertical ? q->height() : q->width();
+ }
+
+ qreal startPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ pos = (*visibleItems.constBegin())->position();
+ if (visibleIndex > 0)
+ pos -= visibleIndex * (averageSize + spacing) - spacing;
+ }
+ return pos;
+ }
+
+ qreal endPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ int invisibleCount = visibleItems.count() - visibleIndex;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ if (visibleItems.at(i)->index != -1) {
+ invisibleCount = model->count() - visibleItems.at(i)->index - 1;
+ break;
+ }
+ }
+ pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
+ }
+ return pos;
+ }
+
+ qreal positionAt(int modelIndex) const {
+ if (FxListItem *item = visibleItem(modelIndex))
+ return item->position();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ return (*visibleItems.constBegin())->position() - count * (averageSize + spacing);
+ } else {
+ int idx = visibleItems.count() - 1;
+ while (idx >= 0 && visibleItems.at(idx)->index == -1)
+ --idx;
+ if (idx < 0)
+ idx = visibleIndex;
+ else
+ idx = visibleItems.at(idx)->index;
+ int count = modelIndex - idx - 1;
+ return (*(--visibleItems.constEnd()))->endPosition() + spacing + count * (averageSize + spacing) + 1;
+ }
+ }
+ return 0;
+ }
+
+ QString sectionAt(int modelIndex) {
+ if (FxListItem *item = visibleItem(modelIndex))
+ return item->attached->section();
+
+ QString section;
+ if (sectionCriteria) {
+ QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+ section = sectionCriteria->sectionString(propValue);
+ }
+
+ return section;
+ }
+
+ bool isValid() const {
+ return model && model->count() && model->isValid();
+ }
+
+ int snapIndex() {
+ int index = currentIndex;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->position();
+ if (itemTop >= highlight->position()-item->size()/2 && itemTop < highlight->position()+item->size()/2)
+ return item->index;
+ }
+ return index;
+ }
+
+ qreal snapPosAt(qreal pos) {
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->position();
+ if (item->index == model->count()-1 || (itemTop+item->size()/2 >= pos))
+ return item->position();
+ }
+ if (visibleItems.count()) {
+ qreal firstPos = visibleItems.first()->position();
+ qreal endPos = visibleItems.last()->position();
+ if (pos < firstPos) {
+ return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
+ } else if (pos > endPos)
+ return endPos + qRound((pos - endPos) / averageSize) * averageSize;
+ }
+ return qRound((pos - startPosition()) / averageSize) * averageSize + startPosition();
+ }
+
+ FxListItem *snapItemAt(qreal pos) {
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->position();
+ if (item->index == model->count()-1 || (itemTop+item->size()/2 >= pos))
+ return item;
+ }
+ if (visibleItems.count() && visibleItems.first()->position() <= pos)
+ return visibleItems.first();
+ return 0;
+ }
+
+ int lastVisibleIndex() const {
+ int lastIndex = -1;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index != -1) {
+ lastIndex = listItem->index;
+ break;
+ }
+ }
+ return lastIndex;
+ }
+
+ // map a model index to visibleItems index.
+ // These may differ if removed items are still present in the visible list,
+ // e.g. doing a removal animation
+ int mapFromModel(int modelIndex) const {
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i + visibleIndex;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ bool mapRangeFromModel(int &index, int &count) const {
+ if (index + count < visibleIndex)
+ return false;
+
+ int lastIndex = -1;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index != -1) {
+ lastIndex = listItem->index;
+ break;
+ }
+ }
+
+ if (index > lastIndex)
+ return false;
+
+ int last = qMin(index + count - 1, lastIndex);
+ index = qMax(index, visibleIndex);
+ count = last - index + 1;
+
+ return true;
+ }
+
+ void updateViewport() {
+ Q_Q(QmlGraphicsListView);
+ if (orient == QmlGraphicsListView::Vertical) {
+ q->setViewportHeight(endPosition() - startPosition() + 1);
+ } else {
+ q->setViewportWidth(endPosition() - startPosition() + 1);
+ }
+ }
+
+ void itemGeometryChanged(QmlGraphicsItem *, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ if ((orient == QmlGraphicsListView::Vertical && newGeometry.height() != oldGeometry.height())
+ || newGeometry.width() != oldGeometry.width()) {
+ layout();
+ fixupPosition();
+ }
+ }
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ qFatal("index %d %d %d", visibleIndex, i, listItem->index);
+ }
+ }
+ }
+
+ void refill(qreal from, qreal to, bool doBuffer = false);
+ void layout();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void createSection(FxListItem *);
+ void updateSections();
+ void updateCurrentSection();
+ void updateCurrent(int);
+ void updateAverage();
+ void updateHeader();
+ void updateFooter();
+ void fixupPosition();
+ virtual void fixupY();
+ virtual void fixupX();
+ virtual void flickX(qreal velocity);
+ virtual void flickY(qreal velocity);
+
+ QGuard<QmlGraphicsVisualModel> model;
+ QVariant modelVariant;
+ QList<FxListItem*> visibleItems;
+ QHash<QmlGraphicsItem*,int> unrequestedItems;
+ FxListItem *currentItem;
+ QmlGraphicsListView::Orientation orient;
+ int visiblePos;
+ int visibleIndex;
+ qreal averageSize;
+ int currentIndex;
+ int requestedIndex;
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ QmlComponent *highlightComponent;
+ FxListItem *highlight;
+ FxListItem *trackedItem;
+ enum MovementReason { Other, SetIndex, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QmlEaseFollow *highlightPosAnimator;
+ QmlEaseFollow *highlightSizeAnimator;
+ QmlGraphicsViewSection *sectionCriteria;
+ QString currentSection;
+ static const int sectionCacheSize = 3;
+ QmlGraphicsItem *sectionCache[sectionCacheSize];
+ qreal spacing;
+ qreal highlightMoveSpeed;
+ qreal highlightResizeSpeed;
+ QmlGraphicsListView::HighlightRangeMode highlightRange;
+ QmlGraphicsListView::SnapMode snapMode;
+ qreal overshootDist;
+ QmlComponent *footerComponent;
+ FxListItem *footer;
+ QmlComponent *headerComponent;
+ FxListItem *header;
+ enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+ int bufferMode;
+ mutable qreal minExtent;
+ mutable qreal maxExtent;
+
+ bool ownModel : 1;
+ bool wrap : 1;
+ bool autoHighlight : 1;
+ bool haveHighlightRange : 1;
+ bool correctFlick : 1;
+ bool inFlickCorrection : 1;
+ bool lazyRelease : 1;
+ bool deferredRelease : 1;
+ mutable bool minExtentDirty : 1;
+ mutable bool maxExtentDirty : 1;
+};
+
+void QmlGraphicsListViewPrivate::init()
+{
+ Q_Q(QmlGraphicsListView);
+ q->setFlag(QGraphicsItem::ItemIsFocusScope);
+ addItemChangeListener(this, Geometry);
+ QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
+ q->setFlickDirection(QmlGraphicsFlickable::VerticalFlick);
+ ::memset(sectionCache, 0, sizeof(QmlGraphicsItem*) * sectionCacheSize);
+}
+
+void QmlGraphicsListViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ for (int i = 0; i < sectionCacheSize; ++i) {
+ delete sectionCache[i];
+ sectionCache[i] = 0;
+ }
+ visiblePos = header ? header->size() : 0;
+ visibleIndex = 0;
+ releaseItem(currentItem);
+ currentItem = 0;
+ createHighlight();
+ trackedItem = 0;
+ minExtentDirty = true;
+ maxExtentDirty = true;
+}
+
+FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QmlGraphicsListView);
+ // create object
+ requestedIndex = modelIndex;
+ FxListItem *listItem = 0;
+ if (QmlGraphicsItem *item = model->item(modelIndex, false)) {
+ listItem = new FxListItem(item, q);
+ listItem->index = modelIndex;
+ // initialise attached properties
+ if (sectionCriteria) {
+ QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+ listItem->attached->m_section = sectionCriteria->sectionString(propValue);
+ if (modelIndex > 0) {
+ if (FxListItem *item = visibleItem(modelIndex-1))
+ listItem->attached->m_prevSection = item->attached->section();
+ else
+ listItem->attached->m_prevSection = sectionAt(modelIndex-1);
+ }
+ }
+ // complete
+ model->completeItem();
+ listItem->item->setZValue(1);
+ listItem->item->setParent(q->viewport());
+ QmlGraphicsItemPrivate *itemPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QmlGraphicsItemPrivate::Geometry);
+ if (sectionCriteria && sectionCriteria->delegate()) {
+ if (listItem->attached->m_prevSection != listItem->attached->m_section)
+ createSection(listItem);
+ }
+ unrequestedItems.remove(listItem->item);
+ }
+ requestedIndex = -1;
+
+ return listItem;
+}
+
+void QmlGraphicsListViewPrivate::releaseItem(FxListItem *item)
+{
+ Q_Q(QmlGraphicsListView);
+ if (!item || !model)
+ return;
+ if (trackedItem == item) {
+ const char *notifier1 = orient == QmlGraphicsListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
+ const char *notifier2 = orient == QmlGraphicsListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+ QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ QmlGraphicsItemPrivate *itemPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(item->item));
+ itemPrivate->removeItemChangeListener(this, QmlGraphicsItemPrivate::Geometry);
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ if (item->section) {
+ int i = 0;
+ do {
+ if (!sectionCache[i]) {
+ sectionCache[i] = item->section;
+ sectionCache[i]->setVisible(false);
+ item->section = 0;
+ break;
+ }
+ ++i;
+ } while (i < sectionCacheSize);
+ delete item->section;
+ }
+ delete item;
+}
+
+void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+{
+ Q_Q(QmlGraphicsListView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+ qreal bufferFrom = from - buffer;
+ qreal bufferTo = to + buffer;
+ qreal fillFrom = from;
+ qreal fillTo = to;
+ if (doBuffer && (bufferMode & BufferAfter))
+ fillTo = bufferTo;
+ if (doBuffer && (bufferMode & BufferBefore))
+ fillFrom = bufferFrom;
+
+ int modelIndex = visibleIndex;
+ qreal itemEnd = visiblePos-1;
+ if (!visibleItems.isEmpty()) {
+ visiblePos = (*visibleItems.constBegin())->position();
+ itemEnd = (*(--visibleItems.constEnd()))->endPosition() + spacing;
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+
+ bool changed = false;
+ FxListItem *item = 0;
+ int pos = itemEnd + 1;
+ while (modelIndex < model->count() && pos <= fillTo) {
+ //qDebug() << "refill: append item" << modelIndex << "pos" << pos;
+ if (!(item = createItem(modelIndex)))
+ break;
+ item->setPosition(pos);
+ pos += item->size() + spacing;
+ visibleItems.append(item);
+ ++modelIndex;
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+ while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
+ //qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+ if (!(item = createItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ visiblePos -= item->size() + spacing;
+ item->setPosition(visiblePos);
+ visibleItems.prepend(item);
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < bufferFrom) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ deferredRelease = false;
+ } else {
+ deferredRelease = true;
+ }
+ if (changed) {
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ if (visibleItems.count())
+ visiblePos = (*visibleItems.constBegin())->position();
+ updateAverage();
+ if (sectionCriteria)
+ updateCurrentSection();
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ updateViewport();
+ updateUnrequestedPositions();
+ } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
+ refill(from, to, true);
+ }
+ lazyRelease = false;
+}
+
+void QmlGraphicsListViewPrivate::layout()
+{
+ Q_Q(QmlGraphicsListView);
+ updateSections();
+ if (!visibleItems.isEmpty()) {
+ int oldEnd = visibleItems.last()->endPosition();
+ int pos = visibleItems.first()->endPosition() + spacing + 1;
+ for (int i=1; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ item->setPosition(pos);
+ pos += item->size() + spacing;
+ }
+ // move current item if it is after the visible items.
+ if (currentItem && currentIndex > lastVisibleIndex())
+ currentItem->setPosition(currentItem->position() + (visibleItems.last()->endPosition() - oldEnd));
+ }
+ if (!isValid())
+ return;
+ q->refill();
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ updateHighlight();
+ fixupPosition();
+ q->refill();
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ updateViewport();
+}
+
+void QmlGraphicsListViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QmlGraphicsListView);
+ QHash<QmlGraphicsItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QmlGraphicsListViewPrivate::updateUnrequestedPositions()
+{
+ Q_Q(QmlGraphicsListView);
+ if (unrequestedItems.count()) {
+ qreal pos = position();
+ QHash<QmlGraphicsItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ QmlGraphicsItem *item = it.key();
+ if (orient == QmlGraphicsListView::Vertical) {
+ if (item->y() + item->height() > pos && item->y() < pos + q->height())
+ item->setY(positionAt(*it));
+ } else {
+ if (item->x() + item->width() > pos && item->x() < pos + q->width())
+ item->setX(positionAt(*it));
+ }
+ }
+ }
+}
+
+void QmlGraphicsListViewPrivate::updateTrackedItem()
+{
+ Q_Q(QmlGraphicsListView);
+ FxListItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ FxListItem *oldTracked = trackedItem;
+
+ const char *notifier1 = orient == QmlGraphicsListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
+ const char *notifier2 = orient == QmlGraphicsListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ }
+ if (trackedItem && trackedItem != oldTracked)
+ q->trackedPositionChanged();
+}
+
+void QmlGraphicsListViewPrivate::createHighlight()
+{
+ Q_Q(QmlGraphicsListView);
+ bool changed = false;
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ delete highlight->item;
+ delete highlight;
+ highlight = 0;
+ delete highlightPosAnimator;
+ delete highlightSizeAnimator;
+ highlightPosAnimator = 0;
+ highlightSizeAnimator = 0;
+ changed = true;
+ }
+
+ if (currentItem) {
+ QmlGraphicsItem *item = 0;
+ if (highlightComponent) {
+ QmlContext *highlightContext = new QmlContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ highlightContext->setParent(nobj);
+ item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QmlGraphicsItem;
+ }
+ if (item) {
+ item->setParent(q->viewport());
+ highlight = new FxListItem(item, q);
+ if (orient == QmlGraphicsListView::Vertical)
+ highlight->item->setHeight(currentItem->item->height());
+ else
+ highlight->item->setWidth(currentItem->item->width());
+ const QLatin1String posProp(orient == QmlGraphicsListView::Vertical ? "y" : "x");
+ highlightPosAnimator = new QmlEaseFollow(q);
+ highlightPosAnimator->setTarget(QmlMetaProperty(highlight->item, posProp));
+ highlightPosAnimator->setVelocity(highlightMoveSpeed);
+ highlightPosAnimator->setEnabled(autoHighlight);
+ const QLatin1String sizeProp(orient == QmlGraphicsListView::Vertical ? "height" : "width");
+ highlightSizeAnimator = new QmlEaseFollow(q);
+ highlightSizeAnimator->setVelocity(highlightResizeSpeed);
+ highlightSizeAnimator->setTarget(QmlMetaProperty(highlight->item, sizeProp));
+ highlightSizeAnimator->setEnabled(autoHighlight);
+ changed = true;
+ }
+ }
+ if (changed)
+ emit q->highlightChanged();
+}
+
+void QmlGraphicsListViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ if (currentItem && autoHighlight && highlight && !moving) {
+ // auto-update highlight
+ highlightPosAnimator->setSourceValue(currentItem->position());
+ highlightSizeAnimator->setSourceValue(currentItem->size());
+ if (orient == QmlGraphicsListView::Vertical) {
+ if (highlight->item->width() == 0)
+ highlight->item->setWidth(currentItem->item->width());
+ } else {
+ if (highlight->item->height() == 0)
+ highlight->item->setHeight(currentItem->item->height());
+ }
+ }
+ updateTrackedItem();
+}
+
+void QmlGraphicsListViewPrivate::createSection(FxListItem *listItem)
+{
+ Q_Q(QmlGraphicsListView);
+ if (!sectionCriteria || !sectionCriteria->delegate())
+ return;
+ if (listItem->attached->m_prevSection != listItem->attached->m_section) {
+ if (!listItem->section) {
+ int i = sectionCacheSize-1;
+ while (i >= 0 && !sectionCache[i])
+ --i;
+ if (i >= 0) {
+ listItem->section = sectionCache[i];
+ sectionCache[i] = 0;
+ listItem->section->setVisible(true);
+ QmlContext *context = QmlEngine::contextForObject(listItem->section)->parentContext();
+ context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
+ } else {
+ QmlContext *context = new QmlContext(qmlContext(q));
+ context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
+ QObject *nobj = sectionCriteria->delegate()->create(context);
+ if (nobj) {
+ context->setParent(nobj);
+ listItem->section = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!listItem->section) {
+ delete nobj;
+ } else {
+ listItem->section->setZValue(1);
+ listItem->section->setParent(q->viewport());
+ }
+ } else {
+ delete context;
+ }
+ }
+ }
+ } else if (listItem->section) {
+ int i = 0;
+ do {
+ if (!sectionCache[i]) {
+ sectionCache[i] = listItem->section;
+ sectionCache[i]->setVisible(false);
+ listItem->section = 0;
+ return;
+ }
+ ++i;
+ } while (i < sectionCacheSize);
+ delete listItem->section;
+ listItem->section = 0;
+ }
+}
+
+void QmlGraphicsListViewPrivate::updateSections()
+{
+ if (sectionCriteria) {
+ QString prevSection;
+ if (visibleIndex > 0)
+ prevSection = sectionAt(visibleIndex-1);
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ if (visibleItems.at(i)->index != -1) {
+ QmlGraphicsListViewAttached *attached = visibleItems.at(i)->attached;
+ attached->setPrevSection(prevSection);
+ createSection(visibleItems.at(i));
+ prevSection = attached->section();
+ }
+ }
+ }
+}
+
+void QmlGraphicsListViewPrivate::updateCurrentSection()
+{
+ if (!sectionCriteria || visibleItems.isEmpty()) {
+ currentSection = QString();
+ return;
+ }
+ int index = 0;
+ while (visibleItems.at(index)->endPosition() < position() && index < visibleItems.count())
+ ++index;
+
+ if (index < visibleItems.count())
+ currentSection = visibleItems.at(index)->attached->section();
+ else
+ currentSection = visibleItems.first()->attached->section();
+}
+
+void QmlGraphicsListViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QmlGraphicsListView);
+ if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
+ updateHighlight();
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+ FxListItem *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ if (modelIndex == visibleIndex - 1) {
+ // We can calculate exact postion in this case
+ currentItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
+ } else {
+ // Create current item now and position as best we can.
+ // Its position will be corrected when it becomes visible.
+ currentItem->setPosition(positionAt(modelIndex));
+ }
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ // Release the old current item
+ releaseItem(oldCurrentItem);
+}
+
+void QmlGraphicsListViewPrivate::updateAverage()
+{
+ if (!visibleItems.count())
+ return;
+ qreal sum = 0.0;
+ for (int i = 0; i < visibleItems.count(); ++i)
+ sum += visibleItems.at(i)->size();
+ averageSize = sum / visibleItems.count();
+}
+
+void QmlGraphicsListViewPrivate::updateFooter()
+{
+ Q_Q(QmlGraphicsListView);
+ if (!footer && footerComponent) {
+ QmlGraphicsItem *item = 0;
+ QmlContext *context = new QmlContext(qmlContext(q));
+ QObject *nobj = footerComponent->create(context);
+ if (nobj) {
+ context->setParent(nobj);
+ item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ item->setParent(q->viewport());
+ item->setZValue(1);
+ footer = new FxListItem(item, q);
+ }
+ }
+ if (footer) {
+ if (visibleItems.count()) {
+ qreal endPos = endPosition();
+ if (lastVisibleIndex() == model->count()-1) {
+ footer->setPosition(endPos);
+ } else {
+ qreal visiblePos = position() + q->height();
+ if (endPos <= visiblePos || footer->position() < endPos)
+ footer->setPosition(endPos);
+ }
+ } else {
+ footer->setPosition(visiblePos);
+ }
+ }
+}
+
+void QmlGraphicsListViewPrivate::updateHeader()
+{
+ Q_Q(QmlGraphicsListView);
+ if (!header && headerComponent) {
+ QmlGraphicsItem *item = 0;
+ QmlContext *context = new QmlContext(qmlContext(q));
+ QObject *nobj = headerComponent->create(context);
+ if (nobj) {
+ context->setParent(nobj);
+ item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ item->setParent(q->viewport());
+ item->setZValue(1);
+ header = new FxListItem(item, q);
+ if (visibleItems.isEmpty())
+ visiblePos = header->size();
+ }
+ }
+ if (header) {
+ if (visibleItems.count()) {
+ qreal startPos = startPosition();
+ if (visibleIndex == 0) {
+ header->setPosition(startPos - header->size());
+ } else {
+ if (position() <= startPos || header->position() > startPos - header->size())
+ header->setPosition(startPos - header->size());
+ }
+ } else {
+ header->setPosition(0);
+ }
+ }
+}
+
+void QmlGraphicsListViewPrivate::fixupPosition()
+{
+ moveReason = Other;
+ if (orient == QmlGraphicsListView::Vertical)
+ fixupY();
+ else
+ fixupX();
+}
+
+void QmlGraphicsListViewPrivate::fixupY()
+{
+ Q_Q(QmlGraphicsListView);
+ if (orient == QmlGraphicsListView::Horizontal)
+ return;
+ if (!q->yflick() || _moveY.timeLine())
+ return;
+
+ int oldDuration = fixupDuration;
+ fixupDuration = moveReason == Mouse ? fixupDuration : 0;
+
+ if (haveHighlightRange && highlightRange == QmlGraphicsListView::StrictlyEnforceRange) {
+ if (currentItem && highlight && currentItem->position() != highlight->position()) {
+ timeline.reset(_moveY);
+ timeline.move(_moveY, -(currentItem->position() - highlightRangeStart), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ vTime = timeline.time();
+ }
+ } else if (snapMode != QmlGraphicsListView::NoSnap) {
+ if (FxListItem *item = snapItemAt(position())) {
+ qreal pos = qMin(item->position() - highlightRangeStart, -q->maxYExtent());
+ qreal dist = qAbs(_moveY + pos);
+ if (dist > 0) {
+ timeline.reset(_moveY);
+ timeline.move(_moveY, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ vTime = timeline.time();
+ }
+ }
+ } else {
+ QmlGraphicsFlickablePrivate::fixupY();
+ }
+ fixupDuration = oldDuration;
+}
+
+void QmlGraphicsListViewPrivate::fixupX()
+{
+ Q_Q(QmlGraphicsListView);
+ if (orient == QmlGraphicsListView::Vertical)
+ return;
+ if (!q->xflick() || _moveX.timeLine())
+ return;
+
+ int oldDuration = fixupDuration;
+ fixupDuration = moveReason == Mouse ? fixupDuration : 0;
+
+ if (haveHighlightRange && highlightRange == QmlGraphicsListView::StrictlyEnforceRange) {
+ if (currentItem && highlight && currentItem->position() != highlight->position()) {
+ timeline.reset(_moveX);
+ timeline.move(_moveX, -(currentItem->position() - highlightRangeStart), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ vTime = timeline.time();
+ }
+ } else if (snapMode != QmlGraphicsListView::NoSnap) {
+ if (FxListItem *item = snapItemAt(position())) {
+ qreal pos = qMin(item->position() - highlightRangeStart, -q->maxXExtent());
+ qreal dist = qAbs(_moveX + pos);
+ if (dist > 0) {
+ timeline.reset(_moveX);
+ timeline.move(_moveX, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration);
+ vTime = timeline.time();
+ }
+ }
+ } else {
+ QmlGraphicsFlickablePrivate::fixupX();
+ }
+ fixupDuration = oldDuration;
+}
+
+void QmlGraphicsListViewPrivate::flickX(qreal velocity)
+{
+ Q_Q(QmlGraphicsListView);
+
+ moveReason = Mouse;
+ if ((!haveHighlightRange || highlightRange != QmlGraphicsListView::StrictlyEnforceRange) && snapMode == QmlGraphicsListView::NoSnap) {
+ QmlGraphicsFlickablePrivate::flickX(velocity);
+ return;
+ }
+ qreal maxDistance = -1;
+ const qreal maxX = q->maxXExtent();
+ const qreal minX = q->minXExtent();
+ // -ve velocity means list is moving up
+ if (velocity > 0) {
+ if (snapMode == QmlGraphicsListView::SnapOneItem) {
+ if (FxListItem *item = firstVisibleItem())
+ maxDistance = qAbs(item->position() + _moveX.value());
+ } else if (_moveX.value() < minX) {
+ maxDistance = qAbs(minX -_moveX.value() + (overShoot?30:0));
+ }
+ if (snapMode != QmlGraphicsListView::SnapToItem && highlightRange != QmlGraphicsListView::StrictlyEnforceRange)
+ flickTargetX = minX;
+ } else {
+ if (snapMode == QmlGraphicsListView::SnapOneItem) {
+ if (FxListItem *item = nextVisibleItem())
+ maxDistance = qAbs(item->position() + _moveX.value());
+ } else if (_moveX.value() > maxX) {
+ maxDistance = qAbs(maxX - _moveX.value()) + (overShoot?30:0);
+ }
+ if (snapMode != QmlGraphicsListView::SnapToItem && highlightRange != QmlGraphicsListView::StrictlyEnforceRange)
+ flickTargetX = maxX;
+ }
+ if (maxDistance > 0 && (snapMode != QmlGraphicsListView::NoSnap || highlightRange == QmlGraphicsListView::StrictlyEnforceRange)) {
+ // These modes require the list to stop exactly on an item boundary.
+ // The initial flick will estimate the boundary to stop on.
+ // Since list items can have variable sizes, the boundary will be
+ // reevaluated and adjusted as we approach the boundary.
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ if (!flicked) {
+ // the initial flick - estimate boundary
+ qreal accel = deceleration;
+ qreal v2 = v * v;
+ qreal maxAccel = v2 / (2.0f * maxDistance);
+ if (maxAccel < accel) {
+ qreal dist = v2 / (accel * 2.0);
+ if (v > 0)
+ dist = -dist;
+ flickTargetX = -snapPosAt(-(_moveX.value() - highlightRangeStart) + dist) + highlightRangeStart;
+ dist = -flickTargetX + _moveX.value();
+ accel = v2 / (2.0f * qAbs(dist));
+ overshootDist = 0.0;
+ } else {
+ flickTargetX = velocity > 0 ? minX : maxX;
+ overshootDist = overShoot ? 30 : 0;
+ }
+ timeline.reset(_moveX);
+ timeline.accel(_moveX, v, accel, maxDistance + overshootDist);
+ timeline.execute(fixupXEvent);
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ correctFlick = true;
+ } else {
+ // reevaluate the target boundary.
+ qreal newtarget = flickTargetX;
+ if (snapMode != QmlGraphicsListView::NoSnap || highlightRange == QmlGraphicsListView::StrictlyEnforceRange)
+ newtarget = -snapPosAt(-(flickTargetX - highlightRangeStart)) + highlightRangeStart;
+ if (velocity < 0 && newtarget < maxX)
+ newtarget = maxX;
+ else if (velocity > 0 && newtarget > minX)
+ newtarget = minX;
+ if (newtarget == flickTargetX) // boundary unchanged - nothing to do
+ return;
+ flickTargetX = newtarget;
+ qreal dist = -newtarget + _moveX.value();
+ if ((v < 0 && dist < 0) || (v > 0 && dist > 0)) {
+ correctFlick = false;
+ timeline.reset(_moveX);
+ fixupX();
+ return;
+ }
+ timeline.reset(_moveX);
+ timeline.accelDistance(_moveX, v, -dist + (v < 0 ? -overshootDist : overshootDist));
+ timeline.execute(fixupXEvent);
+ }
+ } else {
+ correctFlick = false;
+ timeline.reset(_moveX);
+ fixupX();
+ }
+}
+
+void QmlGraphicsListViewPrivate::flickY(qreal velocity)
+{
+ Q_Q(QmlGraphicsListView);
+
+ moveReason = Mouse;
+ if ((!haveHighlightRange || highlightRange != QmlGraphicsListView::StrictlyEnforceRange) && snapMode == QmlGraphicsListView::NoSnap) {
+ QmlGraphicsFlickablePrivate::flickY(velocity);
+ return;
+ }
+ qreal maxDistance = -1;
+ const qreal maxY = q->maxYExtent();
+ const qreal minY = q->minYExtent();
+ // -ve velocity means list is moving up
+ if (velocity > 0) {
+ if (snapMode == QmlGraphicsListView::SnapOneItem) {
+ if (FxListItem *item = firstVisibleItem())
+ maxDistance = qAbs(item->position() + _moveY.value());
+ } else if (_moveY.value() < minY) {
+ maxDistance = qAbs(minY -_moveY.value() + (overShoot?30:0));
+ }
+ if (snapMode != QmlGraphicsListView::SnapToItem && highlightRange != QmlGraphicsListView::StrictlyEnforceRange)
+ flickTargetY = minY;
+ } else {
+ if (snapMode == QmlGraphicsListView::SnapOneItem) {
+ if (FxListItem *item = nextVisibleItem())
+ maxDistance = qAbs(item->position() + _moveY.value());
+ } else if (_moveY.value() > maxY) {
+ maxDistance = qAbs(maxY - _moveY.value()) + (overShoot?30:0);
+ }
+ if (snapMode != QmlGraphicsListView::SnapToItem && highlightRange != QmlGraphicsListView::StrictlyEnforceRange)
+ flickTargetY = maxY;
+ }
+ if (maxDistance > 0 && (snapMode != QmlGraphicsListView::NoSnap || highlightRange == QmlGraphicsListView::StrictlyEnforceRange)) {
+ // These modes require the list to stop exactly on an item boundary.
+ // The initial flick will estimate the boundary to stop on.
+ // Since list items can have variable sizes, the boundary will be
+ // reevaluated and adjusted as we approach the boundary.
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ if (!flicked) {
+ // the initial flick - estimate boundary
+ qreal accel = deceleration;
+ qreal v2 = v * v;
+ qreal maxAccel = v2 / (2.0f * maxDistance);
+ if (maxAccel < accel) {
+ qreal dist = v2 / (accel * 2.0);
+ if (v > 0)
+ dist = -dist;
+ flickTargetY = -snapPosAt(-(_moveY.value() - highlightRangeStart) + dist) + highlightRangeStart;
+ dist = -flickTargetY + _moveY.value();
+ accel = v2 / (2.0f * qAbs(dist));
+ overshootDist = 0.0;
+ } else {
+ flickTargetY = velocity > 0 ? minY : maxY;
+ overshootDist = overShoot ? 30 : 0;
+ }
+ timeline.reset(_moveY);
+ timeline.accel(_moveY, v, accel, maxDistance + overshootDist);
+ timeline.execute(fixupYEvent);
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ correctFlick = true;
+ } else {
+ // reevaluate the target boundary.
+ qreal newtarget = flickTargetY;
+ if (snapMode != QmlGraphicsListView::NoSnap || highlightRange == QmlGraphicsListView::StrictlyEnforceRange)
+ newtarget = -snapPosAt(-(flickTargetY - highlightRangeStart)) + highlightRangeStart;
+ if (velocity < 0 && newtarget < maxY)
+ newtarget = maxY;
+ else if (velocity > 0 && newtarget > minY)
+ newtarget = minY;
+ if (newtarget == flickTargetY) // boundary unchanged - nothing to do
+ return;
+ flickTargetY = newtarget;
+ qreal dist = -newtarget + _moveY.value();
+ if ((v < 0 && dist < 0) || (v > 0 && dist > 0)) {
+ correctFlick = false;
+ timeline.reset(_moveY);
+ fixupY();
+ return;
+ }
+ timeline.reset(_moveY);
+ timeline.accelDistance(_moveY, v, -dist + (v < 0 ? -overshootDist : overshootDist));
+ timeline.execute(fixupYEvent);
+ }
+ } else {
+ correctFlick = false;
+ timeline.reset(_moveY);
+ fixupY();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass ListView QmlGraphicsListView
+ \inherits Flickable
+ \brief The ListView item provides a list view of items provided by a model.
+
+ The model is typically provided by a QAbstractListModel "C++ model object",
+ but can also be created directly in QML. The items are laid out vertically
+ or horizontally and may be flicked to scroll.
+
+ The below example creates a very simple vertical list, using a QML model.
+ \image trivialListView.png
+
+ The user interface defines a delegate to display an item, a highlight,
+ and the ListView which uses the above.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml 3
+
+ The model is defined as a ListModel using QML:
+ \quotefile doc/src/snippets/declarative/listview/dummydata/ContactModel.qml
+
+ In this case ListModel is a handy way for us to test our UI. In practice
+ the model would be implemented in C++, or perhaps via a SQL data source.
+*/
+
+QmlGraphicsListView::QmlGraphicsListView(QmlGraphicsItem *parent)
+ : QmlGraphicsFlickable(*(new QmlGraphicsListViewPrivate), parent)
+{
+ Q_D(QmlGraphicsListView);
+ d->init();
+}
+
+QmlGraphicsListView::~QmlGraphicsListView()
+{
+ Q_D(QmlGraphicsListView);
+ d->clear();
+ if (d->ownModel)
+ delete d->model;
+ delete d->header;
+ delete d->footer;
+}
+
+/*!
+ \qmlattachedproperty bool ListView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+
+ This property may be used to adjust the appearance of the current item, for example:
+
+ \snippet doc/src/snippets/declarative/listview/highlight.qml 0
+*/
+
+/*!
+ \qmlattachedproperty ListView ListView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty string ListView::prevSection
+ This attached property holds the section of the previous element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty string ListView::section
+ This attached property holds the section of this element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty bool ListView::delayRemove
+ This attached property holds whether the delegate may be destroyed.
+
+ It is attached to each instance of the delegate.
+
+ It is sometimes necessary to delay the destruction of an item
+ until an animation completes.
+
+ The example below ensures that the animation completes before
+ the item is removed from the list.
+
+ \code
+ Component {
+ id: myDelegate
+ Item {
+ id: wrapper
+ ListView.onRemove: SequentialAnimation {
+ PropertyAction { target: wrapper.ListView; property: "delayRemove"; value: true }
+ NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing: "easeInOutQuad" }
+ PropertyAction { target: wrapper.ListView; property: "delayRemove"; value: false }
+ }
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \qmlattachedsignal ListView::onAdd()
+ This attached handler is called immediately after an item is added to the view.
+*/
+
+/*!
+ \qmlattachedsignal ListView::onRemove()
+ This attached handler is called immediately before an item is removed from the view.
+*/
+
+/*!
+ \qmlproperty model ListView::model
+ This property holds the model providing data for the list.
+
+ The model provides a set of data that is used to create the items
+ for the view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass or a simple list.
+
+ Models can also be created directly in QML, using a \l{ListModel},
+ \l{XmlListModel} or \l{VisualItemModel}.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QmlGraphicsListView::model() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->modelVariant;
+}
+
+void QmlGraphicsListView::setModel(const QVariant &model)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QmlGraphicsItem*)), this, SLOT(destroyingItem(QmlGraphicsItem*)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QmlGraphicsVisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QmlGraphicsVisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ if (isComponentComplete()) {
+ refill();
+ if (d->currentIndex >= d->model->count() || d->currentIndex < 0) {
+ setCurrentIndex(0);
+ } else {
+ d->moveReason = QmlGraphicsListViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ }
+ }
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QmlGraphicsItem*)), this, SLOT(destroyingItem(QmlGraphicsItem*)));
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty component ListView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ Note that the ListView will layout the items based on the size of the root item
+ in the delegate.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/listview/listview.qml 0
+*/
+QmlComponent *QmlGraphicsListView::delegate() const
+{
+ Q_D(const QmlGraphicsListView);
+ if (d->model) {
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QmlGraphicsListView::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QmlGraphicsListView);
+ if (delegate == this->delegate())
+ return;
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model)) {
+ dataModel->setDelegate(delegate);
+ if (isComponentComplete()) {
+ for (int i = 0; i < d->visibleItems.count(); ++i)
+ d->releaseItem(d->visibleItems.at(i));
+ d->visibleItems.clear();
+ refill();
+ d->moveReason = QmlGraphicsListViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ }
+ }
+}
+
+/*!
+ \qmlproperty int ListView::currentIndex
+ \qmlproperty Item ListView::currentItem
+
+ \c currentIndex holds the index of the current item.
+ \c currentItem is the current item. Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QmlGraphicsListView::currentIndex() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->currentIndex;
+}
+
+void QmlGraphicsListView::setCurrentIndex(int index)
+{
+ Q_D(QmlGraphicsListView);
+ if (isComponentComplete() && d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) {
+ d->moveReason = QmlGraphicsListViewPrivate::SetIndex;
+ cancelFlick();
+ d->updateCurrent(index);
+ } else {
+ d->currentIndex = index;
+ }
+}
+
+QmlGraphicsItem *QmlGraphicsListView::currentItem()
+{
+ Q_D(QmlGraphicsListView);
+ if (!d->currentItem)
+ return 0;
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty Item ListView::highlightItem
+
+ \c highlightItem holds the highlight item, which was created
+ from the \l highlight component.
+
+ The highlightItem is managed by the view unless
+ \l highlightFollowsCurrentItem is set to false.
+
+ \sa highlight, highlightFollowsCurrentItem
+*/
+QmlGraphicsItem *QmlGraphicsListView::highlightItem()
+{
+ Q_D(QmlGraphicsListView);
+ if (!d->highlight)
+ return 0;
+ return d->highlight->item;
+}
+
+/*!
+ \qmlproperty int ListView::count
+ This property holds the number of items in the view.
+*/
+int QmlGraphicsListView::count() const
+{
+ Q_D(const QmlGraphicsListView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty component ListView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each list.
+ The geometry of the resultant component instance will be managed by the list
+ so as to stay with the current item, unless the highlightFollowsCurrentItem
+ property is false.
+
+ The below example demonstrates how to make a simple highlight
+ for a vertical list.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml 1
+ \image trivialListView.png
+
+ \sa highlightItem, highlightFollowsCurrentItem
+*/
+QmlComponent *QmlGraphicsListView::highlight() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->highlightComponent;
+}
+
+void QmlGraphicsListView::setHighlight(QmlComponent *highlight)
+{
+ Q_D(QmlGraphicsListView);
+ if (highlight != d->highlightComponent) {
+ d->highlightComponent = highlight;
+ d->createHighlight();
+ if (d->currentItem)
+ d->updateHighlight();
+ }
+}
+
+/*!
+ \qmlproperty bool ListView::highlightFollowsCurrentItem
+ This property holds whether the highlight is managed by the view.
+
+ If highlightFollowsCurrentItem is true, the highlight will be moved smoothly
+ to follow the current item. If highlightFollowsCurrentItem is false, the
+ highlight will not be moved by the view, and must be implemented
+ by the highlight. The following example creates a highlight with
+ its motion defined by the spring \l {SpringFollow}:
+
+ \snippet doc/src/snippets/declarative/listview/highlight.qml 1
+
+ Note that the highlight animation also affects the way that the view
+ is scrolled. This is because the view moves to maintain the
+ highlight within the preferred highlight range (or visible viewport).
+
+ \sa highlight, highlightMoveSpeed
+*/
+bool QmlGraphicsListView::highlightFollowsCurrentItem() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->autoHighlight;
+}
+
+void QmlGraphicsListView::setHighlightFollowsCurrentItem(bool autoHighlight)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->autoHighlight != autoHighlight) {
+ d->autoHighlight = autoHighlight;
+ if (d->highlightPosAnimator) {
+ d->highlightPosAnimator->setEnabled(d->autoHighlight);
+ d->highlightSizeAnimator->setEnabled(d->autoHighlight);
+ }
+ d->updateHighlight();
+ }
+}
+
+//###Possibly rename these properties, since they are very useful even without a highlight?
+/*!
+ \qmlproperty real ListView::preferredHighlightBegin
+ \qmlproperty real ListView::preferredHighlightEnd
+ \qmlproperty enumeration ListView::highlightRangeMode
+
+ These properties set the preferred range of the highlight (current item)
+ within the view.
+
+ Note that this is the correct way to influence where the
+ current item ends up when the list scrolls. For example, if you want the
+ currently selected item to be in the middle of the list, then set the
+ highlight range to be where the middle item would go. Then, when the list scrolls,
+ the currently selected item will be the item at that spot. This also applies to
+ when the currently selected item changes - it will scroll to within the preferred
+ highlight range. Furthermore, the behaviour of the current item index will occur
+ whether or not a highlight exists.
+
+ If highlightRangeMode is set to \e ApplyRange the view will
+ attempt to maintain the highlight within the range, however
+ the highlight can move outside of the range at the ends of the list
+ or due to a mouse interaction.
+
+ If highlightRangeMode is set to \e StrictlyEnforceRange the highlight will never
+ move outside of the range. This means that the current item will change
+ if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+
+ The default value is \e NoHighlightRange.
+
+ Note that a valid range requires preferredHighlightEnd to be greater
+ than or equal to preferredHighlightBegin.
+*/
+qreal QmlGraphicsListView::preferredHighlightBegin() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->highlightRangeStart;
+}
+
+void QmlGraphicsListView::setPreferredHighlightBegin(qreal start)
+{
+ Q_D(QmlGraphicsListView);
+ d->highlightRangeStart = start;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+}
+
+qreal QmlGraphicsListView::preferredHighlightEnd() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->highlightRangeEnd;
+}
+
+void QmlGraphicsListView::setPreferredHighlightEnd(qreal end)
+{
+ Q_D(QmlGraphicsListView);
+ d->highlightRangeEnd = end;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+}
+
+QmlGraphicsListView::HighlightRangeMode QmlGraphicsListView::highlightRangeMode() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->highlightRange;
+}
+
+void QmlGraphicsListView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+ Q_D(QmlGraphicsListView);
+ d->highlightRange = mode;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+}
+
+/*!
+ \qmlproperty real ListView::spacing
+
+ This property holds the spacing to leave between items.
+*/
+qreal QmlGraphicsListView::spacing() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->spacing;
+}
+
+void QmlGraphicsListView::setSpacing(qreal spacing)
+{
+ Q_D(QmlGraphicsListView);
+ if (spacing != d->spacing) {
+ d->spacing = spacing;
+ d->layout();
+ emit spacingChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration ListView::orientation
+ This property holds the orientation of the list.
+
+ Possible values are \c Vertical (default) and \c Horizontal.
+
+ Vertical Example:
+ \image trivialListView.png
+ Horizontal Example:
+ \image ListViewHorizontal.png
+*/
+QmlGraphicsListView::Orientation QmlGraphicsListView::orientation() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->orient;
+}
+
+void QmlGraphicsListView::setOrientation(QmlGraphicsListView::Orientation orientation)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->orient != orientation) {
+ d->orient = orientation;
+ if (d->orient == QmlGraphicsListView::Vertical) {
+ setViewportWidth(-1);
+ setFlickDirection(VerticalFlick);
+ } else {
+ setViewportHeight(-1);
+ setFlickDirection(HorizontalFlick);
+ }
+ d->clear();
+ refill();
+ emit orientationChanged();
+ d->updateCurrent(d->currentIndex);
+ }
+}
+
+/*!
+ \qmlproperty bool ListView::keyNavigationWraps
+ This property holds whether the list wraps key navigation
+
+ If this property is true then key presses to move off of one end of the list will cause the
+ current item to jump to the other end.
+*/
+bool QmlGraphicsListView::isWrapEnabled() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->wrap;
+}
+
+void QmlGraphicsListView::setWrapEnabled(bool wrap)
+{
+ Q_D(QmlGraphicsListView);
+ d->wrap = wrap;
+}
+
+/*!
+ \qmlproperty int ListView::cacheBuffer
+ This property holds the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the list
+ and below the bottom of the list to cache. Setting this value can make
+ scrolling the list smoother at the expense of additional memory usage.
+*/
+int QmlGraphicsListView::cacheBuffer() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->buffer;
+}
+
+void QmlGraphicsListView::setCacheBuffer(int b)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->buffer != b) {
+ d->buffer = b;
+ if (isComponentComplete()) {
+ d->bufferMode = QmlGraphicsListViewPrivate::BufferBefore | QmlGraphicsListViewPrivate::BufferAfter;
+ refill();
+ }
+ }
+}
+
+/*!
+ \qmlproperty string ListView::section.property
+ \qmlproperty enumeration ListView::section.criteria
+ These properties hold the expression to be evaluated for the section attached property.
+
+ section.property hold the name of the property to use to determine
+ the section the item is in.
+
+ section.criteria holds the criteria to use to get the section. It
+ can be either:
+ \list
+ \o ViewSection.FullString (default) - section is the value of the property.
+ \o ViewSection.FirstCharacter - section is the first character of the property value.
+ \endlist
+
+ Each item in the list has attached properties named \c ListView.section and
+ \c ListView.prevSection. These may be used to place a section header for
+ related items. The example below assumes that the model is sorted by size of
+ pet. The section expression is the size property. If \c ListView.section and
+ \c ListView.prevSection differ, the item will display a section header.
+
+ \snippet examples/declarative/listview/sections.qml 0
+
+ \image ListViewSections.png
+*/
+QmlGraphicsViewSection *QmlGraphicsListView::sectionCriteria()
+{
+ Q_D(QmlGraphicsListView);
+ if (!d->sectionCriteria)
+ d->sectionCriteria = new QmlGraphicsViewSection(this);
+ return d->sectionCriteria;
+}
+
+/*!
+ \qmlproperty string ListView::currentSection
+ This property holds the section that is currently at the beginning of the view.
+*/
+QString QmlGraphicsListView::currentSection() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->currentSection;
+}
+
+/*!
+ \qmlproperty real ListView::highlightMoveSpeed
+ \qmlproperty real ListView::highlightResizeSpeed
+ These properties hold the move and resize animation speed of the highlight delegate.
+
+ highlightFollowsCurrentItem must be true for these properties
+ to have effect.
+
+ The default value for these properties is 400 pixels/second.
+
+ \sa highlightFollowsCurrentItem
+*/
+qreal QmlGraphicsListView::highlightMoveSpeed() const
+{
+ Q_D(const QmlGraphicsListView);\
+ return d->highlightMoveSpeed;
+}
+
+void QmlGraphicsListView::setHighlightMoveSpeed(qreal speed)
+{
+ Q_D(QmlGraphicsListView);\
+ if (d->highlightMoveSpeed != speed) {
+ d->highlightMoveSpeed = speed;
+ if (d->highlightPosAnimator)
+ d->highlightPosAnimator->setVelocity(d->highlightMoveSpeed);
+ emit highlightMoveSpeedChanged();
+ }
+}
+
+qreal QmlGraphicsListView::highlightResizeSpeed() const
+{
+ Q_D(const QmlGraphicsListView);\
+ return d->highlightResizeSpeed;
+}
+
+void QmlGraphicsListView::setHighlightResizeSpeed(qreal speed)
+{
+ Q_D(QmlGraphicsListView);\
+ if (d->highlightResizeSpeed != speed) {
+ d->highlightResizeSpeed = speed;
+ if (d->highlightSizeAnimator)
+ d->highlightSizeAnimator->setVelocity(d->highlightResizeSpeed);
+ emit highlightResizeSpeedChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration ListView::snapMode
+
+ This property determines where the view will settle following a drag or flick.
+ The allowed values are:
+
+ \list
+ \o NoSnap (default) - the view will stop anywhere within the visible area.
+ \o SnapToItem - the view will settle with an item aligned with the start of
+ the view.
+ \o SnapOneItem - the view will settle no more than one item away from the first
+ visible item at the time the mouse button is released. This mode is particularly
+ useful for moving one page at a time.
+ \endlist
+*/
+QmlGraphicsListView::SnapMode QmlGraphicsListView::snapMode() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->snapMode;
+}
+
+void QmlGraphicsListView::setSnapMode(SnapMode mode)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->snapMode != mode) {
+ d->snapMode = mode;
+ }
+}
+
+QmlComponent *QmlGraphicsListView::footer() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->footerComponent;
+}
+
+void QmlGraphicsListView::setFooter(QmlComponent *footer)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->footerComponent != footer) {
+ if (d->footer) {
+ delete d->footer;
+ d->footer = 0;
+ }
+ d->footerComponent = footer;
+ d->minExtentDirty = true;
+ d->maxExtentDirty = true;
+ d->updateFooter();
+ d->updateViewport();
+ }
+}
+
+QmlComponent *QmlGraphicsListView::header() const
+{
+ Q_D(const QmlGraphicsListView);
+ return d->headerComponent;
+}
+
+void QmlGraphicsListView::setHeader(QmlComponent *header)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->headerComponent != header) {
+ if (d->header) {
+ delete d->header;
+ d->header = 0;
+ }
+ d->headerComponent = header;
+ d->minExtentDirty = true;
+ d->maxExtentDirty = true;
+ d->updateHeader();
+ d->updateFooter();
+ d->updateViewport();
+ }
+}
+
+void QmlGraphicsListView::viewportMoved()
+{
+ Q_D(QmlGraphicsListView);
+ QmlGraphicsFlickable::viewportMoved();
+ d->lazyRelease = true;
+ refill();
+ if (isFlicking() || d->moving)
+ d->moveReason = QmlGraphicsListViewPrivate::Mouse;
+ if (d->moveReason != QmlGraphicsListViewPrivate::SetIndex) {
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
+ // reposition highlight
+ qreal pos = d->highlight->position();
+ if (pos > d->position() + d->highlightRangeEnd - 1 - d->highlight->size())
+ pos = d->position() + d->highlightRangeEnd - 1 - d->highlight->size();
+ if (pos < d->position() + d->highlightRangeStart)
+ pos = d->position() + d->highlightRangeStart;
+ d->highlight->setPosition(pos);
+
+ // update current index
+ int idx = d->snapIndex();
+ if (idx >= 0 && idx != d->currentIndex)
+ d->updateCurrent(idx);
+ }
+ }
+
+ if (d->flicked && d->correctFlick && !d->inFlickCorrection) {
+ d->inFlickCorrection = true;
+ // Near an end and it seems that the extent has changed?
+ // Recalculate the flick so that we don't end up in an odd position.
+ if (yflick()) {
+ if (d->velocityY > 0) {
+ const qreal minY = minYExtent();
+ if ((minY - d->_moveY.value() < height()/2 || d->flickTargetY - d->_moveY.value() < height()/2)
+ && minY != d->flickTargetY)
+ d->flickY(-d->verticalVelocity.value());
+ d->bufferMode = QmlGraphicsListViewPrivate::BufferBefore;
+ } else if (d->velocityY < 0) {
+ const qreal maxY = maxYExtent();
+ if ((d->_moveY.value() - maxY < height()/2 || d->_moveY.value() - d->flickTargetY < height()/2)
+ && maxY != d->flickTargetY)
+ d->flickY(-d->verticalVelocity.value());
+ d->bufferMode = QmlGraphicsListViewPrivate::BufferAfter;
+ }
+ }
+
+ if (xflick()) {
+ if (d->velocityX > 0) {
+ const qreal minX = minXExtent();
+ if ((minX - d->_moveX.value() < height()/2 || d->flickTargetX - d->_moveX.value() < height()/2)
+ && minX != d->flickTargetX)
+ d->flickX(-d->horizontalVelocity.value());
+ d->bufferMode = QmlGraphicsListViewPrivate::BufferBefore;
+ } else if (d->velocityX < 0) {
+ const qreal maxX = maxXExtent();
+ if ((d->_moveX.value() - maxX < height()/2 || d->_moveX.value() - d->flickTargetX < height()/2)
+ && maxX != d->flickTargetX)
+ d->flickX(-d->horizontalVelocity.value());
+ d->bufferMode = QmlGraphicsListViewPrivate::BufferAfter;
+ }
+ }
+ d->inFlickCorrection = false;
+ }
+}
+
+qreal QmlGraphicsListView::minYExtent() const
+{
+ Q_D(const QmlGraphicsListView);
+ if (d->orient == QmlGraphicsListView::Horizontal)
+ return QmlGraphicsFlickable::minYExtent();
+ if (d->minExtentDirty) {
+ d->minExtent = -d->startPosition();
+ if (d->header && d->visibleItems.count())
+ d->minExtent += d->header->size();
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
+ d->minExtent += d->highlightRangeStart;
+ d->minExtentDirty = false;
+ }
+
+ return d->minExtent;
+}
+
+qreal QmlGraphicsListView::maxYExtent() const
+{
+ Q_D(const QmlGraphicsListView);
+ if (d->orient == QmlGraphicsListView::Horizontal)
+ return height();
+ if (d->maxExtentDirty) {
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
+ d->maxExtent = -(d->positionAt(count()-1) - d->highlightRangeEnd);
+ else
+ d->maxExtent = -(d->endPosition() - height() + 1);
+ if (d->footer)
+ d->maxExtent -= d->footer->size();
+ qreal minY = minYExtent();
+ if (d->maxExtent > minY)
+ d->maxExtent = minY;
+ d->maxExtentDirty = false;
+ }
+ return d->maxExtent;
+}
+
+qreal QmlGraphicsListView::minXExtent() const
+{
+ Q_D(const QmlGraphicsListView);
+ if (d->orient == QmlGraphicsListView::Vertical)
+ return QmlGraphicsFlickable::minXExtent();
+ if (d->minExtentDirty) {
+ d->minExtent = -d->startPosition();
+ if (d->header)
+ d->minExtent += d->header->size();
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
+ d->minExtent += d->highlightRangeStart;
+ d->minExtentDirty = false;
+ }
+
+ return d->minExtent;
+}
+
+qreal QmlGraphicsListView::maxXExtent() const
+{
+ Q_D(const QmlGraphicsListView);
+ if (d->orient == QmlGraphicsListView::Vertical)
+ return width();
+ if (d->maxExtentDirty) {
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
+ d->maxExtent = -(d->positionAt(count()-1) - d->highlightRangeEnd);
+ else
+ d->maxExtent = -(d->endPosition() - width() + 1);
+ if (d->footer)
+ d->maxExtent -= d->footer->size();
+ qreal minX = minXExtent();
+ if (d->maxExtent > minX)
+ d->maxExtent = minX;
+ d->maxExtentDirty = false;
+ }
+
+ return d->maxExtent;
+}
+
+void QmlGraphicsListView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsListView);
+ QmlGraphicsFlickable::keyPressEvent(event);
+ if (event->isAccepted())
+ return;
+
+ if (d->model && d->model->count() && d->interactive) {
+ if ((d->orient == QmlGraphicsListView::Horizontal && event->key() == Qt::Key_Left)
+ || (d->orient == QmlGraphicsListView::Vertical && event->key() == Qt::Key_Up)) {
+ if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
+ decrementCurrentIndex();
+ event->accept();
+ return;
+ } else if (d->wrap) {
+ event->accept();
+ return;
+ }
+ } else if ((d->orient == QmlGraphicsListView::Horizontal && event->key() == Qt::Key_Right)
+ || (d->orient == QmlGraphicsListView::Vertical && event->key() == Qt::Key_Down)) {
+ if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
+ incrementCurrentIndex();
+ event->accept();
+ return;
+ } else if (d->wrap) {
+ event->accept();
+ return;
+ }
+ }
+ }
+ event->ignore();
+}
+
+/*!
+ \qmlmethod ListView::incrementCurrentIndex()
+
+ Increments the current index. The current index will wrap
+ if keyNavigationWraps is true and it is currently at the end.
+*/
+void QmlGraphicsListView::incrementCurrentIndex()
+{
+ Q_D(QmlGraphicsListView);
+ if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ d->moveReason = QmlGraphicsListViewPrivate::SetIndex;
+ int index = currentIndex()+1;
+ cancelFlick();
+ d->updateCurrent(index < d->model->count() ? index : 0);
+ }
+}
+
+/*!
+ \qmlmethod ListView::decrementCurrentIndex()
+
+ Decrements the current index. The current index will wrap
+ if keyNavigationWraps is true and it is currently at the beginning.
+*/
+void QmlGraphicsListView::decrementCurrentIndex()
+{
+ Q_D(QmlGraphicsListView);
+ if (currentIndex() > 0 || d->wrap) {
+ d->moveReason = QmlGraphicsListViewPrivate::SetIndex;
+ int index = currentIndex()-1;
+ cancelFlick();
+ d->updateCurrent(index >= 0 ? index : d->model->count()-1);
+ }
+}
+
+/*!
+ \qmlmethod ListView::positionViewAtIndex(int index)
+
+ Positions the view such that the \a index is at the top (or left for horizontal orientation) of the view.
+ If positioning the view at the index would cause empty space to be displayed at
+ the end of the view, the view will be positioned at the end.
+*/
+void QmlGraphicsListView::positionViewAtIndex(int index)
+{
+ Q_D(QmlGraphicsListView);
+ if (!d->isValid() || index < 0 || index >= d->model->count())
+ return;
+
+ qreal maxExtent = d->orient == QmlGraphicsListView::Vertical ? -maxYExtent() : -maxXExtent();
+ FxListItem *item = d->visibleItem(index);
+ if (item) {
+ // Already created - just move to top of view
+ int pos = qMin(item->position(), maxExtent);
+ d->setPosition(pos);
+ } else {
+ int pos = d->positionAt(index);
+ // save the currently visible items in case any of them end up visible again
+ QList<FxListItem*> oldVisible = d->visibleItems;
+ d->visibleItems.clear();
+ d->visiblePos = pos;
+ d->visibleIndex = index;
+ d->setPosition(pos);
+ // setPosition() will cause refill. Adjust if we have moved beyond range.
+ if (d->position() > maxExtent)
+ d->setPosition(maxExtent);
+ // now release the reference to all the old visible items.
+ for (int i = 0; i < oldVisible.count(); ++i)
+ d->releaseItem(oldVisible.at(i));
+ }
+}
+
+
+void QmlGraphicsListView::componentComplete()
+{
+ Q_D(QmlGraphicsListView);
+ QmlGraphicsFlickable::componentComplete();
+ refill();
+ d->moveReason = QmlGraphicsListViewPrivate::SetIndex;
+ if (d->currentIndex < 0)
+ d->updateCurrent(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ d->fixupPosition();
+}
+
+void QmlGraphicsListView::refill()
+{
+ Q_D(QmlGraphicsListView);
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+void QmlGraphicsListView::trackedPositionChanged()
+{
+ Q_D(QmlGraphicsListView);
+ if (!d->trackedItem || !d->currentItem)
+ return;
+ if (!isFlicking() && !d->moving && d->moveReason == QmlGraphicsListViewPrivate::SetIndex) {
+ const qreal trackedPos = d->trackedItem->position();
+ const qreal viewPos = d->position();
+ if (d->haveHighlightRange) {
+ if (d->highlightRange == StrictlyEnforceRange) {
+ qreal pos = viewPos;
+ if (trackedPos > pos + d->highlightRangeEnd - d->trackedItem->size())
+ pos = trackedPos - d->highlightRangeEnd + d->trackedItem->size();
+ if (trackedPos < pos + d->highlightRangeStart)
+ pos = trackedPos - d->highlightRangeStart;
+ d->setPosition(pos);
+ } else {
+ qreal pos = viewPos;
+ if (trackedPos < d->startPosition() + d->highlightRangeStart) {
+ pos = d->startPosition();
+ } else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + d->highlightRangeEnd) {
+ pos = d->endPosition() - d->size();
+ if (pos < d->startPosition())
+ pos = d->startPosition();
+ } else {
+ if (trackedPos < viewPos + d->highlightRangeStart) {
+ pos = trackedPos - d->highlightRangeStart;
+ } else if (trackedPos > viewPos + d->highlightRangeEnd - d->trackedItem->size()) {
+ pos = trackedPos - d->highlightRangeEnd + d->trackedItem->size();
+ }
+ }
+ d->setPosition(pos);
+ }
+ } else {
+ if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
+ d->setPosition(d->currentItem->position() < trackedPos ? trackedPos : d->currentItem->position());
+ } else if (d->trackedItem->endPosition() > viewPos + d->size()
+ && d->currentItem->endPosition() > viewPos + d->size()) {
+ qreal pos;
+ if (d->trackedItem->endPosition() < d->currentItem->endPosition()) {
+ pos = d->trackedItem->endPosition() - d->size();
+ if (d->trackedItem->size() > d->size())
+ pos = trackedPos;
+ } else {
+ pos = d->currentItem->endPosition() - d->size();
+ if (d->currentItem->size() > d->size())
+ pos = d->currentItem->position();
+ }
+ d->setPosition(pos);
+ }
+ }
+ }
+}
+
+void QmlGraphicsListView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QmlGraphicsListView);
+ d->updateUnrequestedIndexes();
+ d->moveReason = QmlGraphicsListViewPrivate::Other;
+ if (!d->visibleItems.count() || d->model->count() <= 1) {
+ d->layout();
+ d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
+ emit countChanged();
+ return;
+ }
+
+ int overlapCount = count;
+ if (!d->mapRangeFromModel(modelIndex, overlapCount)) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ // Special case of appending an item to the model.
+ modelIndex = d->visibleIndex + d->visibleItems.count();
+ } else {
+ if (modelIndex < d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxListItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem->index >= modelIndex)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+ }
+
+ // At least some of the added items will be visible
+
+ int index = modelIndex - d->visibleIndex;
+ // index can be the next item past the end of the visible items list (i.e. appended)
+ int pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
+ : d->visibleItems.at(index-1)->endPosition()+d->spacing+1;
+ int initialPos = pos;
+ int diff = 0;
+ QList<FxListItem*> added;
+ bool addedVisible = false;
+ FxListItem *firstVisible = d->firstVisibleItem();
+ if (firstVisible && pos < firstVisible->position()) {
+ // Insert items before the visible item.
+ int insertionIdx = index;
+ int i = 0;
+ int from = d->position() - d->buffer;
+ for (i = count-1; i >= 0 && pos > from; --i) {
+ addedVisible = true;
+ FxListItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(insertionIdx, item);
+ pos -= item->size() + d->spacing;
+ item->setPosition(pos);
+ index++;
+ }
+ if (i >= 0) {
+ // If we didn't insert all our new items - anything
+ // before the current index is not visible - remove it.
+ while (insertionIdx--) {
+ FxListItem *item = d->visibleItems.takeFirst();
+ if (item->index != -1)
+ d->visibleIndex++;
+ d->releaseItem(item);
+ }
+ } else {
+ // adjust pos of items before inserted items.
+ for (int i = insertionIdx-1; i >= 0; i--) {
+ FxListItem *listItem = d->visibleItems.at(i);
+ listItem->setPosition(listItem->position() - (initialPos - pos));
+ }
+ }
+ } else {
+ int i = 0;
+ int to = d->buffer+d->position()+d->size()-1;
+ for (i = 0; i < count && pos <= to; ++i) {
+ addedVisible = true;
+ FxListItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(pos);
+ added.append(item);
+ pos += item->size() + d->spacing;
+ ++index;
+ }
+ if (i != count) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index)
+ d->releaseItem(d->visibleItems.takeLast());
+ }
+ diff = pos - initialPos;
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->currentItem->position() + diff);
+ }
+ }
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxListItem *listItem = d->visibleItems.at(index);
+ if (d->currentItem && listItem->item != d->currentItem->item)
+ listItem->setPosition(listItem->position() + diff);
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+
+ if (addedVisible)
+ d->layout();
+ emit countChanged();
+}
+
+void QmlGraphicsListView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QmlGraphicsListView);
+ d->moveReason = QmlGraphicsListViewPrivate::Other;
+ d->updateUnrequestedIndexes();
+
+ FxListItem *firstVisible = d->firstVisibleItem();
+ int preRemovedSize = 0;
+ bool removedVisible = false;
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxListItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ removedVisible = true;
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ if (item == firstVisible)
+ firstVisible = 0;
+ if (firstVisible && item->position() < firstVisible->position())
+ preRemovedSize += item->size();
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ if (firstVisible && d->visibleItems.first() != firstVisible)
+ d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + preRemovedSize);
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->currentItem->attached->setIsCurrentItem(false);
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (removedVisible) {
+ if (d->visibleItems.isEmpty()) {
+ d->visibleIndex = 0;
+ d->visiblePos = d->header ? d->header->size() : 0;
+ d->timeline.clear();
+ d->setPosition(0);
+ if (d->model->count() == 0)
+ update();
+ else
+ refill();
+ } else {
+ // Correct the positioning of the items
+ d->layout();
+ }
+ }
+
+ emit countChanged();
+}
+
+void QmlGraphicsListView::destroyRemoved()
+{
+ Q_D(QmlGraphicsListView);
+ for (QList<FxListItem*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxListItem *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->layout();
+}
+
+void QmlGraphicsListView::itemsMoved(int from, int to, int count)
+{
+ Q_D(QmlGraphicsListView);
+ d->updateUnrequestedIndexes();
+
+ if (d->visibleItems.isEmpty()) {
+ refill();
+ return;
+ }
+
+ d->moveReason = QmlGraphicsListViewPrivate::Other;
+ FxListItem *firstVisible = d->firstVisibleItem();
+ qreal firstItemPos = firstVisible->position();
+ QHash<int,FxListItem*> moved;
+ int moveBy = 0;
+
+ QList<FxListItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem *item = *it;
+ if (item->index >= from && item->index < from + count) {
+ // take the items that are moving
+ item->index += (to-from);
+ moved.insert(item->index, item);
+ if (item->position() < firstItemPos)
+ moveBy += item->size();
+ it = d->visibleItems.erase(it);
+ } else {
+ // move everything after the moved items.
+ if (item->index > from && item->index != -1)
+ item->index -= count;
+ ++it;
+ }
+ }
+
+ int remaining = count;
+ int endIndex = d->visibleIndex;
+ it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem *item = *it;
+ if (remaining && item->index >= to && item->index < to + count) {
+ // place items in the target position, reusing any existing items
+ FxListItem *movedItem = moved.take(item->index);
+ if (!movedItem)
+ movedItem = d->createItem(item->index);
+ if (item->index <= firstVisible->index)
+ moveBy -= movedItem->size();
+ it = d->visibleItems.insert(it, movedItem);
+ ++it;
+ --remaining;
+ } else {
+ if (item->index != -1) {
+ if (item->index >= to) {
+ // update everything after the moved items.
+ item->index += count;
+ }
+ endIndex = item->index;
+ }
+ ++it;
+ }
+ }
+
+ // If we have moved items to the end of the visible items
+ // then add any existing moved items that we have
+ while (FxListItem *item = moved.take(endIndex+1)) {
+ d->visibleItems.append(item);
+ ++endIndex;
+ }
+
+ // Whatever moved items remain are no longer visible items.
+ while (moved.count())
+ d->releaseItem(moved.take(moved.begin().key()));
+
+ // Ensure we don't cause an ugly list scroll.
+ d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy);
+
+ d->layout();
+}
+
+void QmlGraphicsListView::createdItem(int index, QmlGraphicsItem *item)
+{
+ Q_D(QmlGraphicsListView);
+ if (d->requestedIndex != index) {
+ item->setParentItem(viewport());
+ d->unrequestedItems.insert(item, index);
+ if (d->orient == QmlGraphicsListView::Vertical)
+ item->setY(d->positionAt(index));
+ else
+ item->setX(d->positionAt(index));
+ }
+}
+
+void QmlGraphicsListView::destroyingItem(QmlGraphicsItem *item)
+{
+ Q_D(QmlGraphicsListView);
+ d->unrequestedItems.remove(item);
+}
+
+void QmlGraphicsListView::animStopped()
+{
+ Q_D(QmlGraphicsListView);
+ d->moveReason = QmlGraphicsListViewPrivate::Other;
+ d->bufferMode = QmlGraphicsListViewPrivate::NoBuffer;
+}
+
+QmlGraphicsListViewAttached *QmlGraphicsListView::qmlAttachedProperties(QObject *obj)
+{
+ return new QmlGraphicsListViewAttached(obj);
+}
+
+QML_DEFINE_TYPE(Qt,4,6,ListView,QmlGraphicsListView)
+QML_DEFINE_TYPE(Qt,4,6,ViewSection,QmlGraphicsViewSection)
+
+QT_END_NAMESPACE
+
+#include <qmlgraphicslistview.moc>
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview_p.h b/src/declarative/graphicsitems/qmlgraphicslistview_p.h
new file mode 100644
index 0000000..79d678a
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicslistview_p.h
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSLISTVIEW_H
+#define QMLGRAPHICSLISTVIEW_H
+
+#include "qmlgraphicsflickable_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsViewSection : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY changed)
+ Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY changed)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_ENUMS(SectionCriteria)
+public:
+ QmlGraphicsViewSection(QObject *parent=0) : QObject(parent), m_criteria(FullString), m_delegate(0) {}
+
+ QString property() const { return m_property; }
+ void setProperty(const QString &);
+
+ enum SectionCriteria { FullString, FirstCharacter };
+ SectionCriteria criteria() const { return m_criteria; }
+ void setCriteria(SectionCriteria);
+
+ QmlComponent *delegate() const { return m_delegate; }
+ void setDelegate(QmlComponent *delegate);
+
+ QString sectionString(const QString &value);
+
+Q_SIGNALS:
+ void changed();
+ void delegateChanged();
+
+private:
+ QString m_property;
+ SectionCriteria m_criteria;
+ QmlComponent *m_delegate;
+};
+
+
+class QmlGraphicsVisualModel;
+class QmlGraphicsListViewAttached;
+class QmlGraphicsListViewPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsListView : public QmlGraphicsFlickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsListView)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QmlGraphicsItem *currentItem READ currentItem NOTIFY currentIndexChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+ Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight)
+ Q_PROPERTY(QmlGraphicsItem *highlightItem READ highlightItem NOTIFY highlightChanged)
+ Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem)
+ Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged)
+ Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged)
+
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode)
+
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+ Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer)
+ Q_PROPERTY(QmlGraphicsViewSection *section READ sectionCriteria CONSTANT)
+ Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
+
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode)
+
+ Q_PROPERTY(QmlComponent *header READ header WRITE setHeader)
+ Q_PROPERTY(QmlComponent *footer READ footer WRITE setFooter)
+
+ Q_ENUMS(HighlightRangeMode)
+ Q_ENUMS(Orientation)
+ Q_ENUMS(SnapMode)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ QmlGraphicsListView(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsListView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QmlGraphicsItem *currentItem();
+ QmlGraphicsItem *highlightItem();
+ int count() const;
+
+ QmlComponent *highlight() const;
+ void setHighlight(QmlComponent *highlight);
+
+ bool highlightFollowsCurrentItem() const;
+ void setHighlightFollowsCurrentItem(bool);
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
+
+ qreal spacing() const;
+ void setSpacing(qreal spacing);
+
+ enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
+ Orientation orientation() const;
+ void setOrientation(Orientation);
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ QmlGraphicsViewSection *sectionCriteria();
+ QString currentSection() const;
+
+ qreal highlightMoveSpeed() const;
+ void setHighlightMoveSpeed(qreal);
+
+ qreal highlightResizeSpeed() const;
+ void setHighlightResizeSpeed(qreal);
+
+ enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
+ QmlComponent *footer() const;
+ void setFooter(QmlComponent *);
+
+ QmlComponent *header() const;
+ void setHeader(QmlComponent *);
+
+ static QmlGraphicsListViewAttached *qmlAttachedProperties(QObject *);
+
+public Q_SLOTS:
+ void incrementCurrentIndex();
+ void decrementCurrentIndex();
+ void positionViewAtIndex(int index);
+
+Q_SIGNALS:
+ void countChanged();
+ void spacingChanged();
+ void orientationChanged();
+ void currentIndexChanged();
+ void currentSectionChanged();
+ void highlightMoveSpeedChanged();
+ void highlightResizeSpeedChanged();
+ void highlightChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void refill();
+ void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void destroyRemoved();
+ void createdItem(int index, QmlGraphicsItem *item);
+ void destroyingItem(QmlGraphicsItem *item);
+ void animStopped();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPEINFO(QmlGraphicsListView, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QmlGraphicsListView)
+QML_DECLARE_TYPE(QmlGraphicsViewSection)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsloader.cpp b/src/declarative/graphicsitems/qmlgraphicsloader.cpp
new file mode 100644
index 0000000..b3486ef
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsloader.cpp
@@ -0,0 +1,488 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsloader_p_p.h"
+
+#include <qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlGraphicsLoaderPrivate::QmlGraphicsLoaderPrivate()
+ : item(0), component(0), ownComponent(false)
+ , resizeMode(QmlGraphicsLoader::SizeLoaderToItem)
+{
+}
+
+QmlGraphicsLoaderPrivate::~QmlGraphicsLoaderPrivate()
+{
+}
+
+void QmlGraphicsLoaderPrivate::itemGeometryChanged(QmlGraphicsItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ if (resizeItem == item && resizeMode == QmlGraphicsLoader::SizeLoaderToItem) {
+ _q_updateSize();
+ }
+ QmlGraphicsItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
+}
+
+void QmlGraphicsLoaderPrivate::clear()
+{
+ if (ownComponent) {
+ delete component;
+ component = 0;
+ ownComponent = false;
+ }
+ source = QUrl();
+
+ if (item) {
+ if (QmlGraphicsItem *qmlItem = qobject_cast<QmlGraphicsItem*>(item)) {
+ if (resizeMode == QmlGraphicsLoader::SizeLoaderToItem) {
+ QmlGraphicsItemPrivate *p =
+ static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
+ p->removeItemChangeListener(this, QmlGraphicsItemPrivate::Geometry);
+ }
+ }
+
+ // We can't delete immediately because our item may have triggered
+ // the Loader to load a different item.
+ item->setVisible(false);
+ item->setParentItem(0);
+ item->deleteLater();
+ item = 0;
+ }
+}
+
+void QmlGraphicsLoaderPrivate::initResize()
+{
+ Q_Q(QmlGraphicsLoader);
+ if (QmlGraphicsItem *qmlItem = qobject_cast<QmlGraphicsItem*>(item)) {
+ if (resizeMode == QmlGraphicsLoader::SizeLoaderToItem) {
+ QmlGraphicsItemPrivate *p =
+ static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
+ p->addItemChangeListener(this, QmlGraphicsItemPrivate::Geometry);
+ }
+ } else if (item && item->isWidget()) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(item);
+ if (resizeMode == QmlGraphicsLoader::SizeLoaderToItem) {
+ widget->installEventFilter(q);
+ }
+ }
+ _q_updateSize();
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Loader,QmlGraphicsLoader)
+
+/*!
+ \qmlclass Loader QmlGraphicsLoader
+ \inherits Item
+
+ \brief The Loader item allows dynamically loading an Item-based
+ subtree from a QML URL or Component.
+
+ Loader instantiates an item from a component. The component to
+ instantiate may be specified directly by the \c sourceComponent
+ property, or loaded from a URL via the \c source property.
+
+ It is also an effective means of delaying the creation of a component
+ until it is required:
+ \code
+ Loader { id: pageLoader }
+ Rectangle {
+ MouseRegion { anchors.fill: parent; onClicked: pageLoader.source = "Page1.qml" }
+ }
+ \endcode
+
+ If the Loader source is changed, any previous items instantiated
+ will be destroyed. Setting \c source to an empty string
+ will destroy the currently instantiated items, freeing resources
+ and leaving the Loader empty. For example:
+
+ \code
+ pageLoader.source = ""
+ \endcode
+
+ unloads "Page1.qml" and frees resources consumed by it.
+
+ \sa {dynamic-object-creation}{Dynamic Object Creation}
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsLoader
+ \qmlclass Loader
+ */
+
+/*!
+ Create a new QmlGraphicsLoader instance.
+ */
+QmlGraphicsLoader::QmlGraphicsLoader(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsLoaderPrivate), parent)
+{
+}
+
+/*!
+ Destroy the loader instance.
+ */
+QmlGraphicsLoader::~QmlGraphicsLoader()
+{
+}
+
+/*!
+ \qmlproperty url Loader::source
+ This property holds the URL of the QML component to
+ instantiate.
+
+ \sa sourceComponent, status, progress
+*/
+QUrl QmlGraphicsLoader::source() const
+{
+ Q_D(const QmlGraphicsLoader);
+ return d->source;
+}
+
+void QmlGraphicsLoader::setSource(const QUrl &url)
+{
+ Q_D(QmlGraphicsLoader);
+ if (d->source == url)
+ return;
+
+ d->clear();
+
+ d->source = url;
+ if (d->source.isEmpty()) {
+ emit sourceChanged();
+ emit statusChanged();
+ emit progressChanged();
+ emit itemChanged();
+ return;
+ }
+
+ d->component = new QmlComponent(qmlEngine(this), d->source, this);
+ d->ownComponent = true;
+ if (!d->component->isLoading()) {
+ d->_q_sourceLoaded();
+ } else {
+ connect(d->component, SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(_q_sourceLoaded()));
+ connect(d->component, SIGNAL(progressChanged(qreal)),
+ this, SIGNAL(progressChanged()));
+ emit statusChanged();
+ emit progressChanged();
+ emit sourceChanged();
+ emit itemChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component Loader::sourceComponent
+ The sourceComponent property holds the \l{Component} to instantiate.
+
+ \qml
+ Item {
+ Component {
+ id: redSquare
+ Rectangle { color: "red"; width: 10; height: 10 }
+ }
+
+ Loader { sourceComponent: redSquare }
+ Loader { sourceComponent: redSquare; x: 10 }
+ }
+ \endqml
+
+ \sa source, progress
+*/
+
+QmlComponent *QmlGraphicsLoader::sourceComponent() const
+{
+ Q_D(const QmlGraphicsLoader);
+ return d->component;
+}
+
+void QmlGraphicsLoader::setSourceComponent(QmlComponent *comp)
+{
+ Q_D(QmlGraphicsLoader);
+ if (comp == d->component)
+ return;
+
+ d->clear();
+
+ d->component = comp;
+ d->ownComponent = false;
+ if (!d->component) {
+ emit sourceChanged();
+ emit statusChanged();
+ emit progressChanged();
+ emit itemChanged();
+ return;
+ }
+
+ if (!d->component->isLoading()) {
+ d->_q_sourceLoaded();
+ } else {
+ connect(d->component, SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(_q_sourceLoaded()));
+ connect(d->component, SIGNAL(progressChanged(qreal)),
+ this, SIGNAL(progressChanged()));
+ emit progressChanged();
+ emit sourceChanged();
+ emit statusChanged();
+ emit itemChanged();
+ }
+}
+
+void QmlGraphicsLoaderPrivate::_q_sourceLoaded()
+{
+ Q_Q(QmlGraphicsLoader);
+
+ if (component) {
+ QmlContext *ctxt = new QmlContext(qmlContext(q));
+ ctxt->addDefaultObject(q);
+
+ if (!component->errors().isEmpty()) {
+ qWarning() << component->errors();
+ emit q->sourceChanged();
+ emit q->statusChanged();
+ emit q->progressChanged();
+ return;
+ }
+
+ QObject *obj = component->create(ctxt);
+ if (obj) {
+ ctxt->setParent(obj);
+ item = qobject_cast<QGraphicsObject *>(obj);
+ if (item) {
+ if (QmlGraphicsItem* qmlItem = qobject_cast<QmlGraphicsItem *>(item)) {
+ qmlItem->setParentItem(q);
+ } else {
+ item->setParentItem(q);
+ item->setParent(q);
+ }
+// item->setFocus(true);
+ initResize();
+ }
+ } else {
+ delete obj;
+ delete ctxt;
+ source = QUrl();
+ }
+ emit q->sourceChanged();
+ emit q->statusChanged();
+ emit q->progressChanged();
+ emit q->itemChanged();
+ }
+}
+
+/*!
+ \qmlproperty enum Loader::status
+
+ This property holds the status of QML loading. It can be one of:
+ \list
+ \o Null - no QML source has been set
+ \o Ready - the QML source has been loaded
+ \o Loading - the QML source is currently being loaded
+ \o Error - an error occurred while loading the QML source
+ \endlist
+
+ \sa progress
+*/
+
+QmlGraphicsLoader::Status QmlGraphicsLoader::status() const
+{
+ Q_D(const QmlGraphicsLoader);
+
+ if (d->component)
+ return static_cast<QmlGraphicsLoader::Status>(d->component->status());
+
+ if (d->item)
+ return Ready;
+
+ return d->source.isEmpty() ? Null : Error;
+}
+
+/*!
+ \qmlproperty real Loader::progress
+
+ This property holds the progress of QML data loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+qreal QmlGraphicsLoader::progress() const
+{
+ Q_D(const QmlGraphicsLoader);
+
+ if (d->item)
+ return 1.0;
+
+ if (d->component)
+ return d->component->progress();
+
+ return 0.0;
+}
+
+/*!
+ \qmlproperty enum Loader::resizeMode
+
+ This property determines how the Loader or item are resized:
+ \list
+ \o NoResize - no item will be resized
+ \o SizeLoaderToItem - the Loader will be sized to the size of the item, unless the size of the Loader has been otherwise specified.
+ \o SizeItemToLoader - the item will be sized to the size of the Loader.
+ \endlist
+
+ Note that changing from SizeItemToLoader to SizeLoaderToItem
+ after the component is loaded will not return the item or Loader
+ to it's original size. This is due to the item size being adjusted
+ to the Loader size, thereby losing the original size of the item.
+ Future changes to the item's size will affect the loader, however.
+
+ The default resizeMode is SizeLoaderToItem.
+*/
+QmlGraphicsLoader::ResizeMode QmlGraphicsLoader::resizeMode() const
+{
+ Q_D(const QmlGraphicsLoader);
+ return d->resizeMode;
+}
+
+void QmlGraphicsLoader::setResizeMode(ResizeMode mode)
+{
+ Q_D(QmlGraphicsLoader);
+ if (mode == d->resizeMode)
+ return;
+
+ if (QmlGraphicsItem *qmlItem = qobject_cast<QmlGraphicsItem*>(d->item)) {
+ if (d->resizeMode == SizeLoaderToItem) {
+ QmlGraphicsItemPrivate *p =
+ static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
+ p->removeItemChangeListener(d, QmlGraphicsItemPrivate::Geometry);
+ }
+ } else if (d->item && d->item->isWidget()) {
+ if (d->resizeMode == SizeLoaderToItem)
+ d->item->removeEventFilter(this);
+ }
+
+ d->resizeMode = mode;
+ d->initResize();
+}
+
+void QmlGraphicsLoaderPrivate::_q_updateSize()
+{
+ Q_Q(QmlGraphicsLoader);
+ if (!item)
+ return;
+ if (QmlGraphicsItem *qmlItem = qobject_cast<QmlGraphicsItem*>(item)) {
+ if (resizeMode == QmlGraphicsLoader::SizeLoaderToItem) {
+ q->setWidth(qmlItem->width());
+ q->setHeight(qmlItem->height());
+ } else if (resizeMode == QmlGraphicsLoader::SizeItemToLoader) {
+ qmlItem->setWidth(q->width());
+ qmlItem->setHeight(q->height());
+ }
+ } else if (item && item->isWidget()) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(item);
+ if (resizeMode == QmlGraphicsLoader::SizeLoaderToItem) {
+ QSizeF newSize = widget->size();
+ if (newSize.isValid()) {
+ q->setWidth(newSize.width());
+ q->setHeight(newSize.height());
+ }
+ } else if (resizeMode == QmlGraphicsLoader::SizeItemToLoader) {
+ QSizeF oldSize = widget->size();
+ QSizeF newSize = oldSize;
+ if (q->heightValid())
+ newSize.setHeight(q->height());
+ if (q->widthValid())
+ newSize.setWidth(q->width());
+ if (oldSize != newSize)
+ widget->resize(newSize);
+ }
+ }
+}
+
+/*!
+ \qmlproperty Item Loader::item
+ This property holds the top-level item created from source.
+*/
+QGraphicsObject *QmlGraphicsLoader::item() const
+{
+ Q_D(const QmlGraphicsLoader);
+ return d->item;
+}
+
+void QmlGraphicsLoader::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QmlGraphicsLoader);
+ if (newGeometry != oldGeometry) {
+ if (d->resizeMode == SizeItemToLoader) {
+ d->_q_updateSize();
+ }
+ }
+ QmlGraphicsItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+QVariant QmlGraphicsLoader::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QmlGraphicsLoader);
+ if (change == ItemSceneHasChanged) {
+ if (d->item && d->item->isWidget()) {
+ if (d->resizeMode == SizeLoaderToItem) {
+ d->item->removeEventFilter(this);
+ d->item->installEventFilter(this);
+ }
+ }
+ }
+ return QmlGraphicsItem::itemChange(change, value);
+}
+
+bool QmlGraphicsLoader::eventFilter(QObject *watched, QEvent *e)
+{
+ Q_D(QmlGraphicsLoader);
+ if (watched == d->item && e->type() == QEvent::GraphicsSceneResize) {
+ if (d->item && d->item->isWidget() && d->resizeMode == SizeLoaderToItem) {
+ d->_q_updateSize();
+ }
+ }
+ return QmlGraphicsItem::eventFilter(watched, e);
+}
+
+#include <moc_qmlgraphicsloader_p.cpp>
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsloader_p.h b/src/declarative/graphicsitems/qmlgraphicsloader_p.h
new file mode 100644
index 0000000..87b6a52
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsloader_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSLOADER_H
+#define QMLGRAPHICSLOADER_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsLoaderPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsLoader : public QmlGraphicsItem
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+ Q_ENUMS(ResizeMode)
+
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QmlComponent *sourceComponent READ sourceComponent WRITE setSourceComponent NOTIFY sourceChanged)
+ Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
+ Q_PROPERTY(QGraphicsObject *item READ item NOTIFY itemChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+
+public:
+ QmlGraphicsLoader(QmlGraphicsItem *parent=0);
+ virtual ~QmlGraphicsLoader();
+
+ QUrl source() const;
+ void setSource(const QUrl &);
+
+ QmlComponent *sourceComponent() const;
+ void setSourceComponent(QmlComponent *);
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ enum ResizeMode { NoResize, SizeLoaderToItem, SizeItemToLoader };
+ ResizeMode resizeMode() const;
+ void setResizeMode(ResizeMode mode);
+
+ QGraphicsObject *item() const;
+
+Q_SIGNALS:
+ void itemChanged();
+ void sourceChanged();
+ void statusChanged();
+ void progressChanged();
+protected:
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+ bool eventFilter(QObject *watched, QEvent *e);
+private:
+ Q_DISABLE_COPY(QmlGraphicsLoader)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsLoader)
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceLoaded())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateSize())
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsLoader)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSLOADER_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsloader_p_p.h b/src/declarative/graphicsitems/qmlgraphicsloader_p_p.h
new file mode 100644
index 0000000..7f10eff
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsloader_p_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSLOADER_P_H
+#define QMLGRAPHICSLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsloader_p.h"
+
+#include "qmlgraphicsitem_p.h"
+#include "qmlgraphicsitemchangelistener_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QmlGraphicsLoaderPrivate : public QmlGraphicsItemPrivate, public QmlGraphicsItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsLoader)
+
+public:
+ QmlGraphicsLoaderPrivate();
+ ~QmlGraphicsLoaderPrivate();
+
+ void itemGeometryChanged(QmlGraphicsItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void clear();
+ void initResize();
+
+ QUrl source;
+ QGraphicsObject *item;
+ QmlComponent *component;
+ bool ownComponent : 1;
+ QmlGraphicsLoader::ResizeMode resizeMode;
+
+ void _q_sourceLoaded();
+ void _q_updateSize();
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSLOADER_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp b/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp
new file mode 100644
index 0000000..bd21e7a
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsmouseregion_p.h"
+#include "qmlgraphicsmouseregion_p_p.h"
+
+#include "qmlgraphicsevents_p_p.h"
+
+#include <QGraphicsSceneMouseEvent>
+
+QT_BEGIN_NAMESPACE
+static const int PressAndHoldDelay = 800;
+
+QML_DEFINE_TYPE(Qt,4,6,Drag,QmlGraphicsDrag)
+QmlGraphicsDrag::QmlGraphicsDrag(QObject *parent)
+: QObject(parent), _target(0), _axis(XandYAxis), _xmin(0), _xmax(0), _ymin(0), _ymax(0)
+{
+}
+
+QmlGraphicsDrag::~QmlGraphicsDrag()
+{
+}
+
+QmlGraphicsItem *QmlGraphicsDrag::target() const
+{
+ return _target;
+}
+
+void QmlGraphicsDrag::setTarget(QmlGraphicsItem *t)
+{
+ _target = t;
+}
+
+QmlGraphicsDrag::Axis QmlGraphicsDrag::axis() const
+{
+ return _axis;
+}
+
+void QmlGraphicsDrag::setAxis(QmlGraphicsDrag::Axis a)
+{
+ _axis = a;
+}
+
+qreal QmlGraphicsDrag::xmin() const
+{
+ return _xmin;
+}
+
+void QmlGraphicsDrag::setXmin(qreal m)
+{
+ _xmin = m;
+}
+
+qreal QmlGraphicsDrag::xmax() const
+{
+ return _xmax;
+}
+
+void QmlGraphicsDrag::setXmax(qreal m)
+{
+ _xmax = m;
+}
+
+qreal QmlGraphicsDrag::ymin() const
+{
+ return _ymin;
+}
+
+void QmlGraphicsDrag::setYmin(qreal m)
+{
+ _ymin = m;
+}
+
+qreal QmlGraphicsDrag::ymax() const
+{
+ return _ymax;
+}
+
+void QmlGraphicsDrag::setYmax(qreal m)
+{
+ _ymax = m;
+}
+
+QmlGraphicsMouseRegionPrivate::~QmlGraphicsMouseRegionPrivate()
+{
+ delete drag;
+}
+
+
+/*!
+ \qmlclass MouseRegion QmlGraphicsMouseRegion
+ \brief The MouseRegion item enables simple mouse handling.
+ \inherits Item
+
+ A MouseRegion is typically used in conjunction with a visible item,
+ where the MouseRegion effectively 'proxies' mouse handling for that
+ item. For example, we can put a MouseRegion in a Rectangle that changes
+ the Rectangle color to red when clicked:
+ \snippet doc/src/snippets/declarative/mouseregion.qml 0
+
+ Many MouseRegion signals pass a \l {MouseEvent}{mouse} parameter that contains
+ additional information about the mouse event, such as the position, button,
+ and any key modifiers.
+
+ Below we have the previous
+ example extended so as to give a different color when you right click.
+ \snippet doc/src/snippets/declarative/mouseregion.qml 1
+
+ For basic key handling, see the \l {Keys}{Keys attached property}.
+
+ MouseRegion is an invisible item: it is never painted.
+
+ \sa MouseEvent
+*/
+
+/*!
+ \qmlsignal MouseRegion::onEntered()
+
+ This handler is called when the mouse enters the mouse region.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onExited()
+
+ This handler is called when the mouse exists the mouse region.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPositionChanged(MouseEvent mouse)
+
+ This handler is called when the mouse position changes.
+
+ The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
+ position, and any buttons currently pressed.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onClicked(mouse)
+
+ This handler is called when there is a click. A click is defined as a press followed by a release,
+ both inside the MouseRegion (pressing, moving outside the MouseRegion, and then moving back inside and
+ releasing is also considered a click).
+
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPressed(mouse)
+
+ This handler is called when there is a press.
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position and which button was pressed.
+
+ The \e accepted property of the MouseEvent parameter determines whether this MouseRegion
+ will handle the press and all future mouse events until release. The default is to accept
+ the event and not allow other MouseRegions beneath this one to handle the event. If \e accepted
+ is set to false, no further events will be sent to this MouseRegion until the button is next
+ pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onReleased(mouse)
+
+ This handler is called when there is a release.
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPressAndHold(mouse)
+
+ This handler is called when there is a long press (currently 800ms).
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position of the press, and which button is pressed.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onDoubleClicked(mouse)
+
+ This handler is called when there is a double-click (a press followed by a release followed by a press).
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,MouseRegion,QmlGraphicsMouseRegion)
+
+/*!
+ \internal
+ \class QmlGraphicsMouseRegion
+ \brief The QmlGraphicsMouseRegion class provides a simple mouse handling abstraction for use within Qml.
+
+ \ingroup group_coreitems
+
+ All QmlGraphicsItem derived classes can do mouse handling but the QmlGraphicsMouseRegion class exposes mouse
+ handling data as properties and tracks flicking and dragging of the mouse.
+
+ A QmlGraphicsMouseRegion object can be instantiated in Qml using the tag \l MouseRegion.
+ */
+QmlGraphicsMouseRegion::QmlGraphicsMouseRegion(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsMouseRegionPrivate), parent)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ d->init();
+}
+
+QmlGraphicsMouseRegion::~QmlGraphicsMouseRegion()
+{
+}
+
+/*!
+ \qmlproperty real MouseRegion::mouseX
+ \qmlproperty real MouseRegion::mouseY
+ These properties hold the coordinates of the mouse.
+
+ If the hoverEnabled property is false then these properties will only be valid
+ while a button is pressed, and will remain valid as long as the button is held
+ even if the mouse is moved outside the region.
+
+ If hoverEnabled is true then these properties will be valid:
+ \list
+ \i when no button is pressed, but the mouse is within the MouseRegion (containsMouse is true).
+ \i if a button is pressed and held, even if it has since moved out of the region.
+ \endlist
+
+ The coordinates are relative to the MouseRegion.
+*/
+qreal QmlGraphicsMouseRegion::mouseX() const
+{
+ Q_D(const QmlGraphicsMouseRegion);
+ return d->lastPos.x();
+}
+
+qreal QmlGraphicsMouseRegion::mouseY() const
+{
+ Q_D(const QmlGraphicsMouseRegion);
+ return d->lastPos.y();
+}
+
+/*!
+ \qmlproperty bool MouseRegion::enabled
+ This property holds whether the item accepts mouse events.
+*/
+bool QmlGraphicsMouseRegion::isEnabled() const
+{
+ Q_D(const QmlGraphicsMouseRegion);
+ return d->absorb;
+}
+
+void QmlGraphicsMouseRegion::setEnabled(bool a)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (a != d->absorb) {
+ d->absorb = a;
+ emit enabledChanged();
+ }
+}
+/*!
+ \qmlproperty MouseButtons MouseRegion::pressedButtons
+ This property holds the mouse buttons currently pressed.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MidButton
+ \endlist
+
+ The code below displays "right" when the right mouse buttons is pressed:
+ \code
+ Text {
+ text: mr.pressedButtons & Qt.RightButton ? "right" : ""
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ MouseRegion {
+ id: mr
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ anchors.fill: parent
+ }
+ }
+ \endcode
+
+ \sa acceptedButtons
+*/
+Qt::MouseButtons QmlGraphicsMouseRegion::pressedButtons() const
+{
+ Q_D(const QmlGraphicsMouseRegion);
+ return d->lastButtons;
+}
+
+void QmlGraphicsMouseRegion::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ d->moved = false;
+ if (!d->absorb)
+ QmlGraphicsItem::mousePressEvent(event);
+ else {
+ d->longPress = false;
+ d->saveEvent(event);
+ if (d->drag) {
+ d->dragX = drag()->axis() & QmlGraphicsDrag::XAxis;
+ d->dragY = drag()->axis() & QmlGraphicsDrag::YAxis;
+ }
+ d->dragged = false;
+ setHovered(true);
+ d->start = event->pos();
+ d->startScene = event->scenePos();
+ // we should only start timer if pressAndHold is connected to.
+ if (d->isConnected("pressAndHold(QmlGraphicsMouseEvent*)"))
+ d->pressAndHoldTimer.start(PressAndHoldDelay, this);
+ setKeepMouseGrab(false);
+ event->setAccepted(setPressed(true));
+ }
+}
+
+void QmlGraphicsMouseRegion::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (!d->absorb) {
+ QmlGraphicsItem::mouseMoveEvent(event);
+ return;
+ }
+
+ d->saveEvent(event);
+
+ // ### we should skip this if these signals aren't used
+ // ### can GV handle this for us?
+ bool contains = boundingRect().contains(d->lastPos);
+ if (d->hovered && !contains)
+ setHovered(false);
+ else if (!d->hovered && contains)
+ setHovered(true);
+
+ if (d->drag && d->drag->target()) {
+ if (!d->moved) {
+ if (d->dragX) d->startX = drag()->target()->x();
+ if (d->dragY) d->startY = drag()->target()->y();
+ }
+
+ QPointF startLocalPos;
+ QPointF curLocalPos;
+ if (drag()->target()->parent()) {
+ startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
+ curLocalPos = drag()->target()->parentItem()->mapFromScene(event->scenePos());
+ } else {
+ startLocalPos = d->startScene;
+ curLocalPos = event->scenePos();
+ }
+
+ const int dragThreshold = QApplication::startDragDistance();
+ qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
+ qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
+ if ((d->dragX && !(dx < dragThreshold)) || (d->dragY && !(dy < dragThreshold)))
+ d->dragged = true;
+ if (!keepMouseGrab()) {
+ if ((!d->dragY && dy < dragThreshold && d->dragX && dx > dragThreshold)
+ || (!d->dragX && dx < dragThreshold && d->dragY && dy > dragThreshold)
+ || (d->dragX && d->dragY)) {
+ setKeepMouseGrab(true);
+ }
+ }
+
+ if (d->dragX) {
+ qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX;
+ if (x < drag()->xmin())
+ x = drag()->xmin();
+ else if (x > drag()->xmax())
+ x = drag()->xmax();
+ drag()->target()->setX(x);
+ }
+ if (d->dragY) {
+ qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY;
+ if (y < drag()->ymin())
+ y = drag()->ymin();
+ else if (y > drag()->ymax())
+ y = drag()->ymax();
+ drag()->target()->setY(y);
+ }
+ }
+ d->moved = true;
+ QmlGraphicsMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit positionChanged(&me);
+}
+
+
+void QmlGraphicsMouseRegion::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (!d->absorb) {
+ QmlGraphicsItem::mouseReleaseEvent(event);
+ } else {
+ d->saveEvent(event);
+ setPressed(false);
+ // If we don't accept hover, we need to reset containsMouse.
+ if (!acceptHoverEvents())
+ setHovered(false);
+ setKeepMouseGrab(false);
+ }
+}
+
+void QmlGraphicsMouseRegion::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (!d->absorb) {
+ QmlGraphicsItem::mouseDoubleClickEvent(event);
+ } else {
+ QmlGraphicsItem::mouseDoubleClickEvent(event);
+ if (event->isAccepted()) {
+ // Only deliver the event if we have accepted the press.
+ d->saveEvent(event);
+ QmlGraphicsMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
+ emit this->doubleClicked(&me);
+ }
+ }
+}
+
+void QmlGraphicsMouseRegion::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (!d->absorb)
+ QmlGraphicsItem::hoverEnterEvent(event);
+ else
+ setHovered(true);
+}
+
+void QmlGraphicsMouseRegion::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (!d->absorb) {
+ QmlGraphicsItem::hoverEnterEvent(event);
+ } else {
+ d->lastPos = event->pos();
+ QmlGraphicsMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit positionChanged(&me);
+ }
+}
+
+void QmlGraphicsMouseRegion::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (!d->absorb)
+ QmlGraphicsItem::hoverLeaveEvent(event);
+ else
+ setHovered(false);
+}
+
+bool QmlGraphicsMouseRegion::sceneEvent(QEvent *event)
+{
+ bool rv = QmlGraphicsItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse) {
+ Q_D(QmlGraphicsMouseRegion);
+ if (d->pressed) {
+ // if our mouse grab has been removed (probably by Flickable), fix our
+ // state
+ d->pressed = false;
+ setKeepMouseGrab(false);
+ emit pressedChanged();
+ //emit hoveredChanged();
+ }
+ }
+ return rv;
+}
+
+void QmlGraphicsMouseRegion::timerEvent(QTimerEvent *event)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (event->timerId() == d->pressAndHoldTimer.timerId()) {
+ d->pressAndHoldTimer.stop();
+ if (d->pressed && d->dragged == false && d->hovered == true) {
+ d->longPress = true;
+ QmlGraphicsMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit pressAndHold(&me);
+ }
+ }
+}
+
+/*!
+ \qmlproperty bool MouseRegion::hoverEnabled
+ This property holds whether hover events are handled.
+
+ By default, mouse events are only handled in response to a button event, or when a button is
+ pressed. Hover enables handling of all mouse events even when no mouse button is
+ pressed.
+
+ This property affects the containsMouse property and the onEntered, onExited and onPositionChanged signals.
+*/
+
+/*!
+ \qmlproperty bool MouseRegion::containsMouse
+ This property holds whether the mouse is currently inside the mouse region.
+
+ \warning This property is not updated if the region moves under the mouse: \e containsMouse will not change.
+ In addition, if hoverEnabled is false, containsMouse will only be valid when the mouse is pressed.
+*/
+bool QmlGraphicsMouseRegion::hovered() const
+{
+ Q_D(const QmlGraphicsMouseRegion);
+ return d->hovered;
+}
+
+/*!
+ \qmlproperty bool MouseRegion::pressed
+ This property holds whether the mouse region is currently pressed.
+*/
+bool QmlGraphicsMouseRegion::pressed() const
+{
+ Q_D(const QmlGraphicsMouseRegion);
+ return d->pressed;
+}
+
+void QmlGraphicsMouseRegion::setHovered(bool h)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (d->hovered != h) {
+ d->hovered = h;
+ emit hoveredChanged();
+ d->hovered ? emit entered() : emit exited();
+ }
+}
+
+/*!
+ \qmlproperty Qt::MouseButtons MouseRegion::acceptedButtons
+ This property holds the mouse buttons that the mouse region reacts to.
+
+ The available buttons are:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MidButton
+ \endlist
+
+ To accept more than one button the flags can be combined with the
+ "|" (or) operator:
+
+ \code
+ MouseRegion { acceptedButtons: Qt.LeftButton | Qt.RightButton }
+ \endcode
+
+ The default is to accept the Left button.
+*/
+Qt::MouseButtons QmlGraphicsMouseRegion::acceptedButtons() const
+{
+ return acceptedMouseButtons();
+}
+
+void QmlGraphicsMouseRegion::setAcceptedButtons(Qt::MouseButtons buttons)
+{
+ if (buttons != acceptedMouseButtons()) {
+ setAcceptedMouseButtons(buttons);
+ emit acceptedButtonsChanged();
+ }
+}
+
+bool QmlGraphicsMouseRegion::setPressed(bool p)
+{
+ Q_D(QmlGraphicsMouseRegion);
+ bool isclick = d->pressed == true && p == false && d->dragged == false && d->hovered == true;
+
+ if (d->pressed != p) {
+ d->pressed = p;
+ QmlGraphicsMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
+ if (d->pressed) {
+ emit positionChanged(&me);
+ emit pressed(&me);
+ } else {
+ emit released(&me);
+ if (isclick)
+ emit clicked(&me);
+ }
+
+ emit pressedChanged();
+ return me.isAccepted();
+ }
+ return false;
+}
+
+QmlGraphicsDrag *QmlGraphicsMouseRegion::drag()
+{
+ Q_D(QmlGraphicsMouseRegion);
+ if (!d->drag)
+ d->drag = new QmlGraphicsDrag;
+ return d->drag;
+}
+
+/*!
+ \qmlproperty Item MouseRegion::drag.target
+ \qmlproperty Axis MouseRegion::drag.axis
+ \qmlproperty real MouseRegion::drag.minimumX
+ \qmlproperty real MouseRegion::drag.maximumX
+ \qmlproperty real MouseRegion::drag.minimumY
+ \qmlproperty real MouseRegion::drag.maximumY
+
+ drag provides a convenient way to make an item draggable.
+
+ \list
+ \i \c target specifies the item to drag.
+ \i \c axis specifies whether dragging can be done horizontally (XAxis), vertically (YAxis), or both (XandYAxis)
+ \i the minimum and maximum properties limit how far the target can be dragged along the corresponding axes.
+ \endlist
+
+ The following example uses drag to reduce the opacity of an image as it moves to the right:
+ \snippet doc/src/snippets/declarative/drag.qml 0
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsmouseregion_p.h b/src/declarative/graphicsitems/qmlgraphicsmouseregion_p.h
new file mode 100644
index 0000000..0ddad1b
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsmouseregion_p.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSMOUSEREGION_H
+#define QMLGRAPHICSMOUSEREGION_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsDrag : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(Axis)
+ Q_PROPERTY(QmlGraphicsItem *target READ target WRITE setTarget)
+ Q_PROPERTY(Axis axis READ axis WRITE setAxis)
+ Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin)
+ Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax)
+ Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin)
+ Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax)
+ //### consider drag and drop
+
+public:
+ QmlGraphicsDrag(QObject *parent=0);
+ ~QmlGraphicsDrag();
+
+ QmlGraphicsItem *target() const;
+ void setTarget(QmlGraphicsItem *);
+
+ enum Axis { XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
+ Axis axis() const;
+ void setAxis(Axis);
+
+ qreal xmin() const;
+ void setXmin(qreal);
+ qreal xmax() const;
+ void setXmax(qreal);
+ qreal ymin() const;
+ void setYmin(qreal);
+ qreal ymax() const;
+ void setYmax(qreal);
+
+private:
+ QmlGraphicsItem *_target;
+ Axis _axis;
+ qreal _xmin;
+ qreal _xmax;
+ qreal _ymin;
+ qreal _ymax;
+ Q_DISABLE_COPY(QmlGraphicsDrag)
+};
+
+class QmlGraphicsMouseEvent;
+class QmlGraphicsMouseRegionPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsMouseRegion : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal mouseX READ mouseX NOTIFY positionChanged)
+ Q_PROPERTY(qreal mouseY READ mouseY NOTIFY positionChanged)
+ Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged)
+ Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons NOTIFY pressedChanged)
+ Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
+ Q_PROPERTY(bool hoverEnabled READ acceptHoverEvents WRITE setAcceptHoverEvents)
+ Q_PROPERTY(QmlGraphicsDrag *drag READ drag) //### add flicking to QmlGraphicsDrag or add a QmlGraphicsFlick ???
+
+public:
+ QmlGraphicsMouseRegion(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsMouseRegion();
+
+ qreal mouseX() const;
+ qreal mouseY() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ bool hovered() const;
+ bool pressed() const;
+
+ Qt::MouseButtons pressedButtons() const;
+
+ Qt::MouseButtons acceptedButtons() const;
+ void setAcceptedButtons(Qt::MouseButtons buttons);
+
+ QmlGraphicsDrag *drag();
+
+Q_SIGNALS:
+ void hoveredChanged();
+ void pressedChanged();
+ void enabledChanged();
+ void acceptedButtonsChanged();
+ void positionChanged(QmlGraphicsMouseEvent *mouse);
+
+ void pressed(QmlGraphicsMouseEvent *mouse);
+ void pressAndHold(QmlGraphicsMouseEvent *mouse);
+ void released(QmlGraphicsMouseEvent *mouse);
+ void clicked(QmlGraphicsMouseEvent *mouse);
+ void doubleClicked(QmlGraphicsMouseEvent *mouse);
+ void entered();
+ void exited();
+
+protected:
+ void setHovered(bool);
+ bool setPressed(bool);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+ bool sceneEvent(QEvent *);
+ void timerEvent(QTimerEvent *event);
+
+private:
+ void handlePress();
+ void handleRelease();
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsMouseRegion)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsMouseRegion)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsDrag)
+QML_DECLARE_TYPE(QmlGraphicsMouseRegion)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSMOUSEREGION_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsmouseregion_p_p.h b/src/declarative/graphicsitems/qmlgraphicsmouseregion_p_p.h
new file mode 100644
index 0000000..0f1b0d4
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsmouseregion_p_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSMOUSEREGION_P_H
+#define QMLGRAPHICSMOUSEREGION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem_p.h"
+
+#include <qdatetime.h>
+#include <qbasictimer.h>
+#include <qgraphicssceneevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsMouseRegionPrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsMouseRegion)
+
+public:
+ QmlGraphicsMouseRegionPrivate()
+ : absorb(true), hovered(false), pressed(false), longPress(false), drag(0)
+ {
+ }
+
+ ~QmlGraphicsMouseRegionPrivate();
+
+ void init()
+ {
+ Q_Q(QmlGraphicsMouseRegion);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ }
+
+ void saveEvent(QGraphicsSceneMouseEvent *event) {
+ lastPos = event->pos();
+ lastButton = event->button();
+ lastButtons = event->buttons();
+ lastModifiers = event->modifiers();
+ }
+
+ bool isConnected(const char *signal) {
+ Q_Q(QmlGraphicsMouseRegion);
+ int idx = QObjectPrivate::get(q)->signalIndex(signal);
+ return QObjectPrivate::get(q)->isSignalConnected(idx);
+ }
+
+ bool absorb : 1;
+ bool hovered : 1;
+ bool pressed : 1;
+ bool longPress : 1;
+ bool moved : 1;
+ bool dragX : 1;
+ bool dragY : 1;
+ bool dragged : 1;
+ QmlGraphicsDrag *drag;
+ QPointF start;
+ QPointF startScene;
+ qreal startX;
+ qreal startY;
+ QPointF lastPos;
+ Qt::MouseButton lastButton;
+ Qt::MouseButtons lastButtons;
+ Qt::KeyboardModifiers lastModifiers;
+ QBasicTimer pressAndHoldTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSMOUSEREGION_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicspainteditem.cpp b/src/declarative/graphicsitems/qmlgraphicspainteditem.cpp
new file mode 100644
index 0000000..e50e3e4
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspainteditem.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicspainteditem_p.h"
+#include "qmlgraphicspainteditem_p_p.h"
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QPainter>
+#include <QPaintEngine>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlGraphicsPaintedItem
+ \brief The QmlGraphicsPaintedItem class is an abstract base class for QmlView items that want cached painting.
+ \internal
+
+ This is a convenience class for implementing items that paint their contents
+ using a QPainter. The contents of the item are cached behind the scenes.
+ The dirtyCache() function should be called if the contents change to
+ ensure the cache is refreshed the next time painting occurs.
+
+ To subclass QmlGraphicsPaintedItem, you must reimplement drawContents() to draw
+ the contents of the item.
+*/
+
+/*!
+ \fn void QmlGraphicsPaintedItem::drawContents(QPainter *painter, const QRect &rect)
+
+ This function is called when the cache needs to be refreshed. When
+ sub-classing QmlGraphicsPaintedItem this function should be implemented so as to
+ paint the contents of the item using the given \a painter for the
+ area of the contents specified by \a rect.
+*/
+
+/*!
+ \property QmlGraphicsPaintedItem::contentsSize
+ \brief The size of the contents
+
+ The contents size is the size of the item in regards to how it is painted
+ using the drawContents() function. This is distinct from the size of the
+ item in regards to height() and width().
+*/
+
+// XXX bug in WebKit - can call repaintRequested and other cache-changing functions from within render!
+static int inpaint=0;
+static int inpaint_clearcache=0;
+
+/*!
+ Marks areas of the cache that intersect with the given \a rect as dirty and
+ in need of being refreshed.
+
+ \sa clearCache()
+*/
+void QmlGraphicsPaintedItem::dirtyCache(const QRect& rect)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ QRect srect(qCeil(rect.x()*d->contentsScale),
+ qCeil(rect.y()*d->contentsScale),
+ qCeil(rect.width()*d->contentsScale),
+ qCeil(rect.height()*d->contentsScale));
+ for (int i=0; i < d->imagecache.count(); ) {
+ QmlGraphicsPaintedItemPrivate::ImageCacheItem *c = d->imagecache[i];
+ QRect isect = (c->area & srect) | c->dirty;
+ if (isect == c->area && !inpaint) {
+ delete d->imagecache.takeAt(i);
+ } else {
+ c->dirty = isect;
+ ++i;
+ }
+ }
+}
+
+/*!
+ Marks the entirety of the contents cache as dirty.
+
+ \sa dirtyCache()
+*/
+void QmlGraphicsPaintedItem::clearCache()
+{
+ if (inpaint) {
+ inpaint_clearcache=1;
+ return;
+ }
+ Q_D(QmlGraphicsPaintedItem);
+ qDeleteAll(d->imagecache);
+ d->imagecache.clear();
+}
+
+/*!
+ Returns the size of the contents.
+
+ \sa setContentsSize()
+*/
+QSize QmlGraphicsPaintedItem::contentsSize() const
+{
+ Q_D(const QmlGraphicsPaintedItem);
+ return d->contentsSize;
+}
+
+/*!
+ Sets the size of the contents to the given \a size.
+
+ \sa contentsSize()
+*/
+void QmlGraphicsPaintedItem::setContentsSize(const QSize &size)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ if (d->contentsSize == size) return;
+ d->contentsSize = size;
+ setImplicitWidth(size.width()*d->contentsScale);
+ setImplicitHeight(size.height()*d->contentsScale);
+ clearCache();
+ update();
+ emit contentsSizeChanged();
+}
+
+qreal QmlGraphicsPaintedItem::contentsScale() const
+{
+ Q_D(const QmlGraphicsPaintedItem);
+ return d->contentsScale;
+}
+
+void QmlGraphicsPaintedItem::setContentsScale(qreal scale)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ if (d->contentsScale == scale) return;
+ d->contentsScale = scale;
+ setImplicitWidth(d->contentsSize.width()*scale);
+ setImplicitHeight(d->contentsSize.height()*scale);
+ clearCache();
+ update();
+ emit contentsScaleChanged();
+}
+
+
+/*!
+ Constructs a new QmlGraphicsPaintedItem with the given \a parent.
+*/
+QmlGraphicsPaintedItem::QmlGraphicsPaintedItem(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsPaintedItemPrivate), parent)
+{
+ init();
+}
+
+/*!
+ \internal
+ Constructs a new QmlGraphicsPaintedItem with the given \a parent and
+ initialized private data member \a dd.
+*/
+QmlGraphicsPaintedItem::QmlGraphicsPaintedItem(QmlGraphicsPaintedItemPrivate &dd, QmlGraphicsItem *parent)
+ : QmlGraphicsItem(dd, parent)
+{
+ init();
+}
+
+/*!
+ Destroys the image item.
+*/
+QmlGraphicsPaintedItem::~QmlGraphicsPaintedItem()
+{
+ clearCache();
+}
+
+/*!
+ \internal
+*/
+void QmlGraphicsPaintedItem::init()
+{
+ connect(this,SIGNAL(widthChanged()),this,SLOT(clearCache()));
+ connect(this,SIGNAL(heightChanged()),this,SLOT(clearCache()));
+ connect(this,SIGNAL(visibleChanged()),this,SLOT(clearCache()));
+}
+
+void QmlGraphicsPaintedItem::setCacheFrozen(bool frozen)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ if (d->cachefrozen == frozen)
+ return;
+ d->cachefrozen = frozen;
+ // XXX clear cache?
+}
+
+/*!
+ \reimp
+*/
+void QmlGraphicsPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ const QRect content(0,0,qCeil(d->contentsSize.width()*d->contentsScale),
+ qCeil(d->contentsSize.height()*d->contentsScale));
+ if (content.width() <= 0 || content.height() <= 0)
+ return;
+
+ ++inpaint;
+
+ const QTransform &x = p->deviceTransform();
+ QTransform xinv = x.inverted();
+ QRegion effectiveClip;
+ QRegion sysClip = p->paintEngine()->systemClip();
+ if (xinv.type() <= QTransform::TxScale && sysClip.numRects() < 5) {
+ // simple transform, region gets no more complicated...
+ effectiveClip = xinv.map(sysClip);
+ } else {
+ // do not make complicated regions...
+ effectiveClip = xinv.mapRect(sysClip.boundingRect());
+ }
+
+ QRegion topaint = p->clipRegion();
+ if (topaint.isEmpty()) {
+ if (effectiveClip.isEmpty())
+ topaint = QRect(0,0,p->device()->width(),p->device()->height());
+ else
+ topaint = effectiveClip;
+ } else if (!effectiveClip.isEmpty()) {
+ topaint &= effectiveClip;
+ }
+
+ topaint &= content;
+ QRegion uncached(content);
+ p->setRenderHints(QPainter::SmoothPixmapTransform, d->smooth);
+
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ if (topaint.contains(area)) {
+ QRectF target(area.x(), area.y(), area.width(), area.height());
+ if (!d->cachefrozen) {
+ if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) {
+ QPainter qp(&d->imagecache[i]->image);
+ qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);
+ qp.translate(-area.x(), -area.y());
+ qp.scale(d->contentsScale,d->contentsScale);
+ QRect clip = d->imagecache[i]->dirty;
+ QRect sclip(qFloor(clip.x()/d->contentsScale),
+ qFloor(clip.y()/d->contentsScale),
+ qCeil(clip.width()/d->contentsScale+clip.x()/d->contentsScale-qFloor(clip.x()/d->contentsScale)),
+ qCeil(clip.height()/d->contentsScale+clip.y()/d->contentsScale-qFloor(clip.y()/d->contentsScale)));
+ qp.setClipRect(sclip);
+ if (d->fillColor.isValid()){
+ if(d->fillColor.alpha() < 255){
+ // ### Might not work outside of raster paintengine
+ QPainter::CompositionMode prev = qp.compositionMode();
+ qp.setCompositionMode(QPainter::CompositionMode_Source);
+ qp.fillRect(sclip,d->fillColor);
+ qp.setCompositionMode(prev);
+ }else{
+ qp.fillRect(sclip,d->fillColor);
+ }
+ }
+ drawContents(&qp, sclip);
+ d->imagecache[i]->dirty = QRect();
+ }
+ }
+ p->drawPixmap(target.toRect(), d->imagecache[i]->image);
+ topaint -= area;
+ d->imagecache[i]->age=0;
+ } else {
+ d->imagecache[i]->age++;
+ }
+ cachesize += area.width()*area.height();
+ uncached -= area;
+ }
+
+ if (!topaint.isEmpty()) {
+ if (!d->cachefrozen) {
+ // Find a sensible larger area, otherwise will paint lots of tiny images.
+ QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
+ cachesize += biggerrect.width() * biggerrect.height();
+ while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ uncached += d->imagecache[oldest]->area;
+ delete d->imagecache.takeAt(oldest);
+ }
+ const QRegion bigger = QRegion(biggerrect) & uncached;
+ const QVector<QRect> rects = bigger.rects();
+ for (int i = 0; i < rects.count(); ++i) {
+ const QRect &r = rects.at(i);
+ QPixmap img(r.size());
+ if (d->fillColor.isValid())
+ img.fill(d->fillColor);
+ {
+ QPainter qp(&img);
+ qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);
+
+ qp.translate(-r.x(),-r.y());
+ qp.scale(d->contentsScale,d->contentsScale);
+ QRect sclip(qFloor(r.x()/d->contentsScale),
+ qFloor(r.y()/d->contentsScale),
+ qCeil(r.width()/d->contentsScale+r.x()/d->contentsScale-qFloor(r.x()/d->contentsScale)),
+ qCeil(r.height()/d->contentsScale+r.y()/d->contentsScale-qFloor(r.y()/d->contentsScale)));
+ drawContents(&qp, sclip);
+ }
+ QmlGraphicsPaintedItemPrivate::ImageCacheItem *newitem = new QmlGraphicsPaintedItemPrivate::ImageCacheItem;
+ newitem->area = r;
+ newitem->image = img;
+ d->imagecache.append(newitem);
+ p->drawPixmap(r, newitem->image);
+ }
+ } else {
+ const QVector<QRect> rects = uncached.rects();
+ for (int i = 0; i < rects.count(); ++i)
+ p->fillRect(rects.at(i), Qt::lightGray);
+ }
+ }
+
+ if (inpaint_clearcache) {
+ clearCache();
+ inpaint_clearcache = 0;
+ }
+
+ --inpaint;
+}
+
+/*!
+ \qmlproperty int PaintedItem::pixelCacheSize
+
+ This property holds the maximum number of pixels of image cache to
+ allow. The default is 0.1 megapixels. The cache will not be larger
+ than the (unscaled) size of the WebView.
+*/
+/*!
+ \property QmlGraphicsPaintedItem::pixelCacheSize
+
+ The maximum number of pixels of image cache to allow. The default
+ is 0.1 megapixels. The cache will not be larger than the (unscaled)
+ size of the QmlGraphicsPaintedItem.
+*/
+int QmlGraphicsPaintedItem::pixelCacheSize() const
+{
+ Q_D(const QmlGraphicsPaintedItem);
+ return d->max_imagecache_size;
+}
+
+void QmlGraphicsPaintedItem::setPixelCacheSize(int pixels)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ if (pixels < d->max_imagecache_size) {
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ cachesize += area.width()*area.height();
+ }
+ while (d->imagecache.count() && cachesize > pixels) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ delete d->imagecache.takeAt(oldest);
+ }
+ }
+ d->max_imagecache_size = pixels;
+}
+
+
+
+/*!
+ \property QmlGraphicsPaintedItem::fillColor
+
+ The color to be used to fill the item prior to calling drawContents().
+ By default, this is Qt::transparent.
+
+ Performance improvements can be achieved if subclasses call this with either an
+ invalid color (QColor()), or an appropriate solid color.
+*/
+void QmlGraphicsPaintedItem::setFillColor(const QColor& c)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ if (d->fillColor == c)
+ return;
+ d->fillColor = c;
+ emit fillColorChanged();
+ update();
+}
+
+QColor QmlGraphicsPaintedItem::fillColor() const
+{
+ Q_D(const QmlGraphicsPaintedItem);
+ return d->fillColor;
+}
+
+/*!
+ \qmlproperty bool PaintedItem::smoothCache
+
+ Controls whether the cached tiles of which the item is composed are
+ rendered smoothly when they are generated.
+
+ This is in addition toe Item::smooth, which controls the smooth painting of
+ the already-painted cached tiles under transformation.
+*/
+bool QmlGraphicsPaintedItem::smoothCache() const
+{
+ Q_D(const QmlGraphicsPaintedItem);
+ return d->smoothCache;
+}
+
+void QmlGraphicsPaintedItem::setSmoothCache(bool on)
+{
+ Q_D(QmlGraphicsPaintedItem);
+ if (d->smoothCache != on) {
+ d->smoothCache = on;
+ clearCache();
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicspainteditem_p.h b/src/declarative/graphicsitems/qmlgraphicspainteditem_p.h
new file mode 100644
index 0000000..ab21f36
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspainteditem_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSIMAGEITEM_H
+#define QMLGRAPHICSIMAGEITEM_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsPaintedItemPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsPaintedItem : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged)
+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
+ Q_PROPERTY(int pixelCacheSize READ pixelCacheSize WRITE setPixelCacheSize)
+ Q_PROPERTY(bool smoothCache READ smoothCache WRITE setSmoothCache)
+ Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged)
+
+
+public:
+ QmlGraphicsPaintedItem(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsPaintedItem();
+
+ QSize contentsSize() const;
+ void setContentsSize(const QSize &);
+
+ qreal contentsScale() const;
+ void setContentsScale(qreal);
+
+ int pixelCacheSize() const;
+ void setPixelCacheSize(int pixels);
+
+ bool smoothCache() const;
+ void setSmoothCache(bool on);
+
+ QColor fillColor() const;
+ void setFillColor(const QColor&);
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+protected:
+ QmlGraphicsPaintedItem(QmlGraphicsPaintedItemPrivate &dd, QmlGraphicsItem *parent);
+
+ virtual void drawContents(QPainter *p, const QRect &) = 0;
+
+ void setCacheFrozen(bool);
+
+Q_SIGNALS:
+ void fillColorChanged();
+ void contentsSizeChanged();
+ void contentsScaleChanged();
+
+protected Q_SLOTS:
+ void dirtyCache(const QRect &);
+ void clearCache();
+
+private:
+ void init();
+ Q_DISABLE_COPY(QmlGraphicsPaintedItem)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsPaintedItem)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsPaintedItem)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h b/src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h
new file mode 100644
index 0000000..6bcc51a
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspainteditem_p_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSIMAGEITEM_P_H
+#define QMLGRAPHICSIMAGEITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsPaintedItemPrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsPaintedItem)
+
+public:
+ QmlGraphicsPaintedItemPrivate()
+ : max_imagecache_size(100000), contentsScale(1.0), fillColor(Qt::transparent), cachefrozen(false), smoothCache(true)
+ {
+ }
+
+ struct ImageCacheItem {
+ ImageCacheItem() : age(0) {}
+ ~ImageCacheItem() { }
+ int age;
+ QRect area;
+ QRect dirty; // one dirty area (allows optimization of common cases)
+ QPixmap image;
+ };
+
+ QList<ImageCacheItem*> imagecache;
+
+ int max_imagecache_size;
+ QSize contentsSize;
+ qreal contentsScale;
+ QColor fillColor;
+ bool cachefrozen;
+ bool smoothCache;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsparticles.cpp b/src/declarative/graphicsitems/qmlgraphicsparticles.cpp
new file mode 100644
index 0000000..8c5fb4f
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsparticles.cpp
@@ -0,0 +1,1241 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsparticles_p.h"
+
+#include "qmlgraphicsitem_p.h"
+
+#include <qmlpixmapcache_p.h>
+#include <qfxperf_p_p.h>
+#include <qmlanimation_p_p.h>
+
+#include <QNetworkReply>
+#include <QPainter>
+#include <QtGui/qdrawutil.h>
+#include <QVarLengthArray>
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#define M_PI_2 (M_PI / 2.)
+#endif
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+QT_BEGIN_NAMESPACE
+#define PI_SQR 9.8696044
+// parabolic approximation
+inline qreal fastSin(qreal theta)
+{
+ const qreal b = 4 / M_PI;
+ const qreal c = -4 / PI_SQR;
+
+ qreal y = b * theta + c * theta * qAbs(theta);
+ return y;
+}
+
+inline qreal fastCos(qreal theta)
+{
+ theta += M_PI_2;
+ if (theta > M_PI)
+ theta -= 2 * M_PI;
+
+ return fastSin(theta);
+}
+
+class QmlGraphicsParticle
+{
+public:
+ QmlGraphicsParticle(int time) : lifeSpan(1000), fadeOutAge(800)
+ , opacity(0), birthTime(time), x_velocity(0), y_velocity(0)
+ , state(FadeIn), data(0)
+ {
+ }
+
+ int lifeSpan;
+ int fadeOutAge;
+ qreal x;
+ qreal y;
+ qreal opacity;
+ int birthTime;
+ qreal x_velocity;
+ qreal y_velocity;
+ enum State { FadeIn, Solid, FadeOut };
+ State state;
+ void *data;
+};
+
+//---------------------------------------------------------------------------
+
+QML_DEFINE_TYPE(Qt,4,6,ParticleMotion,QmlGraphicsParticleMotion)
+
+/*!
+ \class QmlGraphicsParticleMotion
+ \ingroup group_effects
+ \brief The QmlGraphicsParticleMotion class is the base class for particle motion.
+ \internal
+
+ This class causes the particles to remain static.
+*/
+
+/*!
+ Constructs a QmlGraphicsParticleMotion with parent object \a parent.
+*/
+QmlGraphicsParticleMotion::QmlGraphicsParticleMotion(QObject *parent) :
+ QObject(parent)
+{
+}
+
+/*!
+ Move the \a particle to its new position. \a interval is the number of
+ milliseconds elapsed since it was last moved.
+*/
+void QmlGraphicsParticleMotion::advance(QmlGraphicsParticle &particle, int interval)
+{
+ Q_UNUSED(particle);
+ Q_UNUSED(interval);
+}
+
+/*!
+ The \a particle has just been created. Some motion strategies require
+ additional state information. This can be allocated by this function.
+*/
+void QmlGraphicsParticleMotion::created(QmlGraphicsParticle &particle)
+{
+ Q_UNUSED(particle);
+}
+
+/*!
+ The \a particle is about to be destroyed. Any additional memory
+ that has been allocated for the particle should be freed.
+*/
+void QmlGraphicsParticleMotion::destroy(QmlGraphicsParticle &particle)
+{
+ Q_UNUSED(particle);
+}
+
+/*!
+ \qmlclass ParticleMotionLinear
+ \brief The ParticleMotionLinear object moves particles linearly.
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsParticleMotionLinear
+ \ingroup group_effects
+ \brief The QmlGraphicsParticleMotionLinear class moves the particles linearly.
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,ParticleMotionLinear,QmlGraphicsParticleMotionLinear)
+
+void QmlGraphicsParticleMotionLinear::advance(QmlGraphicsParticle &p, int interval)
+{
+ p.x += interval * p.x_velocity;
+ p.y += interval * p.y_velocity;
+}
+
+/*!
+ \qmlclass ParticleMotionGravity
+ \brief The ParticleMotionGravity object moves particles towards a point.
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsParticleMotionGravity
+ \ingroup group_effects
+ \brief The QmlGraphicsParticleMotionGravity class moves the particles towards a point.
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,ParticleMotionGravity,QmlGraphicsParticleMotionGravity)
+
+/*!
+ \qmlproperty int ParticleMotionGravity::xattractor
+ \qmlproperty int ParticleMotionGravity::yattractor
+ These properties hold the x and y coordinates of the point attracting the particles.
+*/
+
+/*!
+ \qmlproperty int ParticleMotionGravity::acceleration
+ This property holds the acceleration to apply to the particles.
+*/
+
+/*!
+ \property QmlGraphicsParticleMotionGravity::xattractor
+ \brief the x coordinate of the point attracting the particles.
+*/
+
+/*!
+ \property QmlGraphicsParticleMotionGravity::yattractor
+ \brief the y coordinate of the point attracting the particles.
+*/
+
+/*!
+ \property QmlGraphicsParticleMotionGravity::acceleration
+ \brief the acceleration to apply to the particles.
+*/
+
+void QmlGraphicsParticleMotionGravity::advance(QmlGraphicsParticle &p, int interval)
+{
+ qreal xdiff = p.x - _xAttr;
+ qreal ydiff = p.y - _yAttr;
+
+ qreal xcomp = xdiff / (xdiff + ydiff);
+ qreal ycomp = ydiff / (xdiff + ydiff);
+
+ p.x_velocity += xcomp * _accel * interval;
+ p.y_velocity += ycomp * _accel * interval;
+
+ p.x += interval * p.x_velocity;
+ p.y += interval * p.y_velocity;
+}
+
+/*!
+ \qmlclass ParticleMotionWander
+ \brief The ParticleMotionWander object moves particles in a somewhat random fashion.
+
+ The particles will continue roughly in the original direction, however will randomly
+ drift to each side.
+
+ The code below produces an effect similar to falling snow.
+
+ \qml
+Rectangle {
+ width: 240
+ height: 320
+ color: "black"
+
+ Particles {
+ y: 0
+ width: parent.width
+ height: 30
+ source: "star.png"
+ lifeSpan: 5000
+ count: 50
+ angle: 70
+ angleDeviation: 36
+ velocity: 30
+ velocityDeviation: 10
+ ParticleMotionWander {
+ xvariance: 30
+ pace: 100
+ }
+ }
+}
+ \endqml
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsParticleMotionWander
+ \ingroup group_effects
+ \brief The QmlGraphicsParticleMotionWander class moves particles in a somewhat random fashion.
+
+ The particles will continue roughly in the original direction, however will randomly
+ drift to each side.
+*/
+
+/*!
+ \qmlproperty int QmlGraphicsParticleMotionWander::xvariance
+ \qmlproperty int QmlGraphicsParticleMotionWander::yvariance
+
+ These properties set the amount to wander in the x and y directions.
+*/
+
+/*!
+ \qmlproperty int QmlGraphicsParticleMotionWander::pace
+ This property holds how quickly the paricles will move from side to side.
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,ParticleMotionWander,QmlGraphicsParticleMotionWander)
+
+void QmlGraphicsParticleMotionWander::advance(QmlGraphicsParticle &p, int interval)
+{
+ if (!particles)
+ particles = qobject_cast<QmlGraphicsParticles*>(parent());
+ if (particles) {
+ Data *d = (Data*)p.data;
+ if (_xvariance != 0.) {
+ qreal xdiff = p.x_velocity - d->x_targetV;
+ if ((xdiff > d->x_peak && d->x_var > 0.0) || (xdiff < -d->x_peak && d->x_var < 0.0)) {
+ d->x_var = -d->x_var;
+ d->x_peak = _xvariance + _xvariance * qreal(qrand()) / RAND_MAX;
+ }
+ p.x_velocity += d->x_var * interval;
+ }
+ p.x += interval * p.x_velocity;
+
+ if (_yvariance != 0.) {
+ qreal ydiff = p.y_velocity - d->y_targetV;
+ if ((ydiff > d->y_peak && d->y_var > 0.0) || (ydiff < -d->y_peak && d->y_var < 0.0)) {
+ d->y_var = -d->y_var;
+ d->y_peak = _yvariance + _yvariance * qreal(qrand()) / RAND_MAX;
+ }
+ p.y_velocity += d->y_var * interval;
+ }
+ p.y += interval * p.y_velocity;
+ }
+}
+
+void QmlGraphicsParticleMotionWander::created(QmlGraphicsParticle &p)
+{
+ if (!p.data) {
+ Data *d = new Data;
+ p.data = (void*)d;
+ d->x_targetV = p.x_velocity;
+ d->y_targetV = p.y_velocity;
+ d->x_peak = _xvariance;
+ d->y_peak = _yvariance;
+ d->x_var = _pace * qreal(qrand()) / RAND_MAX / 1000.0;
+ d->y_var = _pace * qreal(qrand()) / RAND_MAX / 1000.0;
+ }
+}
+
+void QmlGraphicsParticleMotionWander::destroy(QmlGraphicsParticle &p)
+{
+ if (p.data)
+ delete (Data*)p.data;
+}
+
+//---------------------------------------------------------------------------
+class QmlGraphicsParticlesPainter : public QmlGraphicsItem
+{
+public:
+ QmlGraphicsParticlesPainter(QmlGraphicsParticlesPrivate *p, QmlGraphicsItem* parent)
+ : QmlGraphicsItem(parent), d(p)
+ {
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+ maxX = minX = maxY = minY = 0;
+ }
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+ void updateSize();
+
+ qreal maxX;
+ qreal minX;
+ qreal maxY;
+ qreal minY;
+ QmlGraphicsParticlesPrivate* d;
+};
+
+//---------------------------------------------------------------------------
+class QmlGraphicsParticlesPrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsParticles)
+public:
+ QmlGraphicsParticlesPrivate()
+ : count(1), emissionRate(-1), emissionVariance(0.5), lifeSpan(1000)
+ , lifeSpanDev(1000), fadeInDur(200), fadeOutDur(300)
+ , angle(0), angleDev(0), velocity(0), velocityDev(0), emissionCarry(0.)
+ , addParticleTime(0), addParticleCount(0), lastAdvTime(0)
+ , motion(0), pendingPixmapCache(false), clock(this)
+ {
+ }
+
+ ~QmlGraphicsParticlesPrivate()
+ {
+ }
+
+ void init()
+ {
+ Q_Q(QmlGraphicsParticles);
+ paintItem = new QmlGraphicsParticlesPainter(this, q);
+ }
+
+ void tick(int time);
+ void createParticle(int time);
+ void updateOpacity(QmlGraphicsParticle &p, int age);
+
+ QUrl url;
+ QPixmap image;
+ int count;
+ int emissionRate;
+ qreal emissionVariance;
+ int lifeSpan;
+ int lifeSpanDev;
+ int fadeInDur;
+ int fadeOutDur;
+ qreal angle;
+ qreal angleDev;
+ qreal velocity;
+ qreal velocityDev;
+ qreal emissionCarry;
+ int addParticleTime;
+ int addParticleCount;
+ int lastAdvTime;
+ QmlGraphicsParticleMotion *motion;
+ QmlGraphicsParticlesPainter *paintItem;
+
+ bool pendingPixmapCache;
+
+ QList<QPair<int, int> > bursts;//countLeft, emissionRate pairs
+ QList<QmlGraphicsParticle> particles;
+ QTickAnimationProxy<QmlGraphicsParticlesPrivate, &QmlGraphicsParticlesPrivate::tick> clock;
+
+};
+
+void QmlGraphicsParticlesPrivate::tick(int time)
+{
+ Q_Q(QmlGraphicsParticles);
+ if (!motion)
+ motion = new QmlGraphicsParticleMotionLinear(q);
+
+ int oldCount = particles.count();
+ int removed = 0;
+ int interval = time - lastAdvTime;
+ for (int i = 0; i < particles.count(); ) {
+ QmlGraphicsParticle &particle = particles[i];
+ int age = time - particle.birthTime;
+ if (age >= particle.lifeSpan) {
+ QmlGraphicsParticle part = particles.takeAt(i);
+ motion->destroy(part);
+ ++removed;
+ } else {
+ updateOpacity(particle, age);
+ motion->advance(particle, interval);
+ ++i;
+ }
+ }
+
+ if(emissionRate == -1)//Otherwise leave emission to the emission rate
+ while(removed-- && ((count == -1) || particles.count() < count))
+ createParticle(time);
+
+ if (!addParticleTime)
+ addParticleTime = time;
+
+ //Possibly emit new particles
+ if (((count == -1) || particles.count() < count) && emissionRate
+ && !(count==-1 && emissionRate==-1)) {
+ int emissionCount = -1;
+ if (emissionRate != -1){
+ qreal variance = 1.;
+ if (emissionVariance > 0.){
+ variance += (qreal(qrand())/RAND_MAX) * emissionVariance * (qrand()%2?-1.:1.);
+ }
+ qreal emission = emissionRate * (qreal(interval)/1000.);
+ emission = emission * variance + emissionCarry;
+ double tmpDbl;
+ emissionCarry = modf(emission, &tmpDbl);
+ emissionCount = (int)tmpDbl;
+ emissionCount = qMax(0,emissionCount);
+ }
+ while(((count == -1) || particles.count() < count) &&
+ (emissionRate==-1 || emissionCount--))
+ createParticle(time);
+ }
+
+ //Deal with emissions from requested bursts
+ for(int i=0; i<bursts.size(); i++){
+ int emission = 0;
+ if(bursts[i].second == -1){
+ emission = bursts[i].first;
+ }else{
+ qreal variance = 1.;
+ if (emissionVariance > 0.){
+ variance += (qreal(qrand())/RAND_MAX) * emissionVariance * (qrand()%2?-1.:1.);
+ }
+ qreal workingEmission = bursts[i].second * (qreal(interval)/1000.);
+ workingEmission *= variance;
+ emission = (int)workingEmission;
+ emission = qMax(emission, 0);
+ }
+ emission = qMin(emission, bursts[i].first);
+ bursts[i].first -= emission;
+ while(emission--)
+ createParticle(time);
+ }
+ for(int i=bursts.size()-1; i>=0; i--)
+ if(bursts[i].first <= 0)
+ bursts.removeAt(i);
+
+ lastAdvTime = time;
+ paintItem->updateSize();
+ paintItem->update();
+ if (!(oldCount || particles.count()) && (!count || !emissionRate) && bursts.isEmpty()) {
+ lastAdvTime = 0;
+ clock.stop();
+ }
+}
+
+void QmlGraphicsParticlesPrivate::createParticle(int time)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::CreateParticle> x;
+#endif
+ Q_Q(QmlGraphicsParticles);
+ QmlGraphicsParticle p(time);
+ p.x = q->x() + q->width() * qreal(qrand()) / RAND_MAX - image.width()/2.0;
+ p.y = q->y() + q->height() * qreal(qrand()) / RAND_MAX - image.height()/2.0;
+ p.lifeSpan = lifeSpan;
+ if (lifeSpanDev)
+ p.lifeSpan += int(lifeSpanDev/2 - lifeSpanDev * qreal(qrand()) / RAND_MAX);
+ p.fadeOutAge = p.lifeSpan - fadeOutDur;
+ if (fadeInDur == 0.) {
+ p.state= QmlGraphicsParticle::Solid;
+ p.opacity = 1.0;
+ }
+ qreal a = angle;
+ if (angleDev)
+ a += angleDev/2 - angleDev * qreal(qrand()) / RAND_MAX;
+ if (a > M_PI)
+ a = a - 2 * M_PI;
+ qreal v = velocity;
+ if (velocityDev)
+ v += velocityDev/2 - velocityDev * qreal(qrand()) / RAND_MAX;
+ p.x_velocity = v * fastCos(a);
+ p.y_velocity = v * fastSin(a);
+ particles.append(p);
+ motion->created(particles.last());
+}
+
+void QmlGraphicsParticlesPrivate::updateOpacity(QmlGraphicsParticle &p, int age)
+{
+ switch (p.state) {
+ case QmlGraphicsParticle::FadeIn:
+ if (age <= fadeInDur) {
+ p.opacity = qreal(age) / fadeInDur;
+ break;
+ } else {
+ p.opacity = 1.0;
+ p.state = QmlGraphicsParticle::Solid;
+ // Fall through
+ }
+ case QmlGraphicsParticle::Solid:
+ if (age <= p.fadeOutAge) {
+ break;
+ } else {
+ p.state = QmlGraphicsParticle::FadeOut;
+ // Fall through
+ }
+ case QmlGraphicsParticle::FadeOut:
+ p.opacity = qreal(p.lifeSpan - age) / fadeOutDur;
+ break;
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Particles,QmlGraphicsParticles)
+
+/*!
+ \qmlclass Particles
+ \brief The Particles object generates and moves particles.
+ \inherits Item
+
+ This element provides preliminary support for particles in QML, and may be heavily changed or removed in later versions.
+
+ The particles created by this object cannot be dealt with directly, they can only be controlled through the parameters of the Particles object. The particles are all the same pixmap, specified by the user.
+
+ The particles are painted relative to the parent of the Particles object. Moving the
+ Particles object will not move the particles already emitted.
+
+ The below example creates two differently behaving particle sources.
+ The top one has particles falling from the top like snow,
+ the lower one has particles expelled up like a fountain.
+
+ \qml
+Rectangle {
+ width: 240
+ height: 320
+ color: "black"
+ Particles {
+ y: 0
+ width: parent.width
+ height: 30
+ source: "star.png"
+ lifeSpan: 5000
+ count: 50
+ angle: 70
+ angleDeviation: 36
+ velocity: 30
+ velocityDeviation: 10
+ ParticleMotionWander {
+ xvariance: 30
+ pace: 100
+ }
+ }
+ Particles {
+ y: 300
+ x: 120
+ width: 1
+ height: 1
+ source: "star.png"
+ lifeSpan: 5000
+ count: 200
+ angle: 270
+ angleDeviation: 45
+ velocity: 50
+ velocityDeviation: 30
+ ParticleMotionGravity {
+ yattractor: 1000
+ xattractor: 0
+ acceleration: 25
+ }
+ }
+}
+ \endqml
+ \image particles.gif
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsParticles
+ \ingroup group_effects
+ \brief The QmlGraphicsParticles class generates and moves particles.
+*/
+
+QmlGraphicsParticles::QmlGraphicsParticles(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsParticlesPrivate), parent)
+{
+ Q_D(QmlGraphicsParticles);
+ d->init();
+}
+
+QmlGraphicsParticles::~QmlGraphicsParticles()
+{
+ Q_D(QmlGraphicsParticles);
+ if (d->pendingPixmapCache)
+ QmlPixmapCache::cancel(d->url, this);
+}
+
+/*!
+ \qmlproperty string Particles::src
+ This property holds the URL of the particle image.
+*/
+
+/*!
+ \property QmlGraphicsParticles::source
+ \brief the URL of the particle image.
+*/
+QUrl QmlGraphicsParticles::source() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->url;
+}
+
+void QmlGraphicsParticles::imageLoaded()
+{
+ Q_D(QmlGraphicsParticles);
+ d->pendingPixmapCache = false;
+ QmlPixmapCache::get(d->url, &d->image);
+ d->paintItem->updateSize();
+ d->paintItem->update();
+}
+
+void QmlGraphicsParticles::setSource(const QUrl &name)
+{
+ Q_D(QmlGraphicsParticles);
+
+ if ((d->url.isEmpty() == name.isEmpty()) && name == d->url)
+ return;
+
+ if (d->pendingPixmapCache) {
+ QmlPixmapCache::cancel(d->url, this);
+ d->pendingPixmapCache = false;
+ }
+ if (name.isEmpty()) {
+ d->url = name;
+ d->image = QPixmap();
+ d->paintItem->updateSize();
+ d->paintItem->update();
+ } else {
+ d->url = name;
+ Q_ASSERT(!name.isRelative());
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->image);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url);
+ connect(reply, SIGNAL(finished()), this, SLOT(imageLoaded()));
+ d->pendingPixmapCache = true;
+ } else {
+ //### unify with imageLoaded
+ d->paintItem->updateSize();
+ d->paintItem->update();
+ }
+ }
+ emit sourceChanged();
+}
+
+/*!
+ \qmlproperty int Particles::count
+ This property holds the maximum number of particles
+
+ The particles element emits particles until it has count active
+ particles. When this number is reached, new particles are not emitted until
+ some of the current particles reach theend of their lifespan.
+
+ If count is -1 then there is no maximum number of active particles, and
+ particles will be constantly emitted at the rate specified by emissionRate.
+
+ If both count and emissionRate are set to -1, nothing will be emitted.
+
+*/
+
+/*!
+ \property QmlGraphicsParticles::count
+ \brief the maximum number of particles
+*/
+int QmlGraphicsParticles::count() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->count;
+}
+
+void QmlGraphicsParticles::setCount(int cnt)
+{
+ Q_D(QmlGraphicsParticles);
+ if (cnt == d->count)
+ return;
+
+ int oldCount = d->count;
+ d->count = cnt;
+ d->addParticleTime = 0;
+ d->addParticleCount = d->particles.count();
+ if (!oldCount && d->clock.state() != QAbstractAnimation::Running && d->count && d->emissionRate) {
+ d->clock.start();
+ }
+ d->paintItem->updateSize();
+ d->paintItem->update();
+ emit countChanged();
+}
+
+
+/*!
+ \qmlproperty int Particles::emissionRate
+ This property holds the target number of particles to emit every second.
+
+ The particles element will emit up to emissionRate particles every
+ second. Fewer particles may be emitted per second if the maximum number of
+ particles has been reached.
+
+ If emissionRate is set to -1 there is no limit to the number of
+ particles emitted per second, and particles will be instantly emitted to
+ reach the maximum number of particles specified by count.
+
+ The default value for emissionRate is -1.
+
+ If both count and emissionRate are set to -1, nothing will be emitted.
+*/
+
+/*!
+ \property QmlGraphicsParticles::emissionRate
+ \brief the emission rate of particles
+*/
+int QmlGraphicsParticles::emissionRate() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->emissionRate;
+}
+void QmlGraphicsParticles::setEmissionRate(int er)
+{
+ Q_D(QmlGraphicsParticles);
+ if(er == d->emissionRate)
+ return;
+ d->emissionRate = er;
+ if (d->clock.state() != QAbstractAnimation::Running && d->count && d->emissionRate) {
+ d->clock.start();
+ }
+ emit emissionRateChanged();
+}
+
+/*!
+ \qmlproperty qreal Particles::emissionVariance
+ This property holds how inconsistent the rate of particle emissions are.
+ It is a number between 0 (no variance) and 1 (some variance).
+
+ The expected number of particles emitted per second is emissionRate. If
+ emissionVariance is 0 then particles will be emitted consistently throughout
+ each second to reach that number. If emissionVariance is greater than 0 the
+ rate of particle emission will vary randomly throughout the second, with the
+ consequence that the actual number of particles emitted in one second will
+ vary randomly as well.
+
+ emissionVariance is the maximum deviation from emitting
+ emissionRate particles per second. An emissionVariance of 0 means you should
+ get exactly emissionRate particles emitted per second,
+ and an emissionVariance of 1 means you will get between zero and two times
+ emissionRate particles per second, but you should get emissionRate particles
+ per second on average.
+
+ Note that even with an emissionVariance of 0 there may be some variance due
+ to performance and hardware constraints.
+
+ The default value of emissionVariance is 0.5
+*/
+
+/*!
+ \property QmlGraphicsParticles::emissionVariance
+ \brief how much the particle emission amounts vary per tick
+*/
+
+qreal QmlGraphicsParticles::emissionVariance() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->emissionVariance;
+}
+
+void QmlGraphicsParticles::setEmissionVariance(qreal ev)
+{
+ Q_D(QmlGraphicsParticles);
+ if(d->emissionVariance == ev)
+ return;
+ d->emissionVariance = ev;
+ emit emissionVarianceChanged();
+}
+
+/*!
+ \qmlproperty int Particles::lifeSpan
+ \qmlproperty int Particles::lifeSpanDeviation
+
+ These properties describe the life span of each particle.
+
+ The default lifespan for a particle is 1000ms.
+
+ lifeSpanDeviation randomly varies the lifeSpan up to the specified variation. For
+ example, the following creates particles whose lifeSpan will vary
+ from 150ms to 250ms:
+
+ \qml
+Particles {
+ source: "star.png"
+ lifeSpan: 200
+ lifeSpanDeviation: 100
+}
+ \endqml
+*/
+
+/*!
+ \property QmlGraphicsParticles::lifeSpan
+ \brief the life span of each particle.
+
+ Default value is 1000ms.
+
+ \sa QmlGraphicsParticles::lifeSpanDeviation
+*/
+int QmlGraphicsParticles::lifeSpan() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->lifeSpan;
+}
+
+void QmlGraphicsParticles::setLifeSpan(int ls)
+{
+ Q_D(QmlGraphicsParticles);
+ if(d->lifeSpan == ls)
+ return;
+ d->lifeSpan = ls;
+ emit lifeSpanChanged();
+}
+
+/*!
+ \property QmlGraphicsParticles::lifeSpanDeviation
+ \brief the maximum possible deviation from the set lifeSpan.
+
+ Randomly varies the lifeSpan up to the specified variation. For
+ example, the following creates particles whose lifeSpan will vary
+ from 150ms to 250ms:
+
+\qml
+Particles {
+ source: "star.png"
+ lifeSpan: 200
+ lifeSpanDeviation: 100
+}
+\endqml
+
+ \sa QmlGraphicsParticles::lifeSpan
+*/
+int QmlGraphicsParticles::lifeSpanDeviation() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->lifeSpanDev;
+}
+
+void QmlGraphicsParticles::setLifeSpanDeviation(int dev)
+{
+ Q_D(QmlGraphicsParticles);
+ if(d->lifeSpanDev == dev)
+ return;
+ d->lifeSpanDev = dev;
+ emit lifeSpanDeviationChanged();
+}
+
+/*!
+ \qmlproperty int Particles::fadeInDuration
+ \qmlproperty int Particles::fadeOutDuration
+ These properties hold the time taken to fade the particles in and out.
+
+ By default fade in is 200ms and fade out is 300ms.
+*/
+
+/*!
+ \property QmlGraphicsParticles::fadeInDuration
+ \brief the time taken to fade in the particles.
+
+ Default value is 200ms.
+*/
+int QmlGraphicsParticles::fadeInDuration() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->fadeInDur;
+}
+
+void QmlGraphicsParticles::setFadeInDuration(int dur)
+{
+ Q_D(QmlGraphicsParticles);
+ if (dur < 0.0 || dur == d->fadeInDur)
+ return;
+ d->fadeInDur = dur;
+ emit fadeInDurationChanged();
+}
+
+/*!
+ \property QmlGraphicsParticles::fadeOutDuration
+ \brief the time taken to fade out the particles.
+
+ Default value is 300ms.
+*/
+int QmlGraphicsParticles::fadeOutDuration() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->fadeOutDur;
+}
+
+void QmlGraphicsParticles::setFadeOutDuration(int dur)
+{
+ Q_D(QmlGraphicsParticles);
+ if (dur < 0.0 || d->fadeOutDur == dur)
+ return;
+ d->fadeOutDur = dur;
+ emit fadeOutDurationChanged();
+}
+
+/*!
+ \qmlproperty real Particles::angle
+ \qmlproperty real Particles::angleDeviation
+
+ These properties control particle direction.
+
+ angleDeviation randomly varies the direction up to the specified variation. For
+ example, the following creates particles whose initial direction will
+ vary from 15 degrees to 105 degrees:
+
+ \qml
+Particles {
+ source: "star.png"
+ angle: 60
+ angleDeviation: 90
+}
+ \endqml
+*/
+
+/*!
+ \property QmlGraphicsParticles::angle
+ \brief the initial angle of direction.
+
+ \sa QmlGraphicsParticles::angleDeviation
+*/
+qreal QmlGraphicsParticles::angle() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->angle * 180.0 / M_PI;
+}
+
+void QmlGraphicsParticles::setAngle(qreal angle)
+{
+ Q_D(QmlGraphicsParticles);
+ qreal radAngle = angle * M_PI / 180.0;
+ if(radAngle == d->angle)
+ return;
+ d->angle = radAngle;
+ emit angleChanged();
+}
+
+/*!
+ \property QmlGraphicsParticles::angleDeviation
+ \brief the maximum possible deviation from the set angle.
+
+ Randomly varies the direction up to the specified variation. For
+ example, the following creates particles whose initial direction will
+ vary from 15 degrees to 105 degrees:
+
+\qml
+Particles {
+ source: "star.png"
+ angle: 60
+ angleDeviation: 90
+}
+\endqml
+
+ \sa QmlGraphicsParticles::angle
+*/
+qreal QmlGraphicsParticles::angleDeviation() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->angleDev * 180.0 / M_PI;
+}
+
+void QmlGraphicsParticles::setAngleDeviation(qreal dev)
+{
+ Q_D(QmlGraphicsParticles);
+ qreal radDev = dev * M_PI / 180.0;
+ if(radDev == d->angleDev)
+ return;
+ d->angleDev = radDev;
+ emit angleDeviationChanged();
+}
+
+/*!
+ \qmlproperty real Particles::velocity
+ \qmlproperty real Particles::velocityDeviation
+
+ These properties control the velocity of the particles.
+
+ velocityDeviation randomly varies the velocity up to the specified variation. For
+ example, the following creates particles whose initial velocity will
+ vary from 40 to 60.
+
+ \qml
+Particles {
+ source: "star.png"
+ velocity: 50
+ velocityDeviation: 20
+}
+ \endqml
+*/
+
+/*!
+ \property QmlGraphicsParticles::velocity
+ \brief the initial velocity of the particles.
+
+ \sa QmlGraphicsParticles::velocityDeviation
+*/
+qreal QmlGraphicsParticles::velocity() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->velocity * 1000.0;
+}
+
+void QmlGraphicsParticles::setVelocity(qreal velocity)
+{
+ Q_D(QmlGraphicsParticles);
+ qreal realVel = velocity / 1000.0;
+ if(realVel == d->velocity)
+ return;
+ d->velocity = realVel;
+ emit velocityChanged();
+}
+
+/*!
+ \property QmlGraphicsParticles::velocityDeviation
+ \brief the maximum possible deviation from the set velocity.
+
+ Randomly varies the velocity up to the specified variation. For
+ example, the following creates particles whose initial velocity will
+ vary from 40 to 60.
+
+\qml
+Particles {
+ source: "star.png"
+ velocity: 50
+ velocityDeviation: 20
+}
+\endqml
+
+ \sa QmlGraphicsParticles::velocity
+*/
+qreal QmlGraphicsParticles::velocityDeviation() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->velocityDev * 1000.0;
+}
+
+void QmlGraphicsParticles::setVelocityDeviation(qreal velocity)
+{
+ Q_D(QmlGraphicsParticles);
+ qreal realDev = velocity / 1000.0;
+ if(realDev == d->velocityDev)
+ return;
+ d->velocityDev = realDev;
+ emit velocityDeviationChanged();
+}
+
+/*!
+ \qmlproperty ParticleMotion Particles::motion
+ This property sets the type of motion to apply to the particles.
+
+ When a particle is created it will have an initial direction and velocity.
+ The motion of the particle during its lifeSpan is then influenced by the
+ motion property.
+
+ Default motion is ParticleMotionLinear.
+*/
+
+/*!
+ \property QmlGraphicsParticles::motion
+ \brief sets the type of motion to apply to the particles.
+
+ When a particle is created it will have an initial direction and velocity.
+ The motion of the particle during its lifeSpan is then influenced by the
+ motion property.
+
+ Default motion is QmlGraphicsParticleMotionLinear.
+*/
+QmlGraphicsParticleMotion *QmlGraphicsParticles::motion() const
+{
+ Q_D(const QmlGraphicsParticles);
+ return d->motion;
+}
+
+void QmlGraphicsParticles::setMotion(QmlGraphicsParticleMotion *motion)
+{
+ Q_D(QmlGraphicsParticles);
+ d->motion = motion;
+}
+
+/*!
+ \qmlmethod Particles::burst(int count, int emissionRate)
+
+ Initiates a burst of particles.
+
+ This method takes two arguments. The first argument is the number
+ of particles to emit and the second argument is the emissionRate for the
+ burst. If the second argument is omitted, it is treated as -1. The burst
+ of particles has a separate emissionRate and count to the normal emission of
+ particles. The burst uses the same values as normal emission for all other
+ properties, including emissionVariance.
+
+ The normal emission of particles will continue during the burst, however
+ the particles created by the burst count towards the maximum number used by
+ normal emission. To avoid this behavior, use two Particles elements.
+
+*/
+void QmlGraphicsParticles::burst(int count, int emissionRate)
+{
+ Q_D(QmlGraphicsParticles);
+ d->bursts << qMakePair(count, emissionRate);
+ if (d->clock.state() != QAbstractAnimation::Running)
+ d->clock.start();
+}
+
+void QmlGraphicsParticlesPainter::updateSize()
+{
+ if (!isComponentComplete())
+ return;
+
+ const int parentX = parentItem()->x();
+ const int parentY = parentItem()->y();
+ for (int i = 0; i < d->particles.count(); ++i) {
+ const QmlGraphicsParticle &particle = d->particles.at(i);
+ if(particle.x > maxX)
+ maxX = particle.x;
+ if(particle.x < minX)
+ minX = particle.x;
+ if(particle.y > maxY)
+ maxY = particle.y;
+ if(particle.y < minY)
+ minY = particle.y;
+ }
+
+ int myWidth = (int)(maxX-minX+0.5)+d->image.width();
+ int myX = (int)(minX - parentX);
+ int myHeight = (int)(maxY-minY+0.5)+d->image.height();
+ int myY = (int)(minY - parentY);
+ setWidth(myWidth);
+ setHeight(myHeight);
+ setX(myX);
+ setY(myY);
+}
+
+void QmlGraphicsParticles::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_UNUSED(p);
+ //painting is done by the ParticlesPainter, so it can have the right size
+}
+
+void QmlGraphicsParticlesPainter::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (d->image.isNull() || d->particles.isEmpty())
+ return;
+
+ const int myX = x() + parentItem()->x();
+ const int myY = y() + parentItem()->y();
+
+ QVarLengthArray<QDrawPixmaps::Data, 256> pixmapData;
+ pixmapData.resize(d->particles.count());
+
+ const QRectF sourceRect = d->image.rect();
+ qreal halfPWidth = sourceRect.width()/2.;
+ qreal halfPHeight = sourceRect.height()/2.;
+ for (int i = 0; i < d->particles.count(); ++i) {
+ const QmlGraphicsParticle &particle = d->particles.at(i);
+ pixmapData[i].point = QPointF(particle.x - myX + halfPWidth, particle.y - myY + halfPHeight);
+ pixmapData[i].opacity = particle.opacity;
+
+ //these never change
+ pixmapData[i].rotation = 0;
+ pixmapData[i].scaleX = 1;
+ pixmapData[i].scaleY = 1;
+ pixmapData[i].source = sourceRect;
+ }
+ qDrawPixmaps(p, pixmapData.data(), d->particles.count(), d->image);
+}
+
+void QmlGraphicsParticles::componentComplete()
+{
+ Q_D(QmlGraphicsParticles);
+ QmlGraphicsItem::componentComplete();
+ if (d->count) {
+ d->paintItem->updateSize();
+ d->clock.start();
+ }
+ if (d->lifeSpanDev > d->lifeSpan)
+ d->lifeSpanDev = d->lifeSpan;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsparticles_p.h b/src/declarative/graphicsitems/qmlgraphicsparticles_p.h
new file mode 100644
index 0000000..c34d55b
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsparticles_p.h
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSPARTICLES_H
+#define QMLGRAPHICSPARTICLES_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsParticle;
+class QmlGraphicsParticles;
+class Q_DECLARATIVE_EXPORT QmlGraphicsParticleMotion : public QObject
+{
+ Q_OBJECT
+public:
+ QmlGraphicsParticleMotion(QObject *parent=0);
+
+ virtual void advance(QmlGraphicsParticle &, int interval);
+ virtual void created(QmlGraphicsParticle &);
+ virtual void destroy(QmlGraphicsParticle &);
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsParticleMotionLinear : public QmlGraphicsParticleMotion
+{
+ Q_OBJECT
+public:
+ QmlGraphicsParticleMotionLinear(QObject *parent=0)
+ : QmlGraphicsParticleMotion(parent) {}
+
+ virtual void advance(QmlGraphicsParticle &, int interval);
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsParticleMotionGravity : public QmlGraphicsParticleMotion
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int xattractor READ xAttractor WRITE setXAttractor)
+ Q_PROPERTY(int yattractor READ yAttractor WRITE setYAttractor)
+ Q_PROPERTY(int acceleration READ acceleration WRITE setAcceleration)
+public:
+ QmlGraphicsParticleMotionGravity(QObject *parent=0)
+ : QmlGraphicsParticleMotion(parent), _xAttr(0), _yAttr(0), _accel(0.00005) {}
+
+ int xAttractor() const { return _xAttr; }
+ void setXAttractor(int x) { _xAttr = x; }
+
+ int yAttractor() const { return _yAttr; }
+ void setYAttractor(int y) { _yAttr = y; }
+
+ int acceleration() const { return int(_accel * 1000000); }
+ void setAcceleration(int accel) { _accel = qreal(accel)/1000000.0; }
+
+ virtual void advance(QmlGraphicsParticle &, int interval);
+
+private:
+ int _xAttr;
+ int _yAttr;
+ qreal _accel;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsParticleMotionWander : public QmlGraphicsParticleMotion
+{
+ Q_OBJECT
+public:
+ QmlGraphicsParticleMotionWander()
+ : QmlGraphicsParticleMotion(), particles(0), _xvariance(0), _yvariance(0) {}
+
+ virtual void advance(QmlGraphicsParticle &, int interval);
+ virtual void created(QmlGraphicsParticle &);
+ virtual void destroy(QmlGraphicsParticle &);
+
+ struct Data {
+ qreal x_targetV;
+ qreal y_targetV;
+ qreal x_peak;
+ qreal y_peak;
+ qreal x_var;
+ qreal y_var;
+ };
+
+ Q_PROPERTY(int xvariance READ xVariance WRITE setXVariance)
+ int xVariance() const { return int(_xvariance * 1000); }
+ void setXVariance(int var) { _xvariance = var / 1000.0; }
+
+ Q_PROPERTY(int yvariance READ yVariance WRITE setYVariance)
+ int yVariance() const { return int(_yvariance * 1000); }
+ void setYVariance(int var) { _yvariance = var / 1000.0; }
+
+ Q_PROPERTY(int pace READ pace WRITE setPace)
+ int pace() const { return int(_pace * 1000); }
+ void setPace(int pace) { _pace = pace / 1000.0; }
+
+private:
+ QmlGraphicsParticles *particles;
+ qreal _xvariance;
+ qreal _yvariance;
+ qreal _pace;
+};
+
+class QmlGraphicsParticlesPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsParticles : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
+ Q_PROPERTY(int emissionRate READ emissionRate WRITE setEmissionRate NOTIFY emissionRateChanged)
+ Q_PROPERTY(qreal emissionVariance READ emissionVariance WRITE setEmissionVariance NOTIFY emissionVarianceChanged)
+ Q_PROPERTY(int lifeSpan READ lifeSpan WRITE setLifeSpan NOTIFY lifeSpanChanged)
+ Q_PROPERTY(int lifeSpanDeviation READ lifeSpanDeviation WRITE setLifeSpanDeviation NOTIFY lifeSpanDeviationChanged)
+ Q_PROPERTY(int fadeInDuration READ fadeInDuration WRITE setFadeInDuration NOTIFY fadeInDurationChanged)
+ Q_PROPERTY(int fadeOutDuration READ fadeOutDuration WRITE setFadeOutDuration NOTIFY fadeOutDurationChanged)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
+ Q_PROPERTY(qreal angleDeviation READ angleDeviation WRITE setAngleDeviation NOTIFY angleDeviationChanged)
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(qreal velocityDeviation READ velocityDeviation WRITE setVelocityDeviation NOTIFY velocityDeviationChanged)
+ Q_PROPERTY(QmlGraphicsParticleMotion *motion READ motion WRITE setMotion)
+ Q_CLASSINFO("DefaultProperty", "motion")
+
+public:
+ QmlGraphicsParticles(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsParticles();
+
+ QUrl source() const;
+ void setSource(const QUrl &);
+
+ int count() const;
+ void setCount(int cnt);
+
+ int emissionRate() const;
+ void setEmissionRate(int);
+
+ qreal emissionVariance() const;
+ void setEmissionVariance(qreal);
+
+ int lifeSpan() const;
+ void setLifeSpan(int);
+
+ int lifeSpanDeviation() const;
+ void setLifeSpanDeviation(int);
+
+ int fadeInDuration() const;
+ void setFadeInDuration(int);
+
+ int fadeOutDuration() const;
+ void setFadeOutDuration(int);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ qreal angleDeviation() const;
+ void setAngleDeviation(qreal);
+
+ qreal velocity() const;
+ void setVelocity(qreal);
+
+ qreal velocityDeviation() const;
+ void setVelocityDeviation(qreal);
+
+ QmlGraphicsParticleMotion *motion() const;
+ void setMotion(QmlGraphicsParticleMotion *);
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+public Q_SLOTS:
+ void burst(int count, int emissionRate=-1);
+
+protected:
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void sourceChanged();
+ void countChanged();
+ void emissionRateChanged();
+ void emissionVarianceChanged();
+ void lifeSpanChanged();
+ void lifeSpanDeviationChanged();
+ void fadeInDurationChanged();
+ void fadeOutDurationChanged();
+ void angleChanged();
+ void angleDeviationChanged();
+ void velocityChanged();
+ void velocityDeviationChanged();
+ void emittingChanged();
+
+private Q_SLOTS:
+ void imageLoaded();
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsParticles)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsParticles)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsParticleMotion)
+QML_DECLARE_TYPE(QmlGraphicsParticleMotionLinear)
+QML_DECLARE_TYPE(QmlGraphicsParticleMotionGravity)
+QML_DECLARE_TYPE(QmlGraphicsParticleMotionWander)
+QML_DECLARE_TYPE(QmlGraphicsParticles)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicspath.cpp b/src/declarative/graphicsitems/qmlgraphicspath.cpp
new file mode 100644
index 0000000..18f27af
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspath.cpp
@@ -0,0 +1,850 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicspath_p.h"
+#include "qmlgraphicspath_p_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QSet>
+
+#include <private/qbezier_p.h>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,Path,QmlGraphicsPath)
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsPathElement)
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsCurve)
+QML_DEFINE_TYPE(Qt,4,6,PathAttribute,QmlGraphicsPathAttribute)
+QML_DEFINE_TYPE(Qt,4,6,PathPercent,QmlGraphicsPathPercent)
+QML_DEFINE_TYPE(Qt,4,6,PathLine,QmlGraphicsPathLine)
+QML_DEFINE_TYPE(Qt,4,6,PathQuad,QmlGraphicsPathQuad)
+QML_DEFINE_TYPE(Qt,4,6,PathCubic,QmlGraphicsPathCubic)
+
+/*!
+ \qmlclass PathElement QmlGraphicsPathElement
+ \brief PathElement is the base path type.
+
+ This type is the base for all path types. It cannot
+ be instantiated.
+
+ \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsPathElement
+ \ingroup group_utility
+*/
+
+/*!
+ \qmlclass Path QmlGraphicsPath
+ \brief A Path object defines a path for use by \l PathView.
+
+ A Path is composed of one or more path segments - PathLine, PathQuad,
+ PathCubic.
+
+ The spacing of the items along the Path can be adjusted via a
+ PathPercent object.
+
+ PathAttribute allows named attributes with values to be defined
+ along the path.
+
+ \sa PathView, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsPath
+ \ingroup group_utility
+ \brief The QmlGraphicsPath class defines a path.
+ \sa QmlGraphicsPathView
+*/
+QmlGraphicsPath::QmlGraphicsPath(QObject *parent)
+ : QObject(*(new QmlGraphicsPathPrivate), parent)
+{
+}
+
+QmlGraphicsPath::~QmlGraphicsPath()
+{
+}
+
+/*!
+ \qmlproperty real Path::startX
+ \qmlproperty real Path::startY
+ These properties hold the starting position of the path.
+*/
+qreal QmlGraphicsPath::startX() const
+{
+ Q_D(const QmlGraphicsPath);
+ return d->startX;
+}
+
+void QmlGraphicsPath::setStartX(qreal x)
+{
+ Q_D(QmlGraphicsPath);
+ d->startX = x;
+}
+
+qreal QmlGraphicsPath::startY() const
+{
+ Q_D(const QmlGraphicsPath);
+ return d->startY;
+}
+
+void QmlGraphicsPath::setStartY(qreal y)
+{
+ Q_D(QmlGraphicsPath);
+ d->startY = y;
+}
+
+/*!
+ \qmlproperty bool Path::closed
+ This property holds whether the start and end of the path are identical.
+*/
+bool QmlGraphicsPath::isClosed() const
+{
+ Q_D(const QmlGraphicsPath);
+ return d->closed;
+}
+
+/*!
+ \qmlproperty list<PathElement> Path::pathElements
+ This property holds the objects composing the path.
+
+ \default
+
+ A path can contain the following path objects:
+ \list
+ \i \l PathLine - a straight line to a given position.
+ \i \l PathQuad - a quadratic Bezier curve to a given position with a control point.
+ \i \l PathCubic - a cubic Bezier curve to a given position with two control points.
+ \i \l PathAttribute - an attribute at a given position in the path.
+ \i \l PathPercent - a way to spread out items along various segments of the path.
+ \endlist
+
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 2
+*/
+
+QList<QmlGraphicsPathElement *>* QmlGraphicsPath::pathElements()
+{
+ Q_D(QmlGraphicsPath);
+ return &(d->_pathElements);
+}
+
+void QmlGraphicsPath::interpolate(int idx, const QString &name, qreal value)
+{
+ Q_D(QmlGraphicsPath);
+ if (!idx)
+ return;
+
+ qreal lastValue = 0;
+ qreal lastPercent = 0;
+ int search = idx - 1;
+ while(search >= 0) {
+ const AttributePoint &point = d->_attributePoints.at(search);
+ if (point.values.contains(name)) {
+ lastValue = point.values.value(name);
+ lastPercent = point.origpercent;
+ break;
+ }
+ --search;
+ }
+
+ ++search;
+
+ const AttributePoint &curPoint = d->_attributePoints.at(idx);
+
+ for (int ii = search; ii < idx; ++ii) {
+ AttributePoint &point = d->_attributePoints[ii];
+
+ qreal val = lastValue + (value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
+ point.values.insert(name, val);
+ }
+}
+
+void QmlGraphicsPath::endpoint(const QString &name)
+{
+ Q_D(QmlGraphicsPath);
+ const AttributePoint &first = d->_attributePoints.first();
+ qreal val = first.values.value(name);
+ for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(name)) {
+ for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
+ AttributePoint &setPoint = d->_attributePoints[jj];
+ setPoint.values.insert(name, val);
+ }
+ return;
+ }
+ }
+}
+
+void QmlGraphicsPath::processPath()
+{
+ Q_D(QmlGraphicsPath);
+
+ d->_pointCache.clear();
+ d->_attributePoints.clear();
+ d->_path = QPainterPath();
+
+ AttributePoint first;
+ for (int ii = 0; ii < d->_attributes.count(); ++ii)
+ first.values[d->_attributes.at(ii)] = 0;
+ d->_attributePoints << first;
+
+ d->_path.moveTo(d->startX, d->startY);
+
+ QmlGraphicsCurve *lastCurve = 0;
+ foreach (QmlGraphicsPathElement *pathElement, d->_pathElements) {
+ if (QmlGraphicsCurve *curve = qobject_cast<QmlGraphicsCurve *>(pathElement)) {
+ curve->addToPath(d->_path);
+ AttributePoint p;
+ p.origpercent = d->_path.length();
+ d->_attributePoints << p;
+ lastCurve = curve;
+ } else if (QmlGraphicsPathAttribute *attribute = qobject_cast<QmlGraphicsPathAttribute *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[attribute->name()] = attribute->value();
+ interpolate(d->_attributePoints.count() - 1, attribute->name(), attribute->value());
+ } else if (QmlGraphicsPathPercent *percent = qobject_cast<QmlGraphicsPathPercent *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[QLatin1String("_qfx_percent")] = percent->value();
+ interpolate(d->_attributePoints.count() - 1, QLatin1String("_qfx_percent"), percent->value());
+ }
+ }
+
+ // Fixup end points
+ const AttributePoint &last = d->_attributePoints.last();
+ for (int ii = 0; ii < d->_attributes.count(); ++ii) {
+ if (!last.values.contains(d->_attributes.at(ii)))
+ endpoint(d->_attributes.at(ii));
+ }
+
+ // Adjust percent
+ qreal length = d->_path.length();
+ qreal prevpercent = 0;
+ qreal prevorigpercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(QLatin1String("_qfx_percent"))) { //special string for QmlGraphicsPathPercent
+ if ( ii > 0) {
+ qreal scale = (d->_attributePoints[ii].origpercent/length - prevorigpercent) /
+ (point.values.value(QLatin1String("_qfx_percent"))-prevpercent);
+ d->_attributePoints[ii].scale = scale;
+ }
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = point.values.value(QLatin1String("_qfx_percent"));
+ prevorigpercent = d->_attributePoints[ii].origpercent;
+ prevpercent = d->_attributePoints[ii].percent;
+ } else {
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = d->_attributePoints[ii].origpercent;
+ }
+ }
+
+ d->closed = lastCurve && d->startX == lastCurve->x() && d->startY == lastCurve->y();
+
+ emit changed();
+}
+
+void QmlGraphicsPath::componentComplete()
+{
+ Q_D(QmlGraphicsPath);
+ QSet<QString> attrs;
+ // First gather up all the attributes
+ foreach (QmlGraphicsPathElement *pathElement, d->_pathElements) {
+ if (QmlGraphicsPathAttribute *attribute =
+ qobject_cast<QmlGraphicsPathAttribute *>(pathElement))
+ attrs.insert(attribute->name());
+ }
+ d->_attributes = attrs.toList();
+
+ processPath();
+
+ foreach (QmlGraphicsPathElement *pathElement, d->_pathElements)
+ connect(pathElement, SIGNAL(changed()), this, SLOT(processPath()));
+}
+
+QPainterPath QmlGraphicsPath::path() const
+{
+ Q_D(const QmlGraphicsPath);
+ return d->_path;
+}
+
+QStringList QmlGraphicsPath::attributes() const
+{
+ Q_D(const QmlGraphicsPath);
+ return d->_attributes;
+}
+#include <QTime>
+
+static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength)
+{
+ const int lastElement = path.elementCount() - 1;
+ for (int i=*from; i <= lastElement; ++i) {
+ const QPainterPath::Element &e = path.elementAt(i);
+
+ switch (e.type) {
+ case QPainterPath::MoveToElement:
+ break;
+ case QPainterPath::LineToElement:
+ {
+ QLineF line(path.elementAt(i-1), e);
+ *bezLength = line.length();
+ QPointF a = path.elementAt(i-1);
+ QPointF delta = e - a;
+ *from = i+1;
+ return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
+ }
+ case QPainterPath::CurveToElement:
+ {
+ QBezier b = QBezier::fromPoints(path.elementAt(i-1),
+ e,
+ path.elementAt(i+1),
+ path.elementAt(i+2));
+ *bezLength = b.length();
+ *from = i+3;
+ return b;
+ }
+ default:
+ break;
+ }
+ }
+ *from = lastElement;
+ *bezLength = 0;
+ return QBezier();
+}
+
+void QmlGraphicsPath::createPointCache() const
+{
+ Q_D(const QmlGraphicsPath);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::QmlGraphicsPathViewPathCache> pc;
+#endif
+ qreal pathLength = d->_path.length();
+ const int points = int(pathLength*2);
+ const int lastElement = d->_path.elementCount() - 1;
+ d->_pointCache.resize(points+1);
+
+ int currElement = 0;
+ qreal bezLength = 0;
+ QBezier currBez = nextBezier(d->_path, &currElement, &bezLength);
+ qreal currLength = bezLength;
+ qreal epc = currLength / pathLength;
+
+ for (int i = 0; i < d->_pointCache.size(); i++) {
+ //find which set we are in
+ qreal prevPercent = 0;
+ qreal prevOrigPercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ qreal percent = qreal(i)/points;
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
+ qreal elementPercent = (percent - prevPercent);
+
+ qreal spc = prevOrigPercent + elementPercent * point.scale;
+
+ while (spc > epc) {
+ if (currElement > lastElement)
+ break;
+ currBez = nextBezier(d->_path, &currElement, &bezLength);
+ if (bezLength == 0.0) {
+ currLength = pathLength;
+ epc = 1.0;
+ break;
+ }
+ currLength += bezLength;
+ epc = currLength / pathLength;
+ }
+ qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
+ d->_pointCache[i] = currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
+ break;
+ }
+ prevOrigPercent = point.origpercent;
+ prevPercent = point.percent;
+ }
+ }
+}
+
+QPointF QmlGraphicsPath::pointAt(qreal p) const
+{
+ Q_D(const QmlGraphicsPath);
+ if (d->_pointCache.isEmpty()) {
+ createPointCache();
+ }
+ int idx = qRound(p*d->_pointCache.size());
+ if (idx >= d->_pointCache.size())
+ idx = d->_pointCache.size() - 1;
+ else if (idx < 0)
+ idx = 0;
+ return d->_pointCache.at(idx);
+}
+
+qreal QmlGraphicsPath::attributeAt(const QString &name, qreal percent) const
+{
+ Q_D(const QmlGraphicsPath);
+ if (percent < 0 || percent > 1)
+ return 0;
+
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+
+ if (point.percent == percent) {
+ return point.values.value(name);
+ } else if (point.percent > percent) {
+ qreal lastValue =
+ ii?(d->_attributePoints.at(ii - 1).values.value(name)):0;
+ qreal lastPercent =
+ ii?(d->_attributePoints.at(ii - 1).percent):0;
+ qreal curValue = point.values.value(name);
+ qreal curPercent = point.percent;
+
+ return lastValue + (curValue - lastValue) * (percent - lastPercent) / (curPercent - lastPercent);
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+qreal QmlGraphicsCurve::x() const
+{
+ return _x;
+}
+
+void QmlGraphicsCurve::setX(qreal x)
+{
+ if (_x != x) {
+ _x = x;
+ emit changed();
+ }
+}
+
+qreal QmlGraphicsCurve::y() const
+{
+ return _y;
+}
+
+void QmlGraphicsCurve::setY(qreal y)
+{
+ if (_y != y) {
+ _y = y;
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathAttribute QmlGraphicsPathAttribute
+ \brief The PathAttribute allows setting an attribute at a given position in a Path.
+
+ The PathAttribute object allows attibutes consisting of a name and
+ a value to be specified for the endpoints of path segments. The
+ attributes are exposed to the delegate as
+ \l{qmlintroduction.html#attached-properties} {Attached Properties}.
+ The value of an attribute at any particular point is interpolated
+ from the PathAttributes bounding the point.
+
+ The example below shows a path with the items scaled to 30% with
+ opacity 50% at the top of the path and scaled 100% with opacity
+ 100% at the bottom. Note the use of the PathView.scale and
+ PathView.opacity attached properties to set the scale and opacity
+ of the delegate.
+
+ \table
+ \row
+ \o \image declarative-pathattribute.png
+ \o
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 0
+ \endtable
+
+ \sa Path
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsPathAttribute
+ \ingroup group_utility
+ \brief The QmlGraphicsPathAttribute class allows to set the value of an attribute at a given position in the path.
+
+ \sa QmlGraphicsPath
+*/
+
+
+/*!
+ \qmlproperty string PathAttribute::name
+ the name of the attribute to change.
+*/
+
+/*!
+ the name of the attribute to change.
+*/
+
+QString QmlGraphicsPathAttribute::name() const
+{
+ return _name;
+}
+
+void QmlGraphicsPathAttribute::setName(const QString &name)
+{
+ _name = name;
+}
+
+/*!
+ \qmlproperty string PathAttribute::value
+ the new value of the attribute.
+*/
+
+/*!
+ the new value of the attribute.
+*/
+qreal QmlGraphicsPathAttribute::value() const
+{
+ return _value;
+}
+
+void QmlGraphicsPathAttribute::setValue(qreal value)
+{
+ if (_value != value) {
+ _value = value;
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathLine QmlGraphicsPathLine
+ \brief The PathLine defines a straight line.
+
+ The example below creates a path consisting of a straight line from
+ 0,100 to 200,100:
+
+ \qml
+ Path {
+ startX: 0; startY: 100
+ PathLine { x: 200; y: 100 }
+ }
+ \endqml
+
+ \sa Path, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsPathLine
+ \ingroup group_utility
+ \brief The QmlGraphicsPathLine class defines a straight line.
+
+ \sa QmlGraphicsPath
+*/
+
+/*!
+ \qmlproperty real PathLine::x
+ \qmlproperty real PathLine::y
+
+ Defines the end point of the line.
+*/
+
+void QmlGraphicsPathLine::addToPath(QPainterPath &path)
+{
+ path.lineTo(x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathQuad QmlGraphicsPathQuad
+ \brief The PathQuad defines a quadratic Bezier curve with a control point.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathquad.png
+ \o
+ \qml
+ Path {
+ startX: 0; startY: 0
+ PathQuad x: 200; y: 0; controlX: 100; controlY: 150 }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathCubic, PathLine
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsPathQuad
+ \ingroup group_utility
+ \brief The QmlGraphicsPathQuad class defines a quadratic Bezier curve with a control point.
+
+ \sa QmlGraphicsPath
+*/
+
+
+/*!
+ \qmlproperty real PathQuad::x
+ \qmlproperty real PathQuad::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathQuad::controlX
+ \qmlproperty real PathQuad::controlY
+
+ Defines the position of the control point.
+*/
+
+/*!
+ the x position of the control point.
+*/
+qreal QmlGraphicsPathQuad::controlX() const
+{
+ return _controlX;
+}
+
+void QmlGraphicsPathQuad::setControlX(qreal x)
+{
+ if (_controlX != x) {
+ _controlX = x;
+ emit changed();
+ }
+}
+
+
+/*!
+ the y position of the control point.
+*/
+qreal QmlGraphicsPathQuad::controlY() const
+{
+ return _controlY;
+}
+
+void QmlGraphicsPathQuad::setControlY(qreal y)
+{
+ if (_controlY != y) {
+ _controlY = y;
+ emit changed();
+ }
+}
+
+void QmlGraphicsPathQuad::addToPath(QPainterPath &path)
+{
+ path.quadTo(controlX(), controlY(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathCubic QmlGraphicsPathCubic
+ \brief The PathCubic defines a cubic Bezier curve with two control points.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathcubic.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathCubic {
+ x: 180; y: 0; control1X: -10; control1Y: 90
+ control2X: 210; control2Y: 90
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathQuad, PathLine
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsPathCubic
+ \ingroup group_utility
+ \brief The QmlGraphicsPathCubic class defines a cubic Bezier curve with two control points.
+
+ \sa QmlGraphicsPath
+*/
+
+/*!
+ \qmlproperty real PathCubic::x
+ \qmlproperty real PathCubic::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathCubic::control1X
+ \qmlproperty real PathCubic::control1Y
+
+ Defines the position of the first control point.
+*/
+qreal QmlGraphicsPathCubic::control1X() const
+{
+ return _control1X;
+}
+
+void QmlGraphicsPathCubic::setControl1X(qreal x)
+{
+ if (_control1X != x) {
+ _control1X = x;
+ emit changed();
+ }
+}
+
+qreal QmlGraphicsPathCubic::control1Y() const
+{
+ return _control1Y;
+}
+
+void QmlGraphicsPathCubic::setControl1Y(qreal y)
+{
+ if (_control1Y != y) {
+ _control1Y = y;
+ emit changed();
+ }
+}
+
+/*!
+ \qmlproperty real PathCubic::control2X
+ \qmlproperty real PathCubic::control2Y
+
+ Defines the position of the second control point.
+*/
+qreal QmlGraphicsPathCubic::control2X() const
+{
+ return _control2X;
+}
+
+void QmlGraphicsPathCubic::setControl2X(qreal x)
+{
+ if (_control2X != x) {
+ _control2X = x;
+ emit changed();
+ }
+}
+
+qreal QmlGraphicsPathCubic::control2Y() const
+{
+ return _control2Y;
+}
+
+void QmlGraphicsPathCubic::setControl2Y(qreal y)
+{
+ if (_control2Y != y) {
+ _control2Y = y;
+ emit changed();
+ }
+}
+
+void QmlGraphicsPathCubic::addToPath(QPainterPath &path)
+{
+ path.cubicTo(control1X(), control1Y(), control2X(), control2Y(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathPercent QmlGraphicsPathPercent
+ \brief The PathPercent manipulates the way a path is interpreted.
+
+ The examples below show the normal distrubution of items along a path
+ compared to a distribution which places 50% of the items along the
+ PathLine section of the path.
+ \table
+ \row
+ \o \image declarative-nopercent.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ }
+ \endqml
+ \row
+ \o \image declarative-percent.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathPercent { value: 0.25 }
+ PathLine { x: 150; y: 80 }
+ PathPercent { value: 0.75 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ PathPercent { value: 1 }
+ }
+ \endqml
+ \endtable
+
+ \sa Path
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsPathPercent
+ \ingroup group_utility
+ \brief The QmlGraphicsPathPercent class manipulates the way a path is interpreted.
+
+ QmlGraphicsPathPercent allows you to bunch up items (or spread out items) along various
+ segments of a QmlGraphicsPathView's path.
+
+ \sa QmlGraphicsPath
+
+*/
+
+qreal QmlGraphicsPathPercent::value() const
+{
+ return _value;
+}
+
+void QmlGraphicsPathPercent::setValue(qreal value)
+{
+ _value = value;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicspath_p.h b/src/declarative/graphicsitems/qmlgraphicspath_p.h
new file mode 100644
index 0000000..2b4b0fd
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspath_p.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSPATH_H
+#define QMLGRAPHICSPATH_H
+
+#include "qmlgraphicsitem.h"
+
+#include <qml.h>
+
+#include <QtCore/QObject>
+#include <QtGui/QPainterPath>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QmlGraphicsPathElement : public QObject
+{
+ Q_OBJECT
+public:
+ QmlGraphicsPathElement(QObject *parent=0) : QObject(parent) {}
+Q_SIGNALS:
+ void changed();
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsPathAttribute : public QmlGraphicsPathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
+public:
+ QmlGraphicsPathAttribute(QObject *parent=0) : QmlGraphicsPathElement(parent), _value(0) {}
+
+
+ QString name() const;
+ void setName(const QString &name);
+
+ qreal value() const;
+ void setValue(qreal value);
+
+private:
+ QString _name;
+ qreal _value;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsCurve : public QmlGraphicsPathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY changed)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY changed)
+public:
+ QmlGraphicsCurve(QObject *parent=0) : QmlGraphicsPathElement(parent), _x(0), _y(0) {}
+
+ qreal x() const;
+ void setX(qreal x);
+
+ qreal y() const;
+ void setY(qreal y);
+
+ virtual void addToPath(QPainterPath &) {}
+
+private:
+ qreal _x;
+ qreal _y;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsPathLine : public QmlGraphicsCurve
+{
+ Q_OBJECT
+public:
+ QmlGraphicsPathLine(QObject *parent=0) : QmlGraphicsCurve(parent) {}
+
+ void addToPath(QPainterPath &path);
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsPathQuad : public QmlGraphicsCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY changed)
+ Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY changed)
+public:
+ QmlGraphicsPathQuad(QObject *parent=0) : QmlGraphicsCurve(parent), _controlX(0), _controlY(0) {}
+
+ qreal controlX() const;
+ void setControlX(qreal x);
+
+ qreal controlY() const;
+ void setControlY(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+private:
+ qreal _controlX;
+ qreal _controlY;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsPathCubic : public QmlGraphicsCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY changed)
+ Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY changed)
+ Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY changed)
+ Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY changed)
+public:
+ QmlGraphicsPathCubic(QObject *parent=0) : QmlGraphicsCurve(parent), _control1X(0), _control1Y(0), _control2X(0), _control2Y(0) {}
+
+ qreal control1X() const;
+ void setControl1X(qreal x);
+
+ qreal control1Y() const;
+ void setControl1Y(qreal y);
+
+ qreal control2X() const;
+ void setControl2X(qreal x);
+
+ qreal control2Y() const;
+ void setControl2Y(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+private:
+ int _control1X;
+ int _control1Y;
+ int _control2X;
+ int _control2Y;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsPathPercent : public QmlGraphicsPathElement
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal value READ value WRITE setValue)
+public:
+ QmlGraphicsPathPercent(QObject *parent=0) : QmlGraphicsPathElement(parent) {}
+
+ qreal value() const;
+ void setValue(qreal value);
+
+private:
+ qreal _value;
+};
+
+class QmlGraphicsPathPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsPath : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+
+ Q_INTERFACES(QmlParserStatus)
+ Q_PROPERTY(QList<QmlGraphicsPathElement *>* pathElements READ pathElements)
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX)
+ Q_PROPERTY(qreal startY READ startY WRITE setStartY)
+ Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
+ Q_CLASSINFO("DefaultProperty", "pathElements")
+ Q_INTERFACES(QmlParserStatus)
+public:
+ QmlGraphicsPath(QObject *parent=0);
+ ~QmlGraphicsPath();
+
+ QList<QmlGraphicsPathElement *>* pathElements();
+
+ qreal startX() const;
+ void setStartX(qreal x);
+
+ qreal startY() const;
+ void setStartY(qreal y);
+
+ bool isClosed() const;
+
+ QPainterPath path() const;
+ QStringList attributes() const;
+ qreal attributeAt(const QString &, qreal) const;
+ QPointF pointAt(qreal) const;
+
+Q_SIGNALS:
+ void changed();
+
+protected:
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void processPath();
+
+private:
+ struct AttributePoint {
+ AttributePoint() : percent(0), scale(1), origpercent(0) {}
+ AttributePoint(const AttributePoint &other)
+ : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
+ AttributePoint &operator=(const AttributePoint &other) {
+ percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
+ }
+ qreal percent; //massaged percent along the painter path
+ qreal scale;
+ qreal origpercent; //'real' percent along the painter path
+ QHash<QString, qreal> values;
+ };
+
+ void interpolate(int idx, const QString &name, qreal value);
+ void endpoint(const QString &name);
+ void createPointCache() const;
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsPath)
+ Q_DECLARE_PRIVATE(QmlGraphicsPath)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsPathElement)
+QML_DECLARE_TYPE(QmlGraphicsPathAttribute)
+QML_DECLARE_TYPE(QmlGraphicsCurve)
+QML_DECLARE_TYPE(QmlGraphicsPathLine)
+QML_DECLARE_TYPE(QmlGraphicsPathQuad)
+QML_DECLARE_TYPE(QmlGraphicsPathCubic)
+QML_DECLARE_TYPE(QmlGraphicsPathPercent)
+QML_DECLARE_TYPE(QmlGraphicsPath)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSPATH_H
diff --git a/src/declarative/graphicsitems/qmlgraphicspath_p_p.h b/src/declarative/graphicsitems/qmlgraphicspath_p_p.h
new file mode 100644
index 0000000..04342a8
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspath_p_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSPATH_P_H
+#define QMLGRAPHICSPATH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicspath_p.h"
+
+#include <qml.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+class QmlGraphicsPathPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsPath)
+
+public:
+ QmlGraphicsPathPrivate() : startX(0), startY(0), closed(false) { }
+
+ QPainterPath _path;
+ QList<QmlGraphicsPathElement*> _pathElements;
+ mutable QVector<QPointF> _pointCache;
+ QList<QmlGraphicsPath::AttributePoint> _attributePoints;
+ QStringList _attributes;
+ int startX;
+ int startY;
+ bool closed;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicspathview.cpp b/src/declarative/graphicsitems/qmlgraphicspathview.cpp
new file mode 100644
index 0000000..6718d25
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspathview.cpp
@@ -0,0 +1,976 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicspathview_p.h"
+#include "qmlgraphicspathview_p_p.h"
+
+#include <qmlstate_p.h>
+#include <qmlopenmetaobject_p.h>
+
+#include <QDebug>
+#include <QEvent>
+#include <qlistmodelinterface_p.h>
+#include <QGraphicsSceneEvent>
+
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,PathView,QmlGraphicsPathView)
+
+
+inline qreal qmlMod(qreal x, qreal y)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return fmodf(float(x), float(y));
+ else
+#endif
+ return fmod(x, y);
+}
+
+
+class QmlGraphicsPathViewAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool onPath READ isOnPath NOTIFY onPathChanged)
+public:
+ QmlGraphicsPathViewAttached(QObject *parent)
+ : QObject(parent), mo(new QmlOpenMetaObject(this)), onPath(false)
+ {
+ }
+
+ ~QmlGraphicsPathViewAttached()
+ {
+ QmlGraphicsPathView::attachedProperties.remove(parent());
+ }
+
+ QVariant value(const QByteArray &name) const
+ {
+ return mo->value(name);
+ }
+ void setValue(const QByteArray &name, const QVariant &val)
+ {
+ mo->setValue(name, val);
+ }
+
+ bool isOnPath() const { return onPath; }
+ void setOnPath(bool on) {
+ if (on != onPath) {
+ onPath = on;
+ emit onPathChanged();
+ }
+ }
+
+Q_SIGNALS:
+ void onPathChanged();
+
+private:
+ QmlOpenMetaObject *mo;
+ bool onPath;
+};
+
+
+QmlGraphicsItem *QmlGraphicsPathViewPrivate::getItem(int modelIndex)
+{
+ Q_Q(QmlGraphicsPathView);
+ requestedIndex = modelIndex;
+ QmlGraphicsItem *item = model->item(modelIndex);
+ if (item) {
+ if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
+ static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(true);
+ item->setParentItem(q);
+ }
+ requestedIndex = -1;
+ return item;
+}
+
+void QmlGraphicsPathViewPrivate::releaseItem(QmlGraphicsItem *item)
+{
+ if (!item || !model)
+ return;
+ if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
+ static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(false);
+ if (model->release(item) == 0) {
+ if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
+ static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(false);
+ }
+}
+
+/*!
+ \qmlclass PathView QmlGraphicsPathView
+ \brief The PathView element lays out model-provided items on a path.
+ \inherits Item
+
+ The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML.
+
+ The items are laid out along a path defined by a \l Path and may be flicked to scroll.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
+
+ \image pathview.gif
+
+ \sa Path
+*/
+
+QmlGraphicsPathView::QmlGraphicsPathView(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsPathViewPrivate), parent)
+{
+ Q_D(QmlGraphicsPathView);
+ d->init();
+}
+
+QmlGraphicsPathView::~QmlGraphicsPathView()
+{
+ Q_D(QmlGraphicsPathView);
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlattachedproperty bool PathView::onPath
+ This attached property holds whether the item is currently on the path.
+
+ If a pathItemCount has been set, it is possible that some items may
+ be instantiated, but not considered to be currently on the path.
+ Usually, these items would be set invisible, for example:
+
+ \code
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ ...
+ }
+ }
+ \endcode
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlproperty model PathView::model
+ This property holds the model providing data for the view.
+
+ The model provides a set of data that is used to create the items for the view.
+ For large or dynamic datasets the model is usually provided by a C++ model object.
+ Models can also be created directly in XML, using the ListModel element.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QmlGraphicsPathView::model() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->modelVariant;
+}
+
+void QmlGraphicsPathView::setModel(const QVariant &model)
+{
+ Q_D(QmlGraphicsPathView);
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ for (int i=0; i<d->items.count(); i++){
+ QmlGraphicsItem *p = d->items[i];
+ d->model->release(p);
+ }
+ d->items.clear();
+ }
+
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QmlGraphicsVisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QmlGraphicsVisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ }
+ d->firstIndex = 0;
+ d->pathOffset = 0;
+ d->regenerate();
+ d->fixOffset();
+}
+
+/*!
+ \qmlproperty int PathView::count
+ This property holds the number of items in the model.
+*/
+int QmlGraphicsPathView::count() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->model ? d->model->count() : 0;
+}
+
+/*!
+ \qmlproperty Path PathView::path
+ \default
+ This property holds the path used to lay out the items.
+ For more information see the \l Path documentation.
+*/
+QmlGraphicsPath *QmlGraphicsPathView::path() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->path;
+}
+
+void QmlGraphicsPathView::setPath(QmlGraphicsPath *path)
+{
+ Q_D(QmlGraphicsPathView);
+ d->path = path;
+ connect(d->path, SIGNAL(changed()), this, SLOT(refill()));
+ d->regenerate();
+}
+
+/*!
+ \qmlproperty int PathView::currentIndex
+ This property holds the index of the current item.
+*/
+int QmlGraphicsPathView::currentIndex() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->currentIndex;
+}
+
+void QmlGraphicsPathView::setCurrentIndex(int idx)
+{
+ Q_D(QmlGraphicsPathView);
+ if (d->model && d->model->count())
+ idx = qAbs(idx % d->model->count());
+ if (d->model && idx != d->currentIndex) {
+ d->currentIndex = idx;
+ if (d->model->count()) {
+ d->snapToCurrent();
+ int itemIndex = (idx - d->firstIndex + d->model->count()) % d->model->count();
+ if (itemIndex < d->items.count())
+ d->items.at(itemIndex)->setFocus(true);
+ }
+ emit currentIndexChanged();
+ }
+}
+
+/*!
+ \qmlproperty real PathView::offset
+
+ The offset specifies how far along the path the items are from their initial positions.
+*/
+qreal QmlGraphicsPathView::offset() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->_offset;
+}
+
+void QmlGraphicsPathView::setOffset(qreal offset)
+{
+ Q_D(QmlGraphicsPathView);
+ d->setOffset(offset);
+ d->updateCurrent();
+}
+
+void QmlGraphicsPathViewPrivate::setOffset(qreal o)
+{
+ Q_Q(QmlGraphicsPathView);
+ if (_offset != o) {
+ _offset = qmlMod(o, qreal(100.0));
+ if (_offset < 0)
+ _offset = 100.0 + _offset;
+ q->refill();
+ }
+}
+
+/*!
+ \qmlproperty real PathView::snapPosition
+
+ This property determines the position (0-100) the nearest item will snap to.
+*/
+qreal QmlGraphicsPathView::snapPosition() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->snapPos;
+}
+
+void QmlGraphicsPathView::setSnapPosition(qreal pos)
+{
+ Q_D(QmlGraphicsPathView);
+ d->snapPos = pos/100;
+ d->fixOffset();
+}
+
+/*!
+ \qmlproperty real PathView::dragMargin
+ This property holds the maximum distance from the path that initiate mouse dragging.
+
+ By default the path can only be dragged by clicking on an item. If
+ dragMargin is greater than zero, a drag can be initiated by clicking
+ within dragMargin pixels of the path.
+*/
+qreal QmlGraphicsPathView::dragMargin() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->dragMargin;
+}
+
+void QmlGraphicsPathView::setDragMargin(qreal dragMargin)
+{
+ Q_D(QmlGraphicsPathView);
+ d->dragMargin = dragMargin;
+}
+
+/*!
+ \qmlproperty component PathView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ Note that the PathView will layout the items based on the size of the root
+ item in the delegate.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+QmlComponent *QmlGraphicsPathView::delegate() const
+{
+ Q_D(const QmlGraphicsPathView);
+ if (d->model) {
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QmlGraphicsPathView::setDelegate(QmlComponent *c)
+{
+ Q_D(QmlGraphicsPathView);
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model)) {
+ dataModel->setDelegate(c);
+ d->regenerate();
+ }
+}
+
+/*!
+ \qmlproperty int PathView::pathItemCount
+ This property holds the number of items visible on the path at any one time
+*/
+int QmlGraphicsPathView::pathItemCount() const
+{
+ Q_D(const QmlGraphicsPathView);
+ return d->pathItems;
+}
+
+void QmlGraphicsPathView::setPathItemCount(int i)
+{
+ Q_D(QmlGraphicsPathView);
+ if (i == d->pathItems)
+ return;
+ d->pathItems = i;
+ d->regenerate();
+}
+
+QPointF QmlGraphicsPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
+{
+ //XXX maybe do recursively at increasing resolution.
+ qreal mindist = 1e10; // big number
+ QPointF nearPoint = path->pointAt(0);
+ qreal nearPc = 0;
+ for (qreal i=1; i < 1000; i++) {
+ QPointF pt = path->pointAt(i/1000.0);
+ QPointF diff = pt - point;
+ qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
+ if (dist < mindist) {
+ nearPoint = pt;
+ nearPc = i;
+ mindist = dist;
+ }
+ }
+
+ if (nearPercent)
+ *nearPercent = nearPc / 10.0;
+
+ return nearPoint;
+}
+
+
+void QmlGraphicsPathView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsPathView);
+ if (!d->items.count())
+ return;
+ QPointF scenePoint = mapToScene(event->pos());
+ int idx = 0;
+ for (; idx < d->items.count(); ++idx) {
+ QRectF rect = d->items.at(idx)->boundingRect();
+ rect = d->items.at(idx)->mapToScene(rect).boundingRect();
+ if (rect.contains(scenePoint))
+ break;
+ }
+ if (idx == d->items.count() && d->dragMargin == 0.) // didn't click on an item
+ return;
+
+ d->startPoint = d->pointNear(event->pos(), &d->startPc);
+ if (idx == d->items.count()) {
+ qreal distance = qAbs(event->pos().x() - d->startPoint.x()) + qAbs(event->pos().y() - d->startPoint.y());
+ if (distance > d->dragMargin)
+ return;
+ }
+
+ d->stealMouse = false;
+ d->lastElapsed = 0;
+ d->lastDist = 0;
+ QmlGraphicsItemPrivate::start(d->lastPosTime);
+ d->tl.clear();
+}
+
+void QmlGraphicsPathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsPathView);
+ if (d->lastPosTime.isNull())
+ return;
+
+ if (!d->stealMouse) {
+ QPointF delta = event->pos() - d->startPoint;
+ if (qAbs(delta.x()) > QApplication::startDragDistance() && qAbs(delta.y()) > QApplication::startDragDistance())
+ d->stealMouse = true;
+ }
+
+ if (d->stealMouse) {
+ d->moveReason = QmlGraphicsPathViewPrivate::Mouse;
+ qreal newPc;
+ d->pointNear(event->pos(), &newPc);
+ qreal diff = newPc - d->startPc;
+ if (diff) {
+ setOffset(d->_offset + diff);
+
+ if (diff > 50)
+ diff -= 100;
+ else if (diff < -50)
+ diff += 100;
+
+ d->lastElapsed = QmlGraphicsItemPrivate::restart(d->lastPosTime);
+ d->lastDist = diff;
+ d->startPc = newPc;
+ }
+ }
+}
+
+void QmlGraphicsPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+{
+ Q_D(QmlGraphicsPathView);
+ if (d->lastPosTime.isNull())
+ return;
+
+ qreal elapsed = qreal(d->lastElapsed + QmlGraphicsItemPrivate::elapsed(d->lastPosTime)) / 1000.;
+ qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0;
+ if (d->model && d->model->count() && qAbs(velocity) > 5) {
+ if (velocity > 100)
+ velocity = 100;
+ else if (velocity < -100)
+ velocity = -100;
+ qreal inc = qmlMod(d->_offset - d->snapPos, qreal(100.0 / d->model->count()));
+ qreal dist = qAbs(velocity/2 - qmlMod(velocity/2, qreal(100.0 / d->model->count()) - inc));
+ d->moveOffset.setValue(d->_offset);
+ d->tl.accel(d->moveOffset, velocity, 10, dist);
+ d->tl.execute(d->fixupOffsetEvent);
+ } else {
+ d->fixOffset();
+ }
+
+ d->lastPosTime = QTime();
+ d->stealMouse = false;
+ ungrabMouse();
+}
+
+bool QmlGraphicsPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsPathView);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
+ QGraphicsScene *s = scene();
+ QmlGraphicsItem *grabber = s ? qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem()) : 0;
+ if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ mouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ mousePressEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ mouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem());
+ if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ return d->stealMouse;
+ } else if (!d->lastPosTime.isNull()) {
+ d->lastPosTime = QTime();
+ }
+ return false;
+}
+
+bool QmlGraphicsPathView::sceneEventFilter(QGraphicsItem *i, QEvent *e)
+{
+ if (!isVisible())
+ return QmlGraphicsItem::sceneEventFilter(i, e);
+
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ {
+ bool ret = sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
+ if (e->type() == QEvent::GraphicsSceneMouseRelease)
+ return ret;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return QmlGraphicsItem::sceneEventFilter(i, e);
+}
+
+void QmlGraphicsPathView::componentComplete()
+{
+ Q_D(QmlGraphicsPathView);
+ QmlGraphicsItem::componentComplete();
+ d->regenerate();
+
+ // move to correct offset
+ if (d->items.count()) {
+ int itemIndex = (d->currentIndex - d->firstIndex + d->model->count()) % d->model->count();
+
+ itemIndex += d->pathOffset;
+ itemIndex %= d->items.count();
+ qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0));
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset != d->_offset) {
+ d->moveOffset.setValue(targetOffset);
+ }
+ }
+}
+
+void QmlGraphicsPathViewPrivate::regenerate()
+{
+ Q_Q(QmlGraphicsPathView);
+ if (!q->isComponentComplete())
+ return;
+
+ for (int i=0; i<items.count(); i++){
+ QmlGraphicsItem *p = items[i];
+ releaseItem(p);
+ }
+ items.clear();
+
+ if (!isValid())
+ return;
+
+ if (firstIndex >= model->count())
+ firstIndex = model->count()-1;
+ if (pathOffset >= model->count())
+ pathOffset = model->count()-1;
+
+ int numItems = pathItems >= 0 ? pathItems : model->count();
+ for (int i=0; i < numItems && i < model->count(); ++i){
+ int index = (i + firstIndex) % model->count();
+ QmlGraphicsItem *item = getItem(index);
+ if (!item) {
+ qWarning() << "PathView: Cannot create item, index" << (i + firstIndex) % model->count();
+ return;
+ }
+ items.append(item);
+ item->setZValue(i);
+ if (currentIndex == index)
+ item->setFocus(true);
+ }
+ q->refill();
+}
+
+void QmlGraphicsPathViewPrivate::updateItem(QmlGraphicsItem *item, qreal percent)
+{
+ if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item)) {
+ foreach(const QString &attr, path->attributes())
+ static_cast<QmlGraphicsPathViewAttached *>(obj)->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
+ }
+ QPointF pf = path->pointAt(percent);
+ item->setX(pf.x() - item->width()*item->scale()/2);
+ item->setY(pf.y() - item->height()*item->scale()/2);
+}
+
+void QmlGraphicsPathView::refill()
+{
+ Q_D(QmlGraphicsPathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
+
+ QList<qreal> positions;
+ for (int i=0; i<d->items.count(); i++){
+ qreal percent = i * (100. / d->items.count());
+ percent = percent + d->_offset;
+ percent = qmlMod(percent, qreal(100.0));
+ positions << qAbs(percent/100.0);
+ }
+
+ if (d->pathItems==-1) {
+ for (int i=0; i<positions.count(); i++)
+ d->updateItem(d->items.at(i), positions[i]);
+ return;
+ }
+
+ QList<qreal> rotatedPositions;
+ for (int i=0; i<d->items.count(); i++)
+ rotatedPositions << positions[(i + d->pathOffset + d->items.count()) % d->items.count()];
+
+ int wrapIndex= -1;
+ for (int i=0; i<d->items.count()-1; i++) {
+ if (rotatedPositions[i] > rotatedPositions[i+1]){
+ wrapIndex = i;
+ break;
+ }
+ }
+ if (wrapIndex != -1 ){
+ //A wraparound has occured
+ if (wrapIndex < d->items.count()/2){
+ while(wrapIndex-- >= 0){
+ QmlGraphicsItem* p = d->items.takeFirst();
+ d->updateItem(p, 0.0);
+ d->releaseItem(p);
+ d->firstIndex++;
+ d->firstIndex %= d->model->count();
+ int index = (d->firstIndex + d->items.count())%d->model->count();
+ QmlGraphicsItem *item = d->getItem(index);
+ item->setZValue(wrapIndex);
+ if (d->currentIndex == index)
+ item->setFocus(true);
+ d->items << item;
+ d->pathOffset++;
+ d->pathOffset=d->pathOffset % d->items.count();
+ }
+ } else {
+ while(wrapIndex++ < d->items.count()-1){
+ QmlGraphicsItem* p = d->items.takeLast();
+ d->updateItem(p, 1.0);
+ d->releaseItem(p);
+ d->firstIndex--;
+ if (d->firstIndex < 0)
+ d->firstIndex = d->model->count() - 1;
+ QmlGraphicsItem *item = d->getItem(d->firstIndex);
+ item->setZValue(d->firstIndex);
+ if (d->currentIndex == d->firstIndex)
+ item->setFocus(true);
+ d->items.prepend(item);
+ d->pathOffset--;
+ if (d->pathOffset < 0)
+ d->pathOffset = d->items.count() - 1;
+ }
+ }
+ for (int i=0; i<d->items.count(); i++)
+ rotatedPositions[i] = positions[(i + d->pathOffset + d->items.count())
+ % d->items.count()];
+ }
+ for (int i=0; i<d->items.count(); i++)
+ d->updateItem(d->items.at(i), rotatedPositions[i]);
+}
+
+void QmlGraphicsPathView::itemsInserted(int modelIndex, int count)
+{
+ //XXX support animated insertion
+ Q_D(QmlGraphicsPathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
+ if (d->pathItems == -1) {
+ for (int i = 0; i < count; ++i) {
+ QmlGraphicsItem *item = d->getItem(modelIndex + i);
+ item->setZValue(modelIndex + i);
+ d->items.insert(modelIndex + i, item);
+ }
+ refill();
+ } else {
+ //XXX This is pretty heavy handed until we reference count items.
+ d->regenerate();
+ }
+
+ // make sure the current item is still at the snap position
+ int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
+ itemIndex += d->pathOffset;
+ itemIndex %= d->items.count();
+ qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0));
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset != d->_offset)
+ d->moveOffset.setValue(targetOffset);
+}
+
+void QmlGraphicsPathView::itemsRemoved(int modelIndex, int count)
+{
+ //XXX support animated removal
+ Q_D(QmlGraphicsPathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
+ if (d->pathItems == -1) {
+ for (int i = 0; i < count; ++i) {
+ QmlGraphicsItem* p = d->items.takeAt(modelIndex);
+ d->model->release(p);
+ }
+ d->snapToCurrent();
+ refill();
+ } else {
+ d->regenerate();
+ }
+
+ if (d->model->count() == 0) {
+ d->currentIndex = -1;
+ d->moveOffset.setValue(0);
+ return;
+ }
+
+ // make sure the current item is still at the snap position
+ if (d->currentIndex >= d->model->count())
+ d->currentIndex = d->model->count() - 1;
+ int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
+ itemIndex += d->pathOffset;
+ itemIndex %= d->items.count();
+ qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0));
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset != d->_offset)
+ d->moveOffset.setValue(targetOffset);
+}
+
+void QmlGraphicsPathView::createdItem(int index, QmlGraphicsItem *item)
+{
+ Q_D(QmlGraphicsPathView);
+ if (d->requestedIndex != index) {
+ item->setParentItem(this);
+ d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0);
+ }
+}
+
+void QmlGraphicsPathView::destroyingItem(QmlGraphicsItem *item)
+{
+ Q_UNUSED(item);
+}
+
+void QmlGraphicsPathView::ticked()
+{
+ Q_D(QmlGraphicsPathView);
+ d->updateCurrent();
+}
+
+// find the item closest to the snap position
+int QmlGraphicsPathViewPrivate::calcCurrentIndex()
+{
+ int current = -1;
+ if (model && items.count()) {
+ _offset = qmlMod(_offset, qreal(100.0));
+ if (_offset < 0)
+ _offset += 100.0;
+
+ if (pathItems == -1) {
+ qreal delta = qmlMod(_offset - snapPos, qreal(100.0));
+ if (delta < 0)
+ delta = 100.0 + delta;
+ int ii = model->count() - qRound(delta * model->count() / 100);
+ if (ii < 0)
+ ii = 0;
+ current = ii;
+ } else {
+ qreal bestDiff=1e9;
+ int bestI=-1;
+ for (int i=0; i<items.count(); i++){
+ qreal percent = i * (100. / items.count());
+ percent = percent + _offset;
+ percent = qmlMod(percent, qreal(100.0));
+ qreal diff = qAbs(snapPos - (percent/100.0));
+ if (diff < bestDiff){
+ bestDiff = diff;
+ bestI = i;
+ }
+ }
+ int modelIndex = (bestI - pathOffset + items.count())%items.count();
+ modelIndex += firstIndex;
+ current = modelIndex;
+ }
+ current = qAbs(current % model->count());
+ }
+
+ return current;
+}
+
+void QmlGraphicsPathViewPrivate::updateCurrent()
+{
+ Q_Q(QmlGraphicsPathView);
+ if (moveReason != Mouse)
+ return;
+ int idx = calcCurrentIndex();
+ if (model && idx != currentIndex) {
+ currentIndex = idx;
+ int itemIndex = (idx - firstIndex + model->count()) % model->count();
+ if (itemIndex < items.count())
+ items.at(itemIndex)->setFocus(true);
+ emit q->currentIndexChanged();
+ }
+}
+
+void QmlGraphicsPathViewPrivate::fixOffset()
+{
+ Q_Q(QmlGraphicsPathView);
+ if (model && items.count()) {
+ int curr = calcCurrentIndex();
+ if (curr != currentIndex)
+ q->setCurrentIndex(curr);
+ else
+ snapToCurrent();
+ }
+}
+
+void QmlGraphicsPathViewPrivate::snapToCurrent()
+{
+ if (!model || model->count() <= 0)
+ return;
+
+ int itemIndex = (currentIndex - firstIndex + model->count()) % model->count();
+
+ //Rounds is the number of times round to make the current item visible
+ int rounds = itemIndex / items.count();
+ int otherWayRounds = (model->count() - (itemIndex)) / items.count();
+ if (otherWayRounds < rounds)
+ rounds = -otherWayRounds;
+
+ itemIndex += pathOffset;
+ if(model->count() % items.count() && itemIndex - model->count() + items.count() > 0){
+ //When model.count() is not a multiple of pathItemCount we need to manually
+ //fix the index so that going backwards one step works correctly.
+ itemIndex = itemIndex - model->count() + items.count();
+ }
+ itemIndex %= items.count();
+ qreal targetOffset = qmlMod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), qreal(100.0));
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset == _offset && rounds == 0)
+ return;
+
+ moveReason = Other;
+ tl.clear();
+ moveOffset.setValue(_offset);
+
+ if (rounds!=0){
+ //Compensate if the targetOffset would bring the target in from off the screen
+ qreal distance = targetOffset - _offset;
+ if (distance <= -50)
+ rounds--;
+ if (distance > 50)
+ rounds++;
+ tl.move(moveOffset, targetOffset + 100.0*(-rounds), QEasingCurve(QEasingCurve::InOutQuad),
+ int(100*items.count()*qMax((qreal)(2.0/items.count()),(qreal)qAbs(rounds))));
+ tl.execute(fixupOffsetEvent);
+ return;
+ }
+
+ if (targetOffset - _offset > 50.0) {
+ qreal distance = 100 - targetOffset + _offset;
+ tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * _offset / distance));
+ tl.set(moveOffset, 100.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * (100-targetOffset) / distance));
+ } else if (targetOffset - _offset <= -50.0) {
+ qreal distance = 100 - _offset + targetOffset;
+ tl.move(moveOffset, 100.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * (100-_offset) / distance));
+ tl.set(moveOffset, 0.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * targetOffset / distance));
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+}
+
+QHash<QObject*, QObject*> QmlGraphicsPathView::attachedProperties;
+QObject *QmlGraphicsPathView::qmlAttachedProperties(QObject *obj)
+{
+ QObject *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QmlGraphicsPathViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+}
+
+QT_END_NAMESPACE
+
+#include <qmlgraphicspathview.moc>
diff --git a/src/declarative/graphicsitems/qmlgraphicspathview_p.h b/src/declarative/graphicsitems/qmlgraphicspathview_p.h
new file mode 100644
index 0000000..17106a2
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspathview_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSPATHVIEW_H
+#define QMLGRAPHICSPATHVIEW_H
+
+#include "qmlgraphicsitem.h"
+#include "qmlgraphicspath_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsPathViewPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsPathView : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QmlGraphicsPath *path READ path WRITE setPath)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
+ Q_PROPERTY(qreal snapPosition READ snapPosition WRITE setSnapPosition)
+ Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount)
+
+public:
+ QmlGraphicsPathView(QmlGraphicsItem *parent=0);
+ virtual ~QmlGraphicsPathView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlGraphicsPath *path() const;
+ void setPath(QmlGraphicsPath *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ qreal offset() const;
+ void setOffset(qreal offset);
+
+ qreal snapPosition() const;
+ void setSnapPosition(qreal pos);
+
+ qreal dragMargin() const;
+ void setDragMargin(qreal margin);
+
+ int count() const;
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int pathItemCount() const;
+ void setPathItemCount(int);
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void currentIndexChanged();
+ void offsetChanged();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+ bool sceneEventFilter(QGraphicsItem *, QEvent *);
+ void componentComplete();
+
+private Q_SLOTS:
+ void refill();
+ void ticked();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void createdItem(int index, QmlGraphicsItem *item);
+ void destroyingItem(QmlGraphicsItem *item);
+
+private:
+ friend class QmlGraphicsPathViewAttached;
+ static QHash<QObject*, QObject*> attachedProperties;
+ Q_DISABLE_COPY(QmlGraphicsPathView)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsPathView)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsPathView)
+QML_DECLARE_TYPEINFO(QmlGraphicsPathView, QML_HAS_ATTACHED_PROPERTIES)
+QT_END_HEADER
+
+#endif // QMLGRAPHICSPATHVIEW_H
diff --git a/src/declarative/graphicsitems/qmlgraphicspathview_p_p.h b/src/declarative/graphicsitems/qmlgraphicspathview_p_p.h
new file mode 100644
index 0000000..18cb205
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspathview_p_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSPATHVIEW_P_H
+#define QMLGRAPHICSPATHVIEW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicspathview_p.h"
+
+#include "qmlgraphicsitem_p.h"
+#include "qmlgraphicsvisualitemmodel_p.h"
+
+#include <qml.h>
+#include <qmlanimation_p_p.h>
+
+#include <qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef struct PathViewItem{
+ int index;
+ QmlGraphicsItem* item;
+}PathViewItem;
+
+class QmlGraphicsPathViewPrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsPathView)
+
+public:
+ QmlGraphicsPathViewPrivate()
+ : path(0), currentIndex(0), startPc(0), lastDist(0)
+ , lastElapsed(0), stealMouse(false), ownModel(false), activeItem(0)
+ , snapPos(0), dragMargin(0), moveOffset(this, &QmlGraphicsPathViewPrivate::setOffset)
+ , firstIndex(0), pathItems(-1), pathOffset(0), requestedIndex(-1)
+ , moveReason(Other)
+ {
+ fixupOffsetEvent = QmlTimeLineEvent::timeLineEvent<QmlGraphicsPathViewPrivate, &QmlGraphicsPathViewPrivate::fixOffset>(&moveOffset, this);
+ }
+
+ void init()
+ {
+ Q_Q(QmlGraphicsPathView);
+ _offset = 0;
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemIsFocusScope);
+ q->setFiltersChildEvents(true);
+ q->connect(&tl, SIGNAL(updated()), q, SLOT(ticked()));
+ }
+
+ QmlGraphicsItem *getItem(int modelIndex);
+ void releaseItem(QmlGraphicsItem *item);
+
+ bool isValid() const {
+ return model && model->count() > 0 && model->isValid() && path;
+ }
+
+ int calcCurrentIndex();
+ void updateCurrent();
+ void fixOffset();
+ void setOffset(qreal offset);
+ void regenerate();
+ void updateItem(QmlGraphicsItem *, qreal);
+ void snapToCurrent();
+ QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const;
+
+ QmlGraphicsPath *path;
+ int currentIndex;
+ qreal startPc;
+ QPointF startPoint;
+ qreal lastDist;
+ int lastElapsed;
+ qreal _offset;
+ bool stealMouse : 1;
+ bool ownModel : 1;
+ QTime lastPosTime;
+ QPointF lastPos;
+ QmlGraphicsItem *activeItem;
+ qreal snapPos;
+ qreal dragMargin;
+ QmlTimeLine tl;
+ QmlTimeLineValueProxy<QmlGraphicsPathViewPrivate> moveOffset;
+ QmlTimeLineEvent fixupOffsetEvent;
+ int firstIndex;
+ int pathItems;
+ int pathOffset;
+ int requestedIndex;
+ QList<QmlGraphicsItem *> items;
+ QGuard<QmlGraphicsVisualModel> model;
+ QVariant modelVariant;
+ enum MovementReason { Other, Key, Mouse };
+ MovementReason moveReason;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
new file mode 100644
index 0000000..5b081a2
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
@@ -0,0 +1,851 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicspositioners_p.h"
+#include "qmlgraphicspositioners_p_p.h"
+
+#include <qml.h>
+#include <qmlstate_p.h>
+#include <qmlstategroup_p.h>
+#include <qmlstateoperations_p.h>
+#include <qfxperf_p_p.h>
+#include <QtCore/qmath.h>
+
+#include <QDebug>
+#include <QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+static const QmlGraphicsItemPrivate::ChangeTypes watchedChanges
+ = QmlGraphicsItemPrivate::Geometry
+ | QmlGraphicsItemPrivate::SiblingOrder
+ | QmlGraphicsItemPrivate::Visibility
+ | QmlGraphicsItemPrivate::Opacity
+ | QmlGraphicsItemPrivate::Destroyed;
+
+void QmlGraphicsBasePositionerPrivate::watchChanges(QmlGraphicsItem *other)
+{
+ QmlGraphicsItemPrivate *otherPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(other));
+ otherPrivate->addItemChangeListener(this, watchedChanges);
+}
+
+void QmlGraphicsBasePositionerPrivate::unwatchChanges(QmlGraphicsItem* other)
+{
+ QmlGraphicsItemPrivate *otherPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(other));
+ otherPrivate->removeItemChangeListener(this, watchedChanges);
+}
+
+/*!
+ \internal
+ \class QmlGraphicsBasePositioner
+ \ingroup group_layouts
+ \brief The QmlGraphicsBasePositioner class provides a base for QmlGraphics layouts.
+
+ To create a QmlGraphics Positioner, simply subclass QmlGraphicsBasePositioner and implement
+ doLayout(), which is automatically called when the layout might need
+ updating. In doLayout() use the setX and setY functions from QmlBasePositioner, and the
+ base class will apply the positions along with the appropriate transitions. The items to
+ position are provided in order as the protected member positionedItems.
+
+ You also need to set a PositionerType, to declare whether you are positioning the x, y or both
+ for the child items. Depending on the chosen type, only x or y changes will be applied.
+
+ Note that the subclass is responsible for adding the
+ spacing in between items.
+*/
+QmlGraphicsBasePositioner::QmlGraphicsBasePositioner(PositionerType at, QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsBasePositionerPrivate), parent)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ d->init(at);
+}
+
+QmlGraphicsBasePositioner::QmlGraphicsBasePositioner(QmlGraphicsBasePositionerPrivate &dd, PositionerType at, QmlGraphicsItem *parent)
+ : QmlGraphicsItem(dd, parent)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ d->init(at);
+}
+
+QmlGraphicsBasePositioner::~QmlGraphicsBasePositioner()
+{
+ Q_D(QmlGraphicsBasePositioner);
+ for (int i = 0; i < positionedItems.count(); ++i)
+ d->unwatchChanges(positionedItems.at(i).item);
+ positionedItems.clear();
+}
+
+int QmlGraphicsBasePositioner::spacing() const
+{
+ Q_D(const QmlGraphicsBasePositioner);
+ return d->spacing;
+}
+
+void QmlGraphicsBasePositioner::setSpacing(int s)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ if (s==d->spacing)
+ return;
+ d->spacing = s;
+ prePositioning();
+ emit spacingChanged();
+}
+
+QmlTransition *QmlGraphicsBasePositioner::move() const
+{
+ Q_D(const QmlGraphicsBasePositioner);
+ return d->moveTransition;
+}
+
+void QmlGraphicsBasePositioner::setMove(QmlTransition *mt)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ d->moveTransition = mt;
+}
+
+QmlTransition *QmlGraphicsBasePositioner::add() const
+{
+ Q_D(const QmlGraphicsBasePositioner);
+ return d->addTransition;
+}
+
+void QmlGraphicsBasePositioner::setAdd(QmlTransition *add)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ d->addTransition = add;
+}
+
+void QmlGraphicsBasePositioner::componentComplete()
+{
+ Q_D(QmlGraphicsBasePositioner);
+ QmlGraphicsItem::componentComplete();
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::BasepositionerComponentComplete> cc;
+#endif
+ positionedItems.reserve(d->QGraphicsItemPrivate::children.count());
+ prePositioning();
+}
+
+QVariant QmlGraphicsBasePositioner::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ if (change == ItemChildAddedChange){
+ QGraphicsItem* item = value.value<QGraphicsItem*>();
+ QmlGraphicsItem* child = 0;
+ if(item)
+ child = qobject_cast<QmlGraphicsItem*>(item->toGraphicsObject());
+ if (child)
+ prePositioning();
+ } else if (change == ItemChildRemovedChange) {
+ QGraphicsItem* item = value.value<QGraphicsItem*>();
+ QmlGraphicsItem* child = 0;
+ if(item)
+ child = qobject_cast<QmlGraphicsItem*>(item->toGraphicsObject());
+ if (child) {
+ QmlGraphicsBasePositioner::PositionedItem posItem(child);
+ int idx = positionedItems.find(posItem);
+ if (idx >= 0) {
+ d->unwatchChanges(child);
+ positionedItems.remove(idx);
+ }
+ prePositioning();
+ }
+ }
+
+ return QmlGraphicsItem::itemChange(change, value);
+}
+
+void QmlGraphicsBasePositioner::prePositioning()
+{
+ Q_D(QmlGraphicsBasePositioner);
+ if (!isComponentComplete())
+ return;
+
+ d->queuedPositioning = false;
+ //Need to order children by creation order modified by stacking order
+ QList<QGraphicsItem *> children = d->QGraphicsItemPrivate::children;
+ qSort(children.begin(), children.end(), d->insertionOrder);
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(children.at(ii));
+ if (!child)
+ continue;
+ PositionedItem *item = 0;
+ PositionedItem posItem(child);
+ int wIdx = positionedItems.find(posItem);
+ if (wIdx < 0) {
+ d->watchChanges(child);
+ positionedItems.append(posItem);
+ item = &positionedItems[positionedItems.count()-1];
+ } else {
+ item = &positionedItems[wIdx];
+ }
+ if (child->opacity() <= 0.0 || !child->isVisible()) {
+ item->isVisible = false;
+ continue;
+ }
+ if (!item->isVisible) {
+ item->isVisible = true;
+ item->isNew = true;
+ } else {
+ item->isNew = false;
+ }
+ }
+ doPositioning();
+ if(d->addTransition || d->moveTransition)
+ finishApplyTransitions();
+ //Set implicit size to the size of its children
+ qreal h = 0.0f;
+ qreal w = 0.0f;
+ for (int i = 0; i < positionedItems.count(); ++i) {
+ const PositionedItem &posItem = positionedItems.at(i);
+ if (posItem.isVisible) {
+ h = qMax(h, posItem.item->y() + posItem.item->height());
+ w = qMax(w, posItem.item->x() + posItem.item->width());
+ }
+ }
+ setImplicitHeight(h);
+ setImplicitWidth(w);
+}
+
+void QmlGraphicsBasePositioner::positionX(int x, const PositionedItem &target)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ if(d->type == Horizontal || d->type == Both){
+ if(!d->addTransition && !d->moveTransition){
+ target.item->setX(x);
+ }else{
+ if(target.isNew)
+ d->addActions << QmlAction(target.item, QLatin1String("x"), QVariant(x));
+ else
+ d->moveActions << QmlAction(target.item, QLatin1String("x"), QVariant(x));
+ }
+ }
+}
+
+void QmlGraphicsBasePositioner::positionY(int y, const PositionedItem &target)
+{
+ Q_D(QmlGraphicsBasePositioner);
+ if(d->type == Vertical || d->type == Both){
+ if(!d->addTransition && !d->moveTransition){
+ target.item->setY(y);
+ }else{
+ if(target.isNew)
+ d->addActions << QmlAction(target.item, QLatin1String("y"), QVariant(y));
+ else
+ d->moveActions << QmlAction(target.item, QLatin1String("y"), QVariant(y));
+ }
+ }
+}
+
+void QmlGraphicsBasePositioner::finishApplyTransitions()
+{
+ Q_D(QmlGraphicsBasePositioner);
+ // Note that if a transition is not set the transition manager will
+ // apply the changes directly, in the case add/move aren't set
+ d->addTransitionManager.transition(d->addActions, d->addTransition);
+ d->moveTransitionManager.transition(d->moveActions, d->moveTransition);
+ d->addActions.clear();
+ d->moveActions.clear();
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Column,QmlGraphicsColumn)
+/*!
+ \qmlclass Column QmlGraphicsColumn
+ \brief The Column item lines up its children vertically.
+ \inherits Item
+
+ The Column item positions its child items so that they are vertically
+ aligned and not overlapping. Spacing between items can be added.
+
+ The below example positions differently shaped rectangles using a Column.
+ \table
+ \row
+ \o \image verticalpositioner_example.png
+ \o
+ \qml
+Column {
+ spacing: 2
+ Rectangle { color: "red"; width: 50; height: 50 }
+ Rectangle { color: "green"; width: 20; height: 50 }
+ Rectangle { color: "blue"; width: 50; height: 20 }
+}
+ \endqml
+ \endtable
+
+ Column also provides for transitions to be set when items are added, moved,
+ or removed in the positioner. Adding and removing apply both to items which are deleted
+ or have their position in the document changed so as to no longer be children of the positioner,
+ as well as to items which have their opacity set to or from zero so as to appear or disappear.
+
+ \table
+ \row
+ \o \image verticalpositioner_transition.gif
+ \o
+ \qml
+Column {
+ spacing: 2
+ remove: ...
+ add: ...
+ move: ...
+ ...
+}
+ \endqml
+ \endtable
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, or use anchors on a child of a positioner, then the
+ positioner may exhibit strange behaviour.
+
+*/
+/*!
+ \qmlproperty Transition Column::add
+ This property holds the transition to be applied when adding an item to the positioner. The transition will only be applied to the added item(s).
+ Positioner transitions will only affect the position (x,y) of items.
+
+ Added can mean that either the object has been created or reparented, and thus is now a child or the positioner, or that the object has had its opacity increased from zero, and thus is now visible.
+
+
+*/
+/*!
+ \qmlproperty Transition Column::move
+ This property holds the transition to apply when moving an item within the positioner.
+ Positioner transitions will only affect the position (x,y) of items.
+
+ This can happen when other items are added or removed from the positioner, or when items resize themselves.
+
+ \table
+ \row
+ \o \image positioner-move.gif
+ \o
+ \qml
+Column {
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+ \endtable
+*/
+/*!
+ \qmlproperty int Column::spacing
+
+ spacing is the amount in pixels left empty between each adjacent
+ item, and defaults to 0.
+
+ The below example places a Grid containing a red, a blue and a
+ green rectangle on a gray background. The area the grid positioner
+ occupies is colored white. The top positioner has the default of no spacing,
+ and the bottom positioner has its spacing set to 2.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QmlGraphicsColumn
+ \brief The QmlGraphicsColumn class lines up items vertically.
+ \ingroup group_positioners
+*/
+QmlGraphicsColumn::QmlGraphicsColumn(QmlGraphicsItem *parent)
+: QmlGraphicsBasePositioner(Vertical, parent)
+{
+}
+
+static inline bool isInvisible(QmlGraphicsItem *child)
+{
+ return child->opacity() == 0.0 || !child->isVisible() || !child->width() || !child->height();
+}
+
+void QmlGraphicsColumn::doPositioning()
+{
+ int voffset = 0;
+
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || isInvisible(child.item))
+ continue;
+
+ if(child.item->y() != voffset)
+ positionY(voffset, child);
+
+ voffset += child.item->height();
+ voffset += spacing();
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Row,QmlGraphicsRow)
+/*!
+ \qmlclass Row QmlGraphicsRow
+ \brief The Row item lines up its children horizontally.
+ \inherits Item
+
+ The Row item positions its child items so that they are
+ horizontally aligned and not overlapping. Spacing can be added between the
+ items, and a margin around all items can also be added. It also provides for
+ transitions to be set when items are added, moved, or removed in the
+ positioner. Adding and removing apply both to items which are deleted or have
+ their position in the document changed so as to no longer be children of the
+ positioner, as well as to items which have their opacity set to or from zero
+ so as to appear or disappear.
+
+ The below example lays out differently shaped rectangles using a Row.
+ \qml
+Row {
+ spacing: 2
+ Rectangle { color: "red"; width: 50; height: 50 }
+ Rectangle { color: "green"; width: 20; height: 50 }
+ Rectangle { color: "blue"; width: 50; height: 20 }
+}
+ \endqml
+ \image horizontalpositioner_example.png
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, or use anchors on a child of a positioner, then the
+ positioner may exhibit strange behaviour.
+
+*/
+/*!
+ \qmlproperty Transition Row::add
+ This property holds the transition to apply when adding an item to the positioner.
+ The transition will only be applied to the added item(s).
+ Positioner transitions will only affect the position (x,y) of items.
+
+ Added can mean that either the object has been created or reparented, and thus is now a child or the positioner, or that the object has had its opacity increased from zero, and thus is now visible.
+
+
+*/
+/*!
+ \qmlproperty Transition Row::move
+ This property holds the transition to apply when moving an item within the positioner.
+ Positioner transitions will only affect the position (x,y) of items.
+
+ This can happen when other items are added or removed from the positioner, or when items resize themselves.
+
+ \qml
+Row {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty int Row::spacing
+
+ spacing is the amount in pixels left empty between each adjacent
+ item, and defaults to 0.
+
+ The below example places a Grid containing a red, a blue and a
+ green rectangle on a gray background. The area the grid positioner
+ occupies is colored white. The top positioner has the default of no spacing,
+ and the bottom positioner has its spacing set to 2.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QmlGraphicsRow
+ \brief The QmlGraphicsRow class lines up items horizontally.
+ \ingroup group_positioners
+*/
+QmlGraphicsRow::QmlGraphicsRow(QmlGraphicsItem *parent)
+: QmlGraphicsBasePositioner(Horizontal, parent)
+{
+}
+
+void QmlGraphicsRow::doPositioning()
+{
+ int hoffset = 0;
+
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || isInvisible(child.item))
+ continue;
+
+ if(child.item->x() != hoffset)
+ positionX(hoffset, child);
+
+ hoffset += child.item->width();
+ hoffset += spacing();
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Grid,QmlGraphicsGrid)
+
+/*!
+ \qmlclass Grid QmlGraphicsGrid
+ \brief The Grid item positions its children in a grid.
+ \inherits Item
+
+ The Grid item positions its child items so that they are
+ aligned in a grid and are not overlapping. Spacing can be added
+ between the items. It also provides for transitions to be set when items are
+ added, moved, or removed in the positioner. Adding and removing apply
+ both to items which are deleted or have their position in the
+ document changed so as to no longer be children of the positioner, as
+ well as to items which have their opacity set to or from zero so
+ as to appear or disappear.
+
+ The Grid defaults to using four columns, and as many rows as
+ are necessary to fit all the child items. The number of rows
+ and/or the number of columns can be constrained by setting the rows
+ or columns properties. The grid positioner calculates a grid with
+ rectangular cells of sufficient size to hold all items, and then
+ places the items in the cells, going across then down, and
+ positioning each item at the (0,0) corner of the cell. The below
+ example demonstrates this.
+
+ \table
+ \row
+ \o \image gridLayout_example.png
+ \o
+ \qml
+Grid {
+ columns: 3
+ spacing: 2
+ Rectangle { color: "red"; width: 50; height: 50 }
+ Rectangle { color: "green"; width: 20; height: 50 }
+ Rectangle { color: "blue"; width: 50; height: 20 }
+ Rectangle { color: "cyan"; width: 50; height: 50 }
+ Rectangle { color: "magenta"; width: 10; height: 10 }
+}
+ \endqml
+ \endtable
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, or use anchors on a child of a positioner, then the
+ positioner may exhibit strange behaviour.
+*/
+/*!
+ \qmlproperty Transition Grid::add
+ This property holds the transition to apply when adding an item to the positioner.
+ The transition is only applied to the added item(s).
+ Positioner transitions will only affect the position (x,y) of items.
+
+ Added can mean that either the object has been created or
+ reparented, and thus is now a child or the positioner, or that the
+ object has had its opacity increased from zero, and thus is now
+ visible.
+
+
+*/
+/*!
+ \qmlproperty Transition Grid::move
+ This property holds the transition to apply when moving an item within the positioner.
+ Positioner transitions will only affect the position (x,y) of items.
+
+ This can happen when other items are added or removed from the positioner, or
+ when items resize themselves.
+
+ \qml
+Grid {
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x,y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty int Grid::spacing
+
+ spacing is the amount in pixels left empty between each adjacent
+ item, and defaults to 0.
+
+ The below example places a Grid containing a red, a blue and a
+ green rectangle on a gray background. The area the grid positioner
+ occupies is colored white. The top positioner has the default of no spacing,
+ and the bottom positioner has its spacing set to 2.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QmlGraphicsGrid
+ \brief The QmlGraphicsGrid class lays out items in a grid.
+ \ingroup group_layouts
+
+*/
+QmlGraphicsGrid::QmlGraphicsGrid(QmlGraphicsItem *parent) :
+ QmlGraphicsBasePositioner(Both, parent)
+{
+ _columns=-1;
+ _rows=-1;
+}
+
+/*!
+ \qmlproperty int Grid::columns
+ This property holds the number of columns in the grid.
+
+ When the columns property is set the Grid will always have
+ that many columns. Note that if you do not have enough items to
+ fill this many columns some columns will be of zero width.
+*/
+
+/*!
+ \qmlproperty int Grid::rows
+ This property holds the number of rows in the grid.
+
+ When the rows property is set the Grid will always have that
+ many rows. Note that if you do not have enough items to fill this
+ many rows some rows will be of zero width.
+*/
+
+void QmlGraphicsGrid::doPositioning()
+{
+ int c=_columns,r=_rows;//Actual number of rows/columns
+ int numVisible = positionedItems.count();
+ if (_columns==-1 && _rows==-1){
+ c = 4;
+ r = (numVisible+3)/4;
+ }else if (_rows==-1){
+ r = (numVisible+(_columns-1))/_columns;
+ }else if (_columns==-1){
+ c = (numVisible+(_rows-1))/_rows;
+ }
+
+ QList<int> maxColWidth;
+ QList<int> maxRowHeight;
+ int childIndex =0;
+ for (int i=0; i<r; i++){
+ for (int j=0; j<c; j++){
+ if (j==0)
+ maxRowHeight << 0;
+ if (i==0)
+ maxColWidth << 0;
+
+ if (childIndex == positionedItems.count())
+ continue;
+ const PositionedItem &child = positionedItems.at(childIndex++);
+ if (!child.item || isInvisible(child.item))
+ continue;
+ if (child.item->width() > maxColWidth[j])
+ maxColWidth[j] = child.item->width();
+ if (child.item->height() > maxRowHeight[i])
+ maxRowHeight[i] = child.item->height();
+ }
+ }
+
+ int xoffset=0;
+ int yoffset=0;
+ int curRow =0;
+ int curCol =0;
+ for (int i = 0; i < positionedItems.count(); ++i) {
+ const PositionedItem &child = positionedItems.at(i);
+ if (!child.item || isInvisible(child.item))
+ continue;
+ if((child.item->x()!=xoffset)||(child.item->y()!=yoffset)){
+ positionX(xoffset, child);
+ positionY(yoffset, child);
+ }
+ xoffset+=maxColWidth[curCol]+spacing();
+ curCol++;
+ curCol%=c;
+ if (!curCol){
+ yoffset+=maxRowHeight[curRow]+spacing();
+ xoffset=0;
+ curRow++;
+ if (curRow>=r)
+ break;
+ }
+ }
+}
+
+
+QML_DEFINE_TYPE(Qt,4,6,Flow,QmlGraphicsFlow)
+/*!
+ \qmlclass Flow QmlGraphicsFlow
+ \brief The Flow item lines up its children side by side, wrapping as necessary.
+ \inherits Item
+
+
+*/
+/*!
+ \qmlproperty Transition Flow::add
+ This property holds the transition to apply when adding an item to the positioner.
+ The transition will only be applied to the added item(s).
+ Positioner transitions will only affect the position (x,y) of items.
+
+ Added can mean that either the object has been created or reparented, and thus is now a child or the positioner, or that the object has had its opacity increased from zero, and thus is now visible.
+
+
+*/
+/*!
+ \qmlproperty Transition Flow::move
+ This property holds the transition to apply when moving an item within the positioner.
+ Positioner transitions will only affect the position (x,y) of items.
+
+ This can happen when other items are added or removed from the positioner, or when items resize themselves.
+
+ \qml
+Flow {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x,y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty int Flow::spacing
+
+ spacing is the amount in pixels left empty between each adjacent
+ item, and defaults to 0.
+
+*/
+
+class QmlGraphicsFlowPrivate : public QmlGraphicsBasePositionerPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsFlow)
+
+public:
+ QmlGraphicsFlowPrivate()
+ : QmlGraphicsBasePositionerPrivate(), flow(QmlGraphicsFlow::LeftToRight)
+ {}
+
+ QmlGraphicsFlow::Flow flow;
+};
+
+QmlGraphicsFlow::QmlGraphicsFlow(QmlGraphicsItem *parent)
+: QmlGraphicsBasePositioner(*(new QmlGraphicsFlowPrivate), Both, parent)
+{
+}
+
+/*!
+ \qmlproperty enumeration Flow::flow
+ This property holds the flow of the layout.
+
+ Possible values are \c LeftToRight (default) and \c TopToBottom.
+
+ If \a flow is \c LeftToRight, the items are positioned next to
+ to each other from left to right until the width of the Flow
+ is exceeded, then wrapped to the next line.
+ If \a flow is \c TopToBottom, the items are positioned next to each
+ other from top to bottom until the height of the Flow is exceeded,
+ then wrapped to the next column.
+*/
+QmlGraphicsFlow::Flow QmlGraphicsFlow::flow() const
+{
+ Q_D(const QmlGraphicsFlow);
+ return d->flow;
+}
+
+void QmlGraphicsFlow::setFlow(Flow flow)
+{
+ Q_D(QmlGraphicsFlow);
+ if (d->flow != flow) {
+ d->flow = flow;
+ prePositioning();
+ emit flowChanged();
+ }
+}
+
+void QmlGraphicsFlow::doPositioning()
+{
+ Q_D(QmlGraphicsFlow);
+
+ int hoffset = 0;
+ int voffset = 0;
+ int linemax = 0;
+
+ for (int i = 0; i < positionedItems.count(); ++i) {
+ const PositionedItem &child = positionedItems.at(i);
+ if (!child.item || isInvisible(child.item))
+ continue;
+
+ if (d->flow == LeftToRight) {
+ if (hoffset && hoffset + child.item->width() > width()) {
+ hoffset = 0;
+ voffset += linemax + spacing();
+ linemax = 0;
+ }
+ } else {
+ if (voffset && voffset + child.item->height() > height()) {
+ voffset = 0;
+ hoffset += linemax + spacing();
+ linemax = 0;
+ }
+ }
+
+ if(child.item->x() != hoffset || child.item->y() != voffset){
+ positionX(hoffset, child);
+ positionY(voffset, child);
+ }
+
+ if (d->flow == LeftToRight) {
+ hoffset += child.item->width();
+ hoffset += spacing();
+ linemax = qMax(linemax, qCeil(child.item->height()));
+ } else {
+ voffset += child.item->height();
+ voffset += spacing();
+ linemax = qMax(linemax, qCeil(child.item->width()));
+ }
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners_p.h b/src/declarative/graphicsitems/qmlgraphicspositioners_p.h
new file mode 100644
index 0000000..d6711f6
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspositioners_p.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSLAYOUTS_H
+#define QMLGRAPHICSLAYOUTS_H
+
+#include "qmlgraphicsitem.h"
+
+#include "../util/qmlstate_p.h"
+#include <private/qpodvector_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlGraphicsBasePositionerPrivate;
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsBasePositioner : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+ Q_PROPERTY(QmlTransition *move READ move WRITE setMove)
+ Q_PROPERTY(QmlTransition *add READ add WRITE setAdd)
+public:
+ enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
+ QmlGraphicsBasePositioner(PositionerType, QmlGraphicsItem *parent);
+ ~QmlGraphicsBasePositioner();
+
+ int spacing() const;
+ void setSpacing(int);
+
+ QmlTransition *move() const;
+ void setMove(QmlTransition *);
+
+ QmlTransition *add() const;
+ void setAdd(QmlTransition *);
+
+protected:
+ QmlGraphicsBasePositioner(QmlGraphicsBasePositionerPrivate &dd, PositionerType at, QmlGraphicsItem *parent);
+ virtual void componentComplete();
+ virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
+ void finishApplyTransitions();
+
+Q_SIGNALS:
+ void spacingChanged();
+
+protected Q_SLOTS:
+ virtual void doPositioning()=0;
+ void prePositioning();
+
+protected:
+ struct PositionedItem {
+ PositionedItem(QmlGraphicsItem *i) : item(i), isNew(false), isVisible(true) {}
+ bool operator==(const PositionedItem &other) const { return other.item == item; }
+ QmlGraphicsItem *item;
+ bool isNew;
+ bool isVisible;
+ };
+
+ QPODVector<PositionedItem,8> positionedItems;
+ void positionX(int,const PositionedItem &target);
+ void positionY(int,const PositionedItem &target);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsBasePositioner)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsBasePositioner)
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsColumn : public QmlGraphicsBasePositioner
+{
+ Q_OBJECT
+public:
+ QmlGraphicsColumn(QmlGraphicsItem *parent=0);
+protected Q_SLOTS:
+ virtual void doPositioning();
+private:
+ Q_DISABLE_COPY(QmlGraphicsColumn)
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsRow: public QmlGraphicsBasePositioner
+{
+ Q_OBJECT
+public:
+ QmlGraphicsRow(QmlGraphicsItem *parent=0);
+protected Q_SLOTS:
+ virtual void doPositioning();
+private:
+ Q_DISABLE_COPY(QmlGraphicsRow)
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsGrid : public QmlGraphicsBasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(int rows READ rows WRITE setRows)
+ Q_PROPERTY(int columns READ columns WRITE setcolumns)
+public:
+ QmlGraphicsGrid(QmlGraphicsItem *parent=0);
+
+ int rows() const {return _rows;}
+ void setRows(const int rows){_rows = rows;}
+
+ int columns() const {return _columns;}
+ void setcolumns(const int columns){_columns = columns;}
+protected Q_SLOTS:
+ virtual void doPositioning();
+
+private:
+ int _rows;
+ int _columns;
+ Q_DISABLE_COPY(QmlGraphicsGrid)
+};
+
+class QmlGraphicsFlowPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsFlow: public QmlGraphicsBasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+public:
+ QmlGraphicsFlow(QmlGraphicsItem *parent=0);
+
+ Q_ENUMS(Flow)
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+Q_SIGNALS:
+ void flowChanged();
+
+protected Q_SLOTS:
+ virtual void doPositioning();
+
+protected:
+ QmlGraphicsFlow(QmlGraphicsFlowPrivate &dd, QmlGraphicsItem *parent);
+private:
+ Q_DISABLE_COPY(QmlGraphicsFlow)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsFlow)
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsColumn)
+QML_DECLARE_TYPE(QmlGraphicsRow)
+QML_DECLARE_TYPE(QmlGraphicsGrid)
+QML_DECLARE_TYPE(QmlGraphicsFlow)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h b/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h
new file mode 100644
index 0000000..55a31c7
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSLAYOUTS_P_H
+#define QMLGRAPHICSLAYOUTS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicspositioners_p.h"
+
+#include "qmlgraphicsitem_p.h"
+
+#include <qmlstate_p.h>
+#include <qmltransitionmanager_p_p.h>
+#include <qmlstateoperations_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QTimer>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+class QmlGraphicsBasePositionerPrivate : public QmlGraphicsItemPrivate, public QmlGraphicsItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsBasePositioner)
+
+public:
+ QmlGraphicsBasePositionerPrivate()
+ : spacing(0), type(QmlGraphicsBasePositioner::None), moveTransition(0), addTransition(0),
+ queuedPositioning(false)
+ {
+ }
+
+ void init(QmlGraphicsBasePositioner::PositionerType at)
+ {
+ type = at;
+ }
+
+ int spacing;
+ QmlGraphicsBasePositioner::PositionerType type;
+ QmlTransition *moveTransition;
+ QmlTransition *addTransition;
+ QmlStateOperation::ActionList addActions;
+ QmlStateOperation::ActionList moveActions;
+ QmlTransitionManager addTransitionManager;
+ QmlTransitionManager moveTransitionManager;
+
+ void watchChanges(QmlGraphicsItem *other);
+ void unwatchChanges(QmlGraphicsItem* other);
+ bool queuedPositioning;
+
+ virtual void itemSiblingOrderChanged(QmlGraphicsItem* other)
+ {
+ Q_Q(QmlGraphicsBasePositioner);
+ Q_UNUSED(other);
+ if(!queuedPositioning){
+ //Delay is due to many children often being reordered at once
+ //And we only want to reposition them all once
+ QTimer::singleShot(0,q,SLOT(prePositioning()));
+ queuedPositioning = true;
+ }
+ }
+
+ void itemGeometryChanged(QmlGraphicsItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
+ {
+ Q_Q(QmlGraphicsBasePositioner);
+ if (newGeometry.size() != oldGeometry.size())
+ q->prePositioning();
+ }
+ virtual void itemVisibilityChanged(QmlGraphicsItem *)
+ {
+ Q_Q(QmlGraphicsBasePositioner);
+ q->prePositioning();
+ }
+ virtual void itemOpacityChanged(QmlGraphicsItem *)
+ {
+ Q_Q(QmlGraphicsBasePositioner);
+ q->prePositioning();
+ }
+
+ void itemDestroyed(QmlGraphicsItem *item)
+ {
+ Q_Q(QmlGraphicsBasePositioner);
+ q->positionedItems.removeOne(QmlGraphicsBasePositioner::PositionedItem(item));
+ }
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicsrectangle.cpp b/src/declarative/graphicsitems/qmlgraphicsrectangle.cpp
new file mode 100644
index 0000000..cc09436
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsrectangle.cpp
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsrectangle_p.h"
+#include "qmlgraphicsrectangle_p_p.h"
+
+#include <QPainter>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,Pen,QmlGraphicsPen)
+QML_DEFINE_TYPE(Qt,4,6,GradientStop,QmlGraphicsGradientStop)
+QML_DEFINE_TYPE(Qt,4,6,Gradient,QmlGraphicsGradient)
+
+/*!
+ \internal
+ \class QmlGraphicsPen
+ \brief The QmlGraphicsPen class provides a pen used for drawing rectangle borders on a QmlView.
+
+ By default, the pen is invalid and nothing is drawn. You must either set a color (then the default
+ width is 1) or a width (then the default color is black).
+
+ A width of 1 indicates is a single-pixel line on the border of the item being painted.
+
+ Example:
+ \qml
+ Rectangle { border.width: 2; border.color: "red" ... }
+ \endqml
+*/
+
+void QmlGraphicsPen::setColor(const QColor &c)
+{
+ _color = c;
+ _valid = _color.alpha() ? true : false;
+ emit penChanged();
+}
+
+void QmlGraphicsPen::setWidth(int w)
+{
+ if (_width == w && _valid)
+ return;
+
+ _width = w;
+ _valid = (_width < 1) ? false : true;
+ emit penChanged();
+}
+
+
+/*!
+ \qmlclass GradientStop QmlGraphicsGradientStop
+ \brief The GradientStop item defines the color at a position in a Gradient
+
+ \sa Gradient
+*/
+
+/*!
+ \qmlproperty real GradientStop::position
+ \qmlproperty color GradientStop::color
+
+ Sets a \e color at a \e position in a gradient.
+*/
+
+void QmlGraphicsGradientStop::updateGradient()
+{
+ if (QmlGraphicsGradient *grad = qobject_cast<QmlGraphicsGradient*>(parent()))
+ grad->doUpdate();
+}
+
+/*!
+ \qmlclass Gradient QmlGraphicsGradient
+ \brief The Gradient item defines a gradient fill.
+
+ A gradient is defined by two or more colors, which will be blended seemlessly. The
+ colors are specified at their position in the range 0.0 - 1.0 via
+ the GradientStop item. For example, the following code paints a
+ rectangle with a gradient starting with red, blending to yellow at 1/3 of the
+ size of the rectangle, and ending with Green:
+
+ \table
+ \row
+ \o \image gradient.png
+ \o \quotefile doc/src/snippets/declarative/gradient.qml
+ \endtable
+
+ \sa GradientStop
+*/
+
+/*!
+ \qmlproperty list<GradientStop> Gradient::stops
+ This property holds the gradient stops describing the gradient.
+*/
+
+const QGradient *QmlGraphicsGradient::gradient() const
+{
+ if (!m_gradient && !m_stops.isEmpty()) {
+ m_gradient = new QLinearGradient(0,0,0,1.0);
+ for (int i = 0; i < m_stops.count(); ++i) {
+ const QmlGraphicsGradientStop *stop = m_stops.at(i);
+ m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_gradient->setColorAt(stop->position(), stop->color());
+ }
+ }
+
+ return m_gradient;
+}
+
+void QmlGraphicsGradient::doUpdate()
+{
+ delete m_gradient;
+ m_gradient = 0;
+ emit updated();
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Rectangle,QmlGraphicsRectangle)
+
+/*!
+ \qmlclass Rectangle QmlGraphicsRectangle
+ \brief The Rectangle item allows you to add rectangles to a scene.
+ \inherits Item
+
+ A Rectangle is painted having a solid fill (color) and an optional border.
+ You can also create rounded rectangles using the radius property.
+
+ \qml
+ Rectangle {
+ width: 100
+ height: 100
+ color: "red"
+ border.color: "black"
+ border.width: 5
+ radius: 10
+ }
+ \endqml
+
+ \image declarative-rect.png
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsRectangle
+ \brief The QmlGraphicsRectangle class provides a rectangle item that you can add to a QmlView.
+*/
+QmlGraphicsRectangle::QmlGraphicsRectangle(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsRectanglePrivate), parent)
+{
+ Q_D(QmlGraphicsRectangle);
+ d->init();
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+}
+
+void QmlGraphicsRectangle::doUpdate()
+{
+ Q_D(QmlGraphicsRectangle);
+ d->rectImage = QPixmap();
+ const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
+ d->setPaintMargin((pw+1)/2);
+ update();
+}
+
+/*!
+ \qmlproperty int Rectangle::border.width
+ \qmlproperty color Rectangle::border.color
+
+ The width and color used to draw the border of the rectangle.
+
+ A width of 1 creates a thin line. For no line, use a width of 0 or a transparent color.
+
+ To keep the border smooth (rather than blurry), odd widths cause the rectangle to be painted at
+ a half-pixel offset;
+*/
+QmlGraphicsPen *QmlGraphicsRectangle::border()
+{
+ Q_D(QmlGraphicsRectangle);
+ return d->getPen();
+}
+
+/*!
+ \qmlproperty Gradient Rectangle::gradient
+
+ The gradient to use to fill the rectangle.
+
+ This property allows for the construction of simple vertical gradients.
+ Other gradients may by formed by adding rotation to the rectangle.
+
+ \table
+ \row
+ \o \image declarative-rect_gradient.png
+ \o
+ \qml
+ Rectangle { y: 0; width: 80; height: 80; color: "lightsteelblue" }
+ Rectangle { y: 100; width: 80; height: 80
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightsteelblue" }
+ GradientStop { position: 1.0; color: "blue" }
+ }
+ }
+ Rectangle { rotation: 90; x: 80; y: 200; width: 80; height: 80
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightsteelblue" }
+ GradientStop { position: 1.0; color: "blue" }
+ }
+ }
+ // The x offset is needed because the rotation is from the top left corner
+ \endqml
+ \endtable
+
+ If both a gradient and a color are specified, the gradient will be used.
+
+ \sa Gradient, color
+*/
+QmlGraphicsGradient *QmlGraphicsRectangle::gradient() const
+{
+ Q_D(const QmlGraphicsRectangle);
+ return d->gradient;
+}
+
+void QmlGraphicsRectangle::setGradient(QmlGraphicsGradient *gradient)
+{
+ Q_D(QmlGraphicsRectangle);
+ if (d->gradient == gradient)
+ return;
+ if (d->gradient)
+ disconnect(d->gradient, SIGNAL(updated()), this, SLOT(doUpdate()));
+ d->gradient = gradient;
+ if (d->gradient)
+ connect(d->gradient, SIGNAL(updated()), this, SLOT(doUpdate()));
+ update();
+}
+
+
+/*!
+ \qmlproperty real Rectangle::radius
+ This property holds the corner radius used to draw a rounded rectangle.
+
+ If radius is non-zero, the rectangle will be painted as a rounded rectangle, otherwise it will be
+ painted as a normal rectangle. The same radius is used by all 4 corners; there is currently
+ no way to specify different radii for different corners.
+*/
+qreal QmlGraphicsRectangle::radius() const
+{
+ Q_D(const QmlGraphicsRectangle);
+ return d->radius;
+}
+
+void QmlGraphicsRectangle::setRadius(qreal radius)
+{
+ Q_D(QmlGraphicsRectangle);
+ if (d->radius == radius)
+ return;
+
+ d->radius = radius;
+ d->rectImage = QPixmap();
+ update();
+ emit radiusChanged();
+}
+
+/*!
+ \qmlproperty color Rectangle::color
+ This property holds the color used to fill the rectangle.
+
+ \qml
+ // green rectangle using hexidecimal notation
+ Rectangle { color: "#00FF00" }
+
+ // steelblue rectangle using SVG color name
+ Rectangle { color: "steelblue" }
+ \endqml
+
+ The default color is white.
+
+ If both a gradient and a color are specified, the gradient will be used.
+*/
+QColor QmlGraphicsRectangle::color() const
+{
+ Q_D(const QmlGraphicsRectangle);
+ return d->color;
+}
+
+void QmlGraphicsRectangle::setColor(const QColor &c)
+{
+ Q_D(QmlGraphicsRectangle);
+ if (d->color == c)
+ return;
+
+ d->color = c;
+ d->rectImage = QPixmap();
+ update();
+ emit colorChanged();
+}
+
+void QmlGraphicsRectangle::generateRoundedRect()
+{
+ Q_D(QmlGraphicsRectangle);
+ if (d->rectImage.isNull()) {
+ const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
+ const int radius = qCeil(d->radius); //ensure odd numbered width/height so we get 1-pixel center
+ d->rectImage = QPixmap(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2);
+ d->rectImage.fill(Qt::transparent);
+ QPainter p(&(d->rectImage));
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->pen && d->pen->isValid()) {
+ QPen pn(QColor(d->pen->color()), d->pen->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->color);
+ if (pw%2)
+ p.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, d->rectImage.width()-(pw+1), d->rectImage.height()-(pw+1)), d->radius, d->radius);
+ else
+ p.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, d->rectImage.width()-pw, d->rectImage.height()-pw), d->radius, d->radius);
+ }
+}
+
+void QmlGraphicsRectangle::generateBorderedRect()
+{
+ Q_D(QmlGraphicsRectangle);
+ if (d->rectImage.isNull()) {
+ const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
+ d->rectImage = QPixmap(pw*2 + 3, pw*2 + 3);
+ d->rectImage.fill(Qt::transparent);
+ QPainter p(&(d->rectImage));
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->pen && d->pen->isValid()) {
+ QPen pn(QColor(d->pen->color()), d->pen->width());
+ pn.setJoinStyle(Qt::MiterJoin);
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->color);
+ if (pw%2)
+ p.drawRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, d->rectImage.width()-(pw+1), d->rectImage.height()-(pw+1)));
+ else
+ p.drawRect(QRectF(qreal(pw)/2, qreal(pw)/2, d->rectImage.width()-pw, d->rectImage.height()-pw));
+ }
+}
+
+void QmlGraphicsRectangle::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QmlGraphicsRectangle);
+ if (d->radius > 0 || (d->pen && d->pen->isValid())
+ || (d->gradient && d->gradient->gradient()) ) {
+ drawRect(*p);
+ }
+ else {
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing, true);
+ p->fillRect(QRectF(0, 0, width(), height()), d->color);
+ if (d->smooth)
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ }
+}
+
+void QmlGraphicsRectangle::drawRect(QPainter &p)
+{
+ Q_D(QmlGraphicsRectangle);
+ if (d->gradient && d->gradient->gradient()) {
+ // XXX This path is still slower than the image path
+ // Image path won't work for gradients though
+ bool oldAA = p.testRenderHint(QPainter::Antialiasing);
+ if (d->smooth)
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->pen && d->pen->isValid()) {
+ QPen pn(QColor(d->pen->color()), d->pen->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(*d->gradient->gradient());
+ if (d->radius > 0.)
+ p.drawRoundedRect(0, 0, width(), height(), d->radius, d->radius);
+ else
+ p.drawRect(0, 0, width(), height());
+ if (d->smooth)
+ p.setRenderHint(QPainter::Antialiasing, oldAA);
+ } else {
+ bool oldAA = p.testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p.testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth)
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+
+ const int pw = d->pen && d->pen->isValid() ? (d->pen->width()+1)/2*2 : 0;
+
+ if (d->radius > 0)
+ generateRoundedRect();
+ else
+ generateBorderedRect();
+
+ int xOffset = (d->rectImage.width()-1)/2;
+ int yOffset = (d->rectImage.height()-1)/2;
+ Q_ASSERT(d->rectImage.width() == 2*xOffset + 1);
+ Q_ASSERT(d->rectImage.height() == 2*yOffset + 1);
+
+ QMargins margins(xOffset, yOffset, xOffset, yOffset);
+ QTileRules rules(Qt::StretchTile, Qt::StretchTile);
+ //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects
+ qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width()+pw, height()+pw), margins, d->rectImage, d->rectImage.rect(), margins, rules);
+
+ if (d->smooth) {
+ p.setRenderHint(QPainter::Antialiasing, oldAA);
+ p.setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ }
+}
+
+/*!
+ \qmlproperty bool Rectangle::smooth
+
+ Set this property if you want the item to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+
+ \image rect-smooth.png
+*/
+
+QRectF QmlGraphicsRectangle::boundingRect() const
+{
+ Q_D(const QmlGraphicsRectangle);
+ return QRectF(-d->paintmargin, -d->paintmargin, d->width+d->paintmargin*2, d->height+d->paintmargin*2);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsrectangle_p.h b/src/declarative/graphicsitems/qmlgraphicsrectangle_p.h
new file mode 100644
index 0000000..4f4c1cf
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsrectangle_p.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSRECT_H
+#define QMLGRAPHICSRECT_H
+
+#include "qmlgraphicsitem.h"
+
+#include <QtGui/qbrush.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QmlGraphicsPen : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int width READ width WRITE setWidth NOTIFY penChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY penChanged)
+public:
+ QmlGraphicsPen(QObject *parent=0)
+ : QObject(parent), _width(1), _color("#000000"), _valid(false)
+ {}
+
+ int width() const { return _width; }
+ void setWidth(int w);
+
+ QColor color() const { return _color; }
+ void setColor(const QColor &c);
+
+ bool isValid() { return _valid; };
+
+Q_SIGNALS:
+ void penChanged();
+
+private:
+ int _width;
+ QColor _color;
+ bool _valid;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsGradientStop : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal position READ position WRITE setPosition)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+
+public:
+ QmlGraphicsGradientStop(QObject *parent=0) : QObject(parent) {}
+
+ qreal position() const { return m_position; }
+ void setPosition(qreal position) { m_position = position; updateGradient(); }
+
+ QColor color() const { return m_color; }
+ void setColor(const QColor &color) { m_color = color; updateGradient(); }
+
+private:
+ void updateGradient();
+
+private:
+ qreal m_position;
+ QColor m_color;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsGradient : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QList<QmlGraphicsGradientStop *> *stops READ stops)
+ Q_CLASSINFO("DefaultProperty", "stops")
+
+public:
+ QmlGraphicsGradient(QObject *parent=0) : QObject(parent), m_gradient(0) {}
+ ~QmlGraphicsGradient() { delete m_gradient; }
+
+ QList<QmlGraphicsGradientStop *> *stops() { return &m_stops; }
+
+ const QGradient *gradient() const;
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ void doUpdate();
+
+private:
+ QList<QmlGraphicsGradientStop *> m_stops;
+ mutable QGradient *m_gradient;
+ friend class QmlGraphicsGradientStop;
+};
+
+class QmlGraphicsRectanglePrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsRectangle : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QmlGraphicsGradient *gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(QmlGraphicsPen * border READ border CONSTANT)
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+public:
+ QmlGraphicsRectangle(QmlGraphicsItem *parent=0);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QmlGraphicsPen *border();
+
+ QmlGraphicsGradient *gradient() const;
+ void setGradient(QmlGraphicsGradient *gradient);
+
+ qreal radius() const;
+ void setRadius(qreal radius);
+
+ QRectF boundingRect() const;
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+Q_SIGNALS:
+ void colorChanged();
+ void radiusChanged();
+
+private Q_SLOTS:
+ void doUpdate();
+
+private:
+ void generateRoundedRect();
+ void generateBorderedRect();
+ void drawRect(QPainter &painter);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsRectangle)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsRectangle)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsPen)
+QML_DECLARE_TYPE(QmlGraphicsGradientStop)
+QML_DECLARE_TYPE(QmlGraphicsGradient)
+QML_DECLARE_TYPE(QmlGraphicsRectangle)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSRECT_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsrectangle_p_p.h b/src/declarative/graphicsitems/qmlgraphicsrectangle_p_p.h
new file mode 100644
index 0000000..c4bbbe4
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsrectangle_p_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSRECT_P_H
+#define QMLGRAPHICSRECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsGradient;
+class QmlGraphicsRectangle;
+class QmlGraphicsRectanglePrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsRectangle)
+
+public:
+ QmlGraphicsRectanglePrivate() :
+ color(Qt::white), gradient(0), pen(0), radius(0), paintmargin(0)
+ {
+ }
+
+ ~QmlGraphicsRectanglePrivate()
+ {
+ delete pen;
+ }
+
+ void init()
+ {
+ }
+
+ QColor getColor();
+ QColor color;
+ QmlGraphicsGradient *gradient;
+ QmlGraphicsPen *getPen() {
+ if (!pen) {
+ Q_Q(QmlGraphicsRectangle);
+ pen = new QmlGraphicsPen;
+ QObject::connect(pen, SIGNAL(penChanged()), q, SLOT(doUpdate()));
+ }
+ return pen;
+ }
+ QmlGraphicsPen *pen;
+ qreal radius;
+ qreal paintmargin;
+ QPixmap rectImage;
+
+ void setPaintMargin(qreal margin)
+ {
+ Q_Q(QmlGraphicsRectangle);
+ if (margin == paintmargin)
+ return;
+ q->prepareGeometryChange();
+ paintmargin = margin;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSRECT_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsrepeater.cpp b/src/declarative/graphicsitems/qmlgraphicsrepeater.cpp
new file mode 100644
index 0000000..99f0faa
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsrepeater.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsrepeater_p.h"
+#include "qmlgraphicsrepeater_p_p.h"
+
+#include "qmlgraphicsvisualitemmodel_p.h"
+
+#include <qmllistaccessor_p.h>
+
+#include <qlistmodelinterface_p.h>
+
+QT_BEGIN_NAMESPACE
+QmlGraphicsRepeaterPrivate::QmlGraphicsRepeaterPrivate()
+: model(0), ownModel(false)
+{
+}
+
+QmlGraphicsRepeaterPrivate::~QmlGraphicsRepeaterPrivate()
+{
+ if (ownModel)
+ delete model;
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Repeater,QmlGraphicsRepeater)
+
+/*!
+ \qmlclass Repeater QmlGraphicsRepeater
+ \inherits Item
+
+ \brief The Repeater item allows you to repeat a component based on a model.
+
+ The Repeater item is used when you want to create a large number of
+ similar items. For each entry in the model, an item is instantiated
+ in a context seeded with data from the model. If the repeater will
+ be instantiating a large number of instances, it may be more efficient to
+ use one of Qt Declarative's \l {xmlViews}{view items}.
+
+ The model may be either an object list, a string list, a number or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component.
+
+ The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes. The
+ following example shows how to use the index property inside the instantiated
+ items.
+
+ \snippet doc/src/snippets/declarative/repeater-index.qml 0
+
+ \image repeater-index.png
+
+ Items instantiated by the Repeater are inserted, in order, as
+ children of the Repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This is to allow
+ you to use a Repeater inside a layout. The following QML example shows how
+ the instantiated items would visually appear stacked between the red and
+ blue rectangles.
+
+ \snippet doc/src/snippets/declarative/repeater.qml 0
+
+ \image repeater.png
+
+ The repeater instance continues to own all items it instantiates, even
+ if they are otherwise manipulated. It is illegal to manually remove an item
+ created by the Repeater.
+ */
+
+/*!
+ \internal
+ \class QmlGraphicsRepeater
+ \qmlclass Repeater
+
+ XXX Repeater is very conservative in how it instatiates/deletes items. Also
+ new model entries will not be created and old ones will not be removed.
+ */
+
+/*!
+ Create a new QmlGraphicsRepeater instance.
+ */
+QmlGraphicsRepeater::QmlGraphicsRepeater(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsRepeaterPrivate), parent)
+{
+}
+
+/*!
+ Destroy the repeater instance. All items it instantiated are also
+ destroyed.
+ */
+QmlGraphicsRepeater::~QmlGraphicsRepeater()
+{
+}
+
+/*!
+ \qmlproperty any Repeater::model
+
+ The model providing data for the repeater.
+
+ The model may be either an object list, a string list, a number or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component. The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes.
+
+ As a special case the model can also be merely a number. In this case it will
+ create that many instances of the component. They will also be assigned an index
+ based on the order they are created.
+
+ Models can also be created directly in QML, using a \l{ListModel} or \l{XmlListModel}.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QmlGraphicsRepeater::model() const
+{
+ Q_D(const QmlGraphicsRepeater);
+ return d->dataSource;
+}
+
+void QmlGraphicsRepeater::setModel(const QVariant &model)
+{
+ Q_D(QmlGraphicsRepeater);
+ clear();
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ /*
+ disconnect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QmlGraphicsItem*)), this, SLOT(destroyingItem(QmlGraphicsItem*)));
+ */
+ }
+ d->dataSource = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QmlGraphicsVisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QmlGraphicsVisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ /*
+ connect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QmlGraphicsItem*)), this, SLOT(destroyingItem(QmlGraphicsItem*)));
+ */
+ regenerate();
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component Repeater::delegate
+ \default
+
+ The delegate provides a template defining each item instantiated by the repeater.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+ */
+QmlComponent *QmlGraphicsRepeater::delegate() const
+{
+ Q_D(const QmlGraphicsRepeater);
+ if (d->model) {
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QmlGraphicsRepeater::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QmlGraphicsRepeater);
+ if (!d->ownModel) {
+ d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model)) {
+ dataModel->setDelegate(delegate);
+ regenerate();
+ }
+}
+
+/*!
+ \qmlproperty int Repeater::count
+
+ This property holds the number of items in the repeater.
+*/
+int QmlGraphicsRepeater::count() const
+{
+ Q_D(const QmlGraphicsRepeater);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+
+/*!
+ \internal
+ */
+void QmlGraphicsRepeater::componentComplete()
+{
+ QmlGraphicsItem::componentComplete();
+ regenerate();
+}
+
+/*!
+ \internal
+ */
+QVariant QmlGraphicsRepeater::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ QVariant rv = QmlGraphicsItem::itemChange(change, value);
+ if (change == ItemParentHasChanged) {
+ regenerate();
+ }
+
+ return rv;
+}
+
+void QmlGraphicsRepeater::clear()
+{
+ Q_D(QmlGraphicsRepeater);
+ if (d->model) {
+ foreach (QmlGraphicsItem *item, d->deletables) {
+ item->setParentItem(this);
+ d->model->release(item);
+ }
+ }
+ d->deletables.clear();
+}
+
+/*!
+ \internal
+ */
+void QmlGraphicsRepeater::regenerate()
+{
+ Q_D(QmlGraphicsRepeater);
+
+ clear();
+
+ if (!d->model || !d->model->count() || !d->model->isValid() || !parentItem() || !isComponentComplete())
+ return;
+
+ for (int ii = 0; ii < count(); ++ii) {
+ QmlGraphicsItem *item = d->model->item(ii);
+ if (item) {
+ item->setParent(parentItem());
+ item->stackBefore(this);
+ d->deletables << item;
+ }
+ }
+}
+
+void QmlGraphicsRepeater::itemsInserted(int, int)
+{
+ regenerate();
+}
+
+void QmlGraphicsRepeater::itemsRemoved(int, int)
+{
+ regenerate();
+}
+
+void QmlGraphicsRepeater::itemsMoved(int,int,int)
+{
+ regenerate();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsrepeater_p.h b/src/declarative/graphicsitems/qmlgraphicsrepeater_p.h
new file mode 100644
index 0000000..61f82d7
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsrepeater_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSREPEATER_H
+#define QMLGRAPHICSREPEATER_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsRepeaterPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsRepeater : public QmlGraphicsItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+
+public:
+ QmlGraphicsRepeater(QmlGraphicsItem *parent=0);
+ virtual ~QmlGraphicsRepeater();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int count() const;
+
+Q_SIGNALS:
+ void countChanged();
+
+private:
+ void clear();
+ void regenerate();
+
+protected:
+ virtual void componentComplete();
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+private Q_SLOTS:
+ void itemsInserted(int,int);
+ void itemsRemoved(int,int);
+ void itemsMoved(int,int,int);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsRepeater)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsRepeater)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsRepeater)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSREPEATER_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsrepeater_p_p.h b/src/declarative/graphicsitems/qmlgraphicsrepeater_p_p.h
new file mode 100644
index 0000000..e6d7bfd
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsrepeater_p_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSREPEATER_P_H
+#define QMLGRAPHICSREPEATER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsrepeater_p.h"
+
+#include "qmlgraphicsitem_p.h"
+
+#include <QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QmlGraphicsVisualModel;
+class QmlGraphicsRepeaterPrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsRepeater)
+
+public:
+ QmlGraphicsRepeaterPrivate();
+ ~QmlGraphicsRepeaterPrivate();
+
+ QmlGraphicsVisualModel *model;
+ QVariant dataSource;
+ bool ownModel;
+
+ QList<QPointer<QmlGraphicsItem> > deletables;
+};
+
+QT_END_NAMESPACE
+#endif // QMLGRAPHICSREPEATER_P_H
diff --git a/src/declarative/graphicsitems/qmlgraphicsscalegrid.cpp b/src/declarative/graphicsitems/qmlgraphicsscalegrid.cpp
new file mode 100644
index 0000000..f50b79b
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsscalegrid.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsscalegrid_p_p.h"
+
+#include <qml.h>
+
+#include <QBuffer>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+/*!
+ \internal
+ \class QmlGraphicsScaleGrid
+ \brief The QmlGraphicsScaleGrid class allows you to specify a 3x3 grid to use in scaling an image.
+*/
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsScaleGrid)
+
+QmlGraphicsScaleGrid::QmlGraphicsScaleGrid(QObject *parent) : QObject(parent), _left(0), _top(0), _right(0), _bottom(0)
+{
+}
+
+QmlGraphicsScaleGrid::~QmlGraphicsScaleGrid()
+{
+}
+
+bool QmlGraphicsScaleGrid::isNull() const
+{
+ return !_left && !_top && !_right && !_bottom;
+}
+
+void QmlGraphicsScaleGrid::setLeft(int pos)
+{
+ if (_left != pos) {
+ _left = pos;
+ emit borderChanged();
+ }
+}
+
+void QmlGraphicsScaleGrid::setTop(int pos)
+{
+ if (_top != pos) {
+ _top = pos;
+ emit borderChanged();
+ }
+}
+
+void QmlGraphicsScaleGrid::setRight(int pos)
+{
+ if (_right != pos) {
+ _right = pos;
+ emit borderChanged();
+ }
+}
+
+void QmlGraphicsScaleGrid::setBottom(int pos)
+{
+ if (_bottom != pos) {
+ _bottom = pos;
+ emit borderChanged();
+ }
+}
+
+QmlGraphicsGridScaledImage::QmlGraphicsGridScaledImage()
+: _l(-1), _r(-1), _t(-1), _b(-1),
+ _h(QmlGraphicsBorderImage::Stretch), _v(QmlGraphicsBorderImage::Stretch)
+{
+}
+
+QmlGraphicsGridScaledImage::QmlGraphicsGridScaledImage(const QmlGraphicsGridScaledImage &o)
+: _l(o._l), _r(o._r), _t(o._t), _b(o._b), _h(o._h), _v(o._v), _pix(o._pix)
+{
+}
+
+QmlGraphicsGridScaledImage &QmlGraphicsGridScaledImage::operator=(const QmlGraphicsGridScaledImage &o)
+{
+ _l = o._l;
+ _r = o._r;
+ _t = o._t;
+ _b = o._b;
+ _h = o._h;
+ _v = o._v;
+ _pix = o._pix;
+ return *this;
+}
+
+QmlGraphicsGridScaledImage::QmlGraphicsGridScaledImage(QIODevice *data)
+: _l(-1), _r(-1), _t(-1), _b(-1), _h(QmlGraphicsBorderImage::Stretch), _v(QmlGraphicsBorderImage::Stretch)
+{
+ int l = -1;
+ int r = -1;
+ int t = -1;
+ int b = -1;
+ QString imgFile;
+
+ while(!data->atEnd()) {
+ QString line = QString::fromUtf8(data->readLine().trimmed());
+ if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
+ continue;
+
+ QStringList list = line.split(QLatin1Char(':'));
+ if (list.count() != 2)
+ return;
+
+ list[0] = list[0].trimmed();
+ list[1] = list[1].trimmed();
+
+ if (list[0] == QLatin1String("border.left"))
+ l = list[1].toInt();
+ else if (list[0] == QLatin1String("border.right"))
+ r = list[1].toInt();
+ else if (list[0] == QLatin1String("border.top"))
+ t = list[1].toInt();
+ else if (list[0] == QLatin1String("border.bottom"))
+ b = list[1].toInt();
+ else if (list[0] == QLatin1String("source"))
+ imgFile = list[1];
+ else if (list[0] == QLatin1String("horizontalTileRule"))
+ _h = stringToRule(list[1]);
+ else if (list[0] == QLatin1String("verticalTileRule"))
+ _v = stringToRule(list[1]);
+ }
+
+ if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty())
+ return;
+
+ _l = l; _r = r; _t = t; _b = b;
+
+ _pix = imgFile;
+}
+
+QmlGraphicsBorderImage::TileMode QmlGraphicsGridScaledImage::stringToRule(const QString &s)
+{
+ if (s == QLatin1String("Stretch"))
+ return QmlGraphicsBorderImage::Stretch;
+ if (s == QLatin1String("Repeat"))
+ return QmlGraphicsBorderImage::Repeat;
+ if (s == QLatin1String("Round"))
+ return QmlGraphicsBorderImage::Round;
+
+ qWarning() << "Unknown tile rule specified. Using Stretch";
+ return QmlGraphicsBorderImage::Stretch;
+}
+
+bool QmlGraphicsGridScaledImage::isValid() const
+{
+ return _l >= 0;
+}
+
+int QmlGraphicsGridScaledImage::gridLeft() const
+{
+ return _l;
+}
+
+int QmlGraphicsGridScaledImage::gridRight() const
+{
+ return _r;
+}
+
+int QmlGraphicsGridScaledImage::gridTop() const
+{
+ return _t;
+}
+
+int QmlGraphicsGridScaledImage::gridBottom() const
+{
+ return _b;
+}
+
+QString QmlGraphicsGridScaledImage::pixmapUrl() const
+{
+ return _pix;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsscalegrid_p_p.h b/src/declarative/graphicsitems/qmlgraphicsscalegrid_p_p.h
new file mode 100644
index 0000000..88938a7
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsscalegrid_p_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSSCALEGRID_H
+#define QMLGRAPHICSSCALEGRID_H
+
+#include "qmlgraphicsborderimage_p.h"
+
+#include "../util/qmlpixmapcache_p.h"
+#include <qml.h>
+
+#include <QtCore/QString>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsScaleGrid : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(TileRule)
+
+ Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged)
+ Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged)
+ Q_PROPERTY(int right READ right WRITE setRight NOTIFY borderChanged)
+ Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY borderChanged)
+
+public:
+ QmlGraphicsScaleGrid(QObject *parent=0);
+ ~QmlGraphicsScaleGrid();
+
+ bool isNull() const;
+
+ int left() const { return _left; }
+ void setLeft(int);
+
+ int top() const { return _top; }
+ void setTop(int);
+
+ int right() const { return _right; }
+ void setRight(int);
+
+ int bottom() const { return _bottom; }
+ void setBottom(int);
+
+Q_SIGNALS:
+ void borderChanged();
+
+private:
+ int _left;
+ int _top;
+ int _right;
+ int _bottom;
+};
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsGridScaledImage
+{
+public:
+ QmlGraphicsGridScaledImage();
+ QmlGraphicsGridScaledImage(const QmlGraphicsGridScaledImage &);
+ QmlGraphicsGridScaledImage(QIODevice*);
+ QmlGraphicsGridScaledImage &operator=(const QmlGraphicsGridScaledImage &);
+ bool isValid() const;
+ int gridLeft() const;
+ int gridRight() const;
+ int gridTop() const;
+ int gridBottom() const;
+ QmlGraphicsBorderImage::TileMode horizontalTileRule() const { return _h; }
+ QmlGraphicsBorderImage::TileMode verticalTileRule() const { return _v; }
+
+ QString pixmapUrl() const;
+
+private:
+ static QmlGraphicsBorderImage::TileMode stringToRule(const QString &);
+
+private:
+ int _l;
+ int _r;
+ int _t;
+ int _b;
+ QmlGraphicsBorderImage::TileMode _h;
+ QmlGraphicsBorderImage::TileMode _v;
+ QString _pix;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsScaleGrid)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSSCALEGRID_H
diff --git a/src/declarative/graphicsitems/qmlgraphicstext.cpp b/src/declarative/graphicsitems/qmlgraphicstext.cpp
new file mode 100644
index 0000000..b13fb7c
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstext.cpp
@@ -0,0 +1,927 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicstext_p.h"
+#include "qmlgraphicstext_p_p.h"
+#include <qmlstyledtext_p.h>
+
+#include <qfxperf_p_p.h>
+
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QGraphicsSceneMouseEvent>
+#include <QPainter>
+#include <QAbstractTextDocumentLayout>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,Text,QmlGraphicsText)
+
+/*!
+ \qmlclass Text QmlGraphicsText
+ \brief The Text item allows you to add formatted text to a scene.
+ \inherits Item
+
+ It can display both plain and rich text. For example:
+
+ \qml
+ Text { text: "Hello World!"; font.family: "Helvetica"; font.pointSize: 24; color: "red" }
+ Text { text: "<b>Hello</b> <i>World!</i>" }
+ \endqml
+
+ \image declarative-text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \c wrap is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \c elide property can alternatively be used to fit a single line of
+ plain text to a set width.
+
+ Text provides read-only text. For editable text, see \l TextEdit.
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsText
+ \qmlclass Text
+ \ingroup group_coreitems
+
+ \brief The QmlGraphicsText class provides a formatted text item that you can add to a QmlView.
+
+ Text was designed for read-only text; it does not allow for any text editing.
+ It can display both plain and rich text. For example:
+
+ \qml
+ Text { text: "Hello World!"; font.family: "Helvetica"; font.pointSize: 24; color: "red" }
+ Text { text: "<b>Hello</b> <i>World!</i>" }
+ \endqml
+
+ \image text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \c wrap is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \c elide property can alternatively be used to fit a line of plain text to a set width.
+
+ A QmlGraphicsText object can be instantiated in Qml using the tag \c Text.
+*/
+QmlGraphicsText::QmlGraphicsText(QmlGraphicsItem *parent)
+ : QmlGraphicsItem(*(new QmlGraphicsTextPrivate), parent)
+{
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+}
+
+QmlGraphicsText::~QmlGraphicsText()
+{
+}
+
+
+QmlGraphicsTextPrivate::~QmlGraphicsTextPrivate()
+{
+}
+
+/*!
+ \qmlproperty string Text::font.family
+ \qmlproperty bool Text::font.bold
+ \qmlproperty bool Text::font.italic
+ \qmlproperty bool Text::font.underline
+ \qmlproperty real Text::font.pointSize
+ \qmlproperty int Text::font.pixelSize
+
+ Set the Text's font attributes.
+*/
+QFont QmlGraphicsText::font() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->font;
+}
+
+void QmlGraphicsText::setFont(const QFont &font)
+{
+ Q_D(QmlGraphicsText);
+ if (d->font == font)
+ return;
+
+ d->font = font;
+
+ d->updateLayout();
+ d->markImgDirty();
+ emit fontChanged(d->font);
+}
+
+void QmlGraphicsText::setText(const QString &n)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::QmlGraphicsText_setText> st;
+#endif
+ Q_D(QmlGraphicsText);
+ if (d->text == n)
+ return;
+
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
+ if (d->richText) {
+ if (!d->doc) {
+ d->doc = new QTextDocument(this);
+ d->doc->setDocumentMargin(0);
+ }
+ d->doc->setHtml(n);
+ }
+
+ d->text = n;
+ d->updateLayout();
+ d->markImgDirty();
+ emit textChanged(d->text);
+}
+
+/*!
+ \qmlproperty string Text::text
+
+ The text to display. Text supports both plain and rich text strings.
+
+ The item will try to automatically determine whether the text should
+ be treated as rich text. This determination is made using Qt::mightBeRichText().
+*/
+QString QmlGraphicsText::text() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->text;
+}
+
+void QmlGraphicsText::setColor(const QColor &color)
+{
+ Q_D(QmlGraphicsText);
+ if (d->color == color)
+ return;
+
+ d->color = color;
+ d->markImgDirty();
+ emit colorChanged(d->color);
+}
+
+/*!
+ \qmlproperty color Text::color
+
+ The text color.
+
+ \qml
+ //green text using hexadecimal notation
+ Text { color: "#00FF00"; ... }
+
+ //steelblue text using SVG color name
+ Text { color: "steelblue"; ... }
+ \endqml
+*/
+
+QColor QmlGraphicsText::color() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->color;
+}
+
+/*!
+ \qmlproperty enumeration Text::style
+
+ Set an additional text style.
+
+ Supported text styles are \c Normal, \c Outline, \c Raised and \c Sunken.
+
+ \qml
+ Row {
+ Text { font.pointSize: 24; text: "Normal" }
+ Text { font.pointSize: 24; text: "Raised"; style: Text.Raised; styleColor: "#AAAAAA" }
+ Text { font.pointSize: 24; text: "Outline"; style: Text.Outline; styleColor: "red" }
+ Text { font.pointSize: 24; text: "Sunken"; style: Text.Sunken; styleColor: "#AAAAAA" }
+ }
+ \endqml
+
+ \image declarative-textstyle.png
+*/
+QmlGraphicsText::TextStyle QmlGraphicsText::style() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->style;
+}
+
+void QmlGraphicsText::setStyle(QmlGraphicsText::TextStyle style)
+{
+ Q_D(QmlGraphicsText);
+ if (d->style == style)
+ return;
+
+ d->style = style;
+ d->markImgDirty();
+ emit styleChanged(d->style);
+}
+
+void QmlGraphicsText::setStyleColor(const QColor &color)
+{
+ Q_D(QmlGraphicsText);
+ if (d->styleColor == color)
+ return;
+
+ d->styleColor = color;
+ d->markImgDirty();
+ emit styleColorChanged(d->styleColor);
+}
+
+/*!
+ \qmlproperty color Text::styleColor
+
+ Defines the secondary color used by text styles.
+
+ \c styleColor is used as the outline color for outlined text, and as the
+ shadow color for raised or sunken text. If no style has been set, it is not
+ used at all.
+ */
+QColor QmlGraphicsText::styleColor() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->styleColor;
+}
+
+/*!
+ \qmlproperty enumeration Text::horizontalAlignment
+ \qmlproperty enumeration Text::verticalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the Text items
+ width and height. By default, the text is top-left aligned.
+
+ The valid values for \c horizontalAlignment are \c AlignLeft, \c AlignRight and
+ \c AlignHCenter. The valid values for \c verticalAlignment are \c AlignTop, \c AlignBottom
+ and \c AlignVCenter.
+*/
+QmlGraphicsText::HAlignment QmlGraphicsText::hAlign() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->hAlign;
+}
+
+void QmlGraphicsText::setHAlign(HAlignment align)
+{
+ Q_D(QmlGraphicsText);
+ if (d->hAlign == align)
+ return;
+
+ d->hAlign = align;
+ emit horizontalAlignmentChanged(align);
+}
+
+QmlGraphicsText::VAlignment QmlGraphicsText::vAlign() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->vAlign;
+}
+
+void QmlGraphicsText::setVAlign(VAlignment align)
+{
+ Q_D(QmlGraphicsText);
+ if (d->vAlign == align)
+ return;
+
+ d->vAlign = align;
+ emit verticalAlignmentChanged(align);
+}
+
+/*!
+ \qmlproperty bool Text::wrap
+
+ Set this property to wrap the text to the Text item's width. The text will only
+ wrap if an explicit width has been set.
+
+ Wrapping is done on word boundaries (i.e. it is a "word-wrap"). If the text cannot be
+ word-wrapped to the specified width it will be partially drawn outside of the item's bounds.
+ If this is undesirable then enable clipping on the item (Item::clip).
+
+ Wrapping is off by default.
+*/
+//### Future may provide choice of wrap modes, such as QTextOption::WrapAtWordBoundaryOrAnywhere
+bool QmlGraphicsText::wrap() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->wrap;
+}
+
+void QmlGraphicsText::setWrap(bool w)
+{
+ Q_D(QmlGraphicsText);
+ if (w == d->wrap)
+ return;
+
+ d->wrap = w;
+
+ d->updateLayout();
+ d->markImgDirty();
+ emit wrapChanged(d->wrap);
+}
+
+/*!
+ \qmlproperty enumeration Text::textFormat
+
+ The way the text property should be displayed.
+
+ Supported text formats are \c AutoText, \c PlainText, \c RichText and \c StyledText
+
+ The default is AutoText. If the text format is AutoText the text element
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ StyledText is an optimized format supporting some basic text
+ styling markup, in the style of html 3.2:
+
+ \code
+ <font size="4" color="#ff0000">font size and color</font>
+ <b>bold</b>
+ <i>italic</i>
+ <br>
+ &gt; &lt; &amp;
+ \endcode
+
+ \c StyledText parser is strict, requiring tags to be correctly nested.
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ TextEdit {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: "RichText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: "PlainText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+
+QmlGraphicsText::TextFormat QmlGraphicsText::textFormat() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->format;
+}
+
+void QmlGraphicsText::setTextFormat(TextFormat format)
+{
+ Q_D(QmlGraphicsText);
+ if (format == d->format)
+ return;
+ d->format = format;
+ bool wasRich = d->richText;
+ d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (wasRich && !d->richText) {
+ //### delete control? (and vice-versa below)
+ d->updateLayout();
+ d->markImgDirty();
+ } else if (!wasRich && d->richText) {
+ if (!d->doc) {
+ d->doc = new QTextDocument(this);
+ d->doc->setDocumentMargin(0);
+ }
+ d->doc->setHtml(d->text);
+ d->updateLayout();
+ d->markImgDirty();
+ }
+
+ emit textFormatChanged(d->format);
+}
+
+/*!
+ \qmlproperty enumeration Text::elide
+
+ Set this property to elide parts of the text fit to the Text item's width.
+ The text will only elide if an explicit width has been set.
+
+ This property cannot be used with wrap enabled or with rich text.
+
+ Eliding can be \c ElideNone (the default), \c ElideLeft, \c ElideMiddle, or \c ElideRight.
+
+ If the text is a multi-length string, and the mode is not \c ElideNone,
+ the first string that fits will be used, otherwise the last will be elided.
+
+ Multi-length strings are ordered from longest to shortest, separated by the
+ Unicode "String Terminator" character \c U009C (write this in QML with \c{"\u009C"} or \c{"\x9C"}).
+*/
+QmlGraphicsText::TextElideMode QmlGraphicsText::elideMode() const
+{
+ Q_D(const QmlGraphicsText);
+ return d->elideMode;
+}
+
+void QmlGraphicsText::setElideMode(QmlGraphicsText::TextElideMode mode)
+{
+ Q_D(QmlGraphicsText);
+ if (mode == d->elideMode)
+ return;
+
+ d->elideMode = mode;
+
+ d->updateLayout();
+ d->markImgDirty();
+ emit elideModeChanged(d->elideMode);
+}
+
+void QmlGraphicsText::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QmlGraphicsText);
+ if (newGeometry.width() != oldGeometry.width()) {
+ if (d->wrap || d->elideMode != QmlGraphicsText::ElideNone) {
+ //re-elide if needed
+ if (d->singleline && d->elideMode != QmlGraphicsText::ElideNone &&
+ isComponentComplete() && widthValid()) {
+
+ QFontMetrics fm(d->font);
+ QString tmp = fm.elidedText(d->text,(Qt::TextElideMode)d->elideMode,width()); // XXX still worth layout...?
+ d->layout.setText(tmp);
+ }
+
+ d->imgDirty = true;
+ d->updateSize();
+ }
+ }
+ QmlGraphicsItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void QmlGraphicsTextPrivate::updateLayout()
+{
+ Q_Q(QmlGraphicsText);
+ if (q->isComponentComplete()) {
+ //setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ layout.clearLayout();
+ layout.setFont(font);
+ if (format != QmlGraphicsText::StyledText) {
+ QString tmp = text;
+ tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ singleline = !tmp.contains(QChar::LineSeparator);
+ if (singleline && elideMode != QmlGraphicsText::ElideNone && q->widthValid()) {
+ QFontMetrics fm(font);
+ tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...?
+ }
+ layout.setText(tmp);
+ } else {
+ singleline = false;
+ QmlStyledText::parse(text, layout);
+ }
+ }
+ updateSize();
+ } else {
+ dirty = true;
+ }
+}
+
+void QmlGraphicsTextPrivate::updateSize()
+{
+ Q_Q(QmlGraphicsText);
+ if (q->isComponentComplete()) {
+ QFontMetrics fm(font);
+ if (text.isEmpty()) {
+ q->setImplicitHeight(fm.height());
+ return;
+ }
+
+ int dy = q->height();
+ QSize size(0, 0);
+
+ //setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ size = setupTextLayout(&layout);
+ cachedLayoutSize = size;
+ dy -= size.height();
+ } else {
+ singleline = false; // richtext can't elide or be optimized for single-line case
+ doc->setDefaultFont(font);
+ QTextOption option((Qt::Alignment)int(hAlign | vAlign));
+ if (wrap)
+ option.setWrapMode(QTextOption::WordWrap);
+ else
+ option.setWrapMode(QTextOption::NoWrap);
+ doc->setDefaultTextOption(option);
+ if (wrap && !q->heightValid() && q->widthValid())
+ doc->setTextWidth(q->width());
+ else
+ doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
+ dy -= (int)doc->size().height();
+ }
+ int yoff = 0;
+
+ if (q->heightValid()) {
+ if (vAlign == QmlGraphicsText::AlignBottom)
+ yoff = dy;
+ else if (vAlign == QmlGraphicsText::AlignVCenter)
+ yoff = dy/2;
+ }
+ q->setBaselineOffset(fm.ascent() + yoff);
+
+ //### need to comfirm cost of always setting these for richText
+ q->setImplicitWidth(richText ? (int)doc->idealWidth() : size.width());
+ q->setImplicitHeight(richText ? (int)doc->size().height() : size.height());
+ } else {
+ dirty = true;
+ }
+}
+
+// ### text layout handling should be profiled and optimized as needed
+// what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
+
+void QmlGraphicsTextPrivate::drawOutline()
+{
+ QPixmap img = QPixmap(imgStyleCache.width()+2,imgStyleCache.height()+2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ QPoint pos(imgCache.rect().topLeft());
+ pos += QPoint(-1, 0);
+ ppm.drawPixmap(pos, imgStyleCache);
+ pos += QPoint(2, 0);
+ ppm.drawPixmap(pos, imgStyleCache);
+ pos += QPoint(-1, -1);
+ ppm.drawPixmap(pos, imgStyleCache);
+ pos += QPoint(0, 2);
+ ppm.drawPixmap(pos, imgStyleCache);
+
+ pos += QPoint(0, -1);
+ ppm.drawPixmap(pos, imgCache);
+ ppm.end();
+
+ imgCache = img;
+}
+
+void QmlGraphicsTextPrivate::drawOutline(int yOffset)
+{
+ QPixmap img = QPixmap(imgStyleCache.width()+2,imgStyleCache.height()+2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ QPoint pos(imgCache.rect().topLeft());
+ pos += QPoint(0, yOffset);
+ ppm.drawPixmap(pos, imgStyleCache);
+
+ pos += QPoint(0, -yOffset);
+ ppm.drawPixmap(pos, imgCache);
+ ppm.end();
+
+ imgCache = img;
+}
+
+QSize QmlGraphicsTextPrivate::setupTextLayout(QTextLayout *layout)
+{
+ Q_Q(QmlGraphicsText);
+ layout->setCacheEnabled(true);
+
+ int height = 0;
+ qreal widthUsed = 0;
+ qreal lineWidth = 0;
+
+ //set manual width
+ if ((wrap || elideMode != QmlGraphicsText::ElideNone) && q->widthValid())
+ lineWidth = q->width();
+
+ layout->beginLayout();
+
+ while (1) {
+ QTextLine line = layout->createLine();
+ if (!line.isValid())
+ break;
+
+ if ((wrap || elideMode != QmlGraphicsText::ElideNone) && q->widthValid())
+ line.setLineWidth(lineWidth);
+ }
+ layout->endLayout();
+
+ int x = 0;
+ for (int i = 0; i < layout->lineCount(); ++i) {
+ QTextLine line = layout->lineAt(i);
+ widthUsed = qMax(widthUsed, line.naturalTextWidth());
+ line.setPosition(QPointF(0, height));
+ height += int(line.height());
+
+ if (!cache) {
+ if (hAlign == QmlGraphicsText::AlignLeft) {
+ x = 0;
+ } else if (hAlign == QmlGraphicsText::AlignRight) {
+ x = q->width() - (int)line.naturalTextWidth();
+ } else if (hAlign == QmlGraphicsText::AlignHCenter) {
+ x = (q->width() - (int)line.naturalTextWidth()) / 2;
+ }
+ line.setPosition(QPoint(x, (int)line.y()));
+ }
+ }
+
+ return QSize(qCeil(widthUsed), height);
+}
+
+QPixmap QmlGraphicsTextPrivate::wrappedTextImage(bool drawStyle)
+{
+ //do layout
+ QSize size = cachedLayoutSize;
+
+ int x = 0;
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ if (hAlign == QmlGraphicsText::AlignLeft) {
+ x = 0;
+ } else if (hAlign == QmlGraphicsText::AlignRight) {
+ x = size.width() - (int)line.naturalTextWidth();
+ } else if (hAlign == QmlGraphicsText::AlignHCenter) {
+ x = (size.width() - (int)line.naturalTextWidth()) / 2;
+ }
+ line.setPosition(QPoint(x, (int)line.y()));
+ }
+
+ //paint text
+ QPixmap img(size);
+ if (!size.isEmpty()) {
+ img.fill(Qt::transparent);
+ QPainter p(&img);
+ drawWrappedText(&p, QPointF(0,0), drawStyle);
+ }
+ return img;
+}
+
+void QmlGraphicsTextPrivate::drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle)
+{
+ if (drawStyle)
+ p->setPen(styleColor);
+ else
+ p->setPen(color);
+ p->setFont(font);
+ layout.draw(p, pos);
+}
+
+QPixmap QmlGraphicsTextPrivate::richTextImage(bool drawStyle)
+{
+ QSize size = doc->size().toSize();
+
+ //paint text
+ QPixmap img(size);
+ img.fill(Qt::transparent);
+ QPainter p(&img);
+
+ QAbstractTextDocumentLayout::PaintContext context;
+
+ if (drawStyle) {
+ context.palette.setColor(QPalette::Text, styleColor);
+ // ### Do we really want this?
+ QTextOption colorOption;
+ colorOption.setFlags(QTextOption::SuppressColors);
+ doc->setDefaultTextOption(colorOption);
+ } else {
+ context.palette.setColor(QPalette::Text, color);
+ }
+ doc->documentLayout()->draw(&p, context);
+ if (drawStyle)
+ doc->setDefaultTextOption(QTextOption());
+ return img;
+}
+
+void QmlGraphicsTextPrivate::checkImgCache()
+{
+ if (!imgDirty)
+ return;
+
+ bool empty = text.isEmpty();
+ if (empty) {
+ imgCache = QPixmap();
+ imgStyleCache = QPixmap();
+ } else if (richText) {
+ imgCache = richTextImage(false);
+ if (style != QmlGraphicsText::Normal)
+ imgStyleCache = richTextImage(true); //### should use styleColor
+ } else {
+ imgCache = wrappedTextImage(false);
+ if (style != QmlGraphicsText::Normal)
+ imgStyleCache = wrappedTextImage(true); //### should use styleColor
+ }
+ if (!empty)
+ switch (style) {
+ case QmlGraphicsText::Outline:
+ drawOutline();
+ break;
+ case QmlGraphicsText::Sunken:
+ drawOutline(-1);
+ break;
+ case QmlGraphicsText::Raised:
+ drawOutline(1);
+ break;
+ default:
+ break;
+ }
+
+ imgDirty = false;
+}
+
+void QmlGraphicsText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QmlGraphicsText);
+
+ if (d->cache || d->richText || d->style != Normal) {
+ d->checkImgCache();
+ if (d->imgCache.isNull())
+ return;
+
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+
+ int w = width();
+ int h = height();
+
+ int x = 0;
+ int y = 0;
+
+ switch (d->hAlign) {
+ case AlignLeft:
+ x = 0;
+ break;
+ case AlignRight:
+ x = w - d->imgCache.width();
+ break;
+ case AlignHCenter:
+ x = (w - d->imgCache.width()) / 2;
+ break;
+ }
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->imgCache.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->imgCache.height()) / 2;
+ break;
+ }
+
+ bool needClip = !clip() && (d->imgCache.width() > width() ||
+ d->imgCache.height() > height());
+
+ if (needClip) {
+ p->save();
+ p->setClipRect(boundingRect(), Qt::IntersectClip);
+ }
+ p->drawPixmap(x, y, d->imgCache);
+ if (needClip)
+ p->restore();
+
+ if (d->smooth) {
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ } else {
+ int h = height();
+ int y = 0;
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->cachedLayoutSize.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->cachedLayoutSize.height()) / 2;
+ break;
+ }
+ bool needClip = !clip() && (d->cachedLayoutSize.width() > width() ||
+ d->cachedLayoutSize.height() > height());
+
+ if (needClip) {
+ p->save();
+ p->setClipRect(boundingRect(), Qt::IntersectClip);
+ }
+ d->drawWrappedText(p, QPointF(0,y), false);
+ if (needClip)
+ p->restore();
+ }
+}
+
+/*!
+ \qmlproperty bool Text::smooth
+
+ Set this property if you want the text to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+void QmlGraphicsText::componentComplete()
+{
+ Q_D(QmlGraphicsText);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::TextComponentComplete> cc;
+#endif
+ QmlGraphicsItem::componentComplete();
+ if (d->dirty) {
+ d->updateLayout();
+ d->dirty = false;
+ }
+}
+
+/*!
+ \overload
+ Handles the given mouse \a event.
+ */
+void QmlGraphicsText::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsText);
+
+ if (!d->richText || !d->doc || d->doc->documentLayout()->anchorAt(event->pos()).isEmpty()) {
+ event->setAccepted(false);
+ d->activeLink = QString();
+ } else {
+ d->activeLink = d->doc->documentLayout()->anchorAt(event->pos());
+ }
+
+ // ### may malfunction if two of the same links are clicked & dragged onto each other)
+
+ if (!event->isAccepted())
+ QmlGraphicsItem::mousePressEvent(event);
+
+}
+
+/*!
+ \qmlsignal Text::linkActivated(link)
+
+ This handler is called when the user clicks on a link embedded in the text.
+*/
+
+/*!
+ \overload
+ Handles the given mouse \a event.
+ */
+void QmlGraphicsText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsText);
+
+ // ### confirm the link, and send a signal out
+ if (d->richText && d->doc && d->activeLink == d->doc->documentLayout()->anchorAt(event->pos()))
+ emit linkActivated(d->activeLink);
+ else
+ event->setAccepted(false);
+
+ if (!event->isAccepted())
+ QmlGraphicsItem::mouseReleaseEvent(event);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicstext_p.h b/src/declarative/graphicsitems/qmlgraphicstext_p.h
new file mode 100644
index 0000000..8fa2e65
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstext_p.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSTEXT_H
+#define QMLGRAPHICSTEXT_H
+
+#include "qmlgraphicsitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlGraphicsTextPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsText : public QmlGraphicsItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(TextStyle)
+ Q_ENUMS(TextFormat)
+ Q_ENUMS(TextElideMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(TextStyle style READ style WRITE setStyle NOTIFY styleChanged)
+ Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor NOTIFY styleColorChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged) //### there are several wrap modes in Qt
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
+ Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode?
+
+public:
+ QmlGraphicsText(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsText();
+
+ enum HAlignment { AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter };
+ enum VAlignment { AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter };
+ enum TextStyle { Normal,
+ Outline,
+ Raised,
+ Sunken };
+ enum TextFormat { PlainText = Qt::PlainText,
+ RichText = Qt::RichText,
+ AutoText = Qt::AutoText,
+ StyledText = 4 };
+ enum TextElideMode { ElideLeft = Qt::ElideLeft,
+ ElideRight = Qt::ElideRight,
+ ElideMiddle = Qt::ElideMiddle,
+ ElideNone = Qt::ElideNone };
+
+ QString text() const;
+ void setText(const QString &);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ TextStyle style() const;
+ void setStyle(TextStyle style);
+
+ QColor styleColor() const;
+ void setStyleColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ bool wrap() const;
+ void setWrap(bool w);
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ TextElideMode elideMode() const;
+ void setElideMode(TextElideMode);
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void textChanged(const QString &text);
+ void linkActivated(const QString &link);
+ void fontChanged(const QFont &font);
+ void colorChanged(const QColor &color);
+ void styleChanged(TextStyle style);
+ void styleColorChanged(const QColor &color);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+ void wrapChanged(bool wrap);
+ void textFormatChanged(TextFormat textFormat);
+ void elideModeChanged(TextElideMode mode);
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsText)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsText)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsText)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicstext_p_p.h b/src/declarative/graphicsitems/qmlgraphicstext_p_p.h
new file mode 100644
index 0000000..1e29e58
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstext_p_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSTEXT_P_H
+#define QMLGRAPHICSTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem.h"
+#include "qmlgraphicsitem_p.h"
+
+#include <qml.h>
+
+#include <QtGui/qtextlayout.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTextLayout;
+class QTextDocument;
+
+class QmlGraphicsTextPrivate : public QmlGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsText)
+public:
+ QmlGraphicsTextPrivate()
+ : color((QRgb)0), style(QmlGraphicsText::Normal), imgDirty(true),
+ hAlign(QmlGraphicsText::AlignLeft), vAlign(QmlGraphicsText::AlignTop), elideMode(QmlGraphicsText::ElideNone),
+ dirty(true), wrap(false), richText(false), singleline(false), cache(true), doc(0),
+ format(QmlGraphicsText::AutoText)
+ {
+#ifdef QML_NO_TEXT_CACHE
+ cache = false;
+#endif
+ }
+
+ ~QmlGraphicsTextPrivate();
+
+ void updateSize();
+ void updateLayout();
+ void markImgDirty() {
+ Q_Q(QmlGraphicsText);
+ imgDirty = true;
+ if (q->isComponentComplete())
+ q->update();
+ }
+ void checkImgCache();
+
+ void drawOutline();
+ void drawOutline(int yOffset);
+
+ QPixmap wrappedTextImage(bool drawStyle);
+ void drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle);
+ QPixmap richTextImage(bool drawStyle);
+ QSize setupTextLayout(QTextLayout *layout);
+
+ QString text;
+ QFont font;
+ QColor color;
+ QmlGraphicsText::TextStyle style;
+ QColor styleColor;
+ QString activeLink;
+ bool imgDirty;
+ QPixmap imgCache;
+ QPixmap imgStyleCache;
+ QmlGraphicsText::HAlignment hAlign;
+ QmlGraphicsText::VAlignment vAlign;
+ QmlGraphicsText::TextElideMode elideMode;
+ bool dirty:1;
+ bool wrap:1;
+ bool richText:1;
+ bool singleline:1;
+ bool cache:1;
+ QTextDocument *doc;
+ QTextLayout layout;
+ QSize cachedLayoutSize;
+ QmlGraphicsText::TextFormat format;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicstextedit.cpp b/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
new file mode 100644
index 0000000..fc80258
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
@@ -0,0 +1,1035 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicstextedit_p.h"
+#include "qmlgraphicstextedit_p_p.h"
+
+#include "qmlgraphicsevents_p_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QGraphicsSceneMouseEvent>
+#include <QDebug>
+#include <QPainter>
+
+#include <private/qtextcontrol_p.h>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,TextEdit,QmlGraphicsTextEdit)
+
+/*!
+ \qmlclass TextEdit QmlGraphicsTextEdit
+ \brief The TextEdit item allows you to add editable formatted text to a scene.
+
+ It can display both plain and rich text. For example:
+
+ \qml
+TextEdit {
+ id: edit
+ text: "<b>Hello</b> <i>World!</i>"
+ focus: true
+ font.family: "Helvetica"
+ font.pointSize: 20
+ color: "blue"
+ width: 240
+}
+ \endqml
+
+ \image declarative-textedit.gif
+
+ \sa Text
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsTextEdit
+ \qmlclass TextEdit
+ \ingroup group_coreitems
+
+ \brief The QmlGraphicsTextEdit class provides an editable formatted text item that you can add to a QmlView.
+
+ It can display both plain and rich text.
+
+ \image declarative-textedit.png
+
+ A QmlGraphicsTextEdit object can be instantiated in Qml using the tag \c &lt;TextEdit&gt;.
+*/
+
+/*!
+ Constructs a new QmlGraphicsTextEdit.
+*/
+QmlGraphicsTextEdit::QmlGraphicsTextEdit(QmlGraphicsItem *parent)
+: QmlGraphicsPaintedItem(*(new QmlGraphicsTextEditPrivate), parent)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->init();
+}
+
+QString QmlGraphicsTextEdit::text() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+
+ if (d->richText)
+ return d->document->toHtml();
+ else
+ return d->document->toPlainText();
+}
+
+/*!
+ \qmlproperty string TextEdit::font.family
+ \qmlproperty bool TextEdit::font.bold
+ \qmlproperty bool TextEdit::font.italic
+ \qmlproperty bool TextEdit::font.underline
+ \qmlproperty real TextEdit::font.pointSize
+ \qmlproperty int TextEdit::font.pixelSize
+
+ Set the TextEdit's font attributes.
+*/
+
+/*!
+ \qmlproperty string TextEdit::text
+
+ The text to display. If the text format is AutoText the text edit will
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+*/
+void QmlGraphicsTextEdit::setText(const QString &text)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (QmlGraphicsTextEdit::text() == text)
+ return;
+ d->text = text;
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
+ if (d->richText) {
+ d->control->setHtml(text);
+ } else {
+ d->control->setPlainText(text);
+ }
+ q_textChanged();
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::textFormat
+
+ The way the text property should be displayed.
+
+ Supported text formats are \c AutoText, \c PlainText and \c RichText.
+
+ The default is AutoText. If the text format is AutoText the text edit
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ TextEdit {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: "RichText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: "PlainText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+QmlGraphicsTextEdit::TextFormat QmlGraphicsTextEdit::textFormat() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->format;
+}
+
+void QmlGraphicsTextEdit::setTextFormat(TextFormat format)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (format == d->format)
+ return;
+ bool wasRich = d->richText;
+ d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (wasRich && !d->richText) {
+ d->control->setPlainText(d->text);
+ updateSize();
+ } else if (!wasRich && d->richText) {
+ d->control->setHtml(d->text);
+ updateSize();
+ }
+ d->format = format;
+ emit textFormatChanged(d->format);
+}
+
+QFont QmlGraphicsTextEdit::font() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->font;
+}
+
+void QmlGraphicsTextEdit::setFont(const QFont &font)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->font = font;
+
+ clearCache();
+ d->document->setDefaultFont(d->font);
+ if(d->cursor){
+ d->cursor->setHeight(QFontMetrics(d->font).height());
+ moveCursorDelegate();
+ }
+ updateSize();
+ update();
+}
+
+/*!
+ \qmlproperty color TextEdit::color
+
+ The text color.
+
+ \qml
+// green text using hexadecimal notation
+TextEdit { color: "#00FF00"; ... }
+
+// steelblue text using SVG color name
+TextEdit { color: "steelblue"; ... }
+ \endqml
+*/
+QColor QmlGraphicsTextEdit::color() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->color;
+}
+
+void QmlGraphicsTextEdit::setColor(const QColor &color)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->color == color)
+ return;
+
+ clearCache();
+ d->color = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Text, color);
+ d->control->setPalette(pal);
+ update();
+ emit colorChanged(d->color);
+}
+
+/*!
+ \qmlproperty color TextEdit::selectionColor
+
+ The text highlight color, used behind selections.
+*/
+QColor QmlGraphicsTextEdit::selectionColor() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->selectionColor;
+}
+
+void QmlGraphicsTextEdit::setSelectionColor(const QColor &color)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->selectionColor == color)
+ return;
+
+ clearCache();
+ d->selectionColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Highlight, color);
+ d->control->setPalette(pal);
+ update();
+ emit selectionColorChanged(d->selectionColor);
+}
+
+/*!
+ \qmlproperty color TextEdit::selectedTextColor
+
+ The selected text color, used in selections.
+*/
+QColor QmlGraphicsTextEdit::selectedTextColor() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->selectedTextColor;
+}
+
+void QmlGraphicsTextEdit::setSelectedTextColor(const QColor &color)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->selectedTextColor == color)
+ return;
+
+ clearCache();
+ d->selectedTextColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::HighlightedText, color);
+ d->control->setPalette(pal);
+ update();
+ emit selectedTextColorChanged(d->selectedTextColor);
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::horizontalAlignment
+ \qmlproperty enumeration TextEdit::verticalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the TextEdit items
+ width and height. By default, the text is top-left aligned.
+
+ The valid values for \c horizontalAlignment are \c AlignLeft, \c AlignRight and
+ \c AlignHCenter. The valid values for \c verticalAlignment are \c AlignTop, \c AlignBottom
+ and \c AlignVCenter.
+*/
+QmlGraphicsTextEdit::HAlignment QmlGraphicsTextEdit::hAlign() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->hAlign;
+}
+
+void QmlGraphicsTextEdit::setHAlign(QmlGraphicsTextEdit::HAlignment alignment)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (alignment == d->hAlign)
+ return;
+ d->hAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+ emit horizontalAlignmentChanged(d->hAlign);
+}
+
+QmlGraphicsTextEdit::VAlignment QmlGraphicsTextEdit::vAlign() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->vAlign;
+}
+
+void QmlGraphicsTextEdit::setVAlign(QmlGraphicsTextEdit::VAlignment alignment)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (alignment == d->vAlign)
+ return;
+ d->vAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+ emit verticalAlignmentChanged(d->vAlign);
+}
+
+bool QmlGraphicsTextEdit::wrap() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->wrap;
+}
+
+/*!
+ \qmlproperty bool TextEdit::wrap
+
+ Set this property to wrap the text to the TextEdit item's width.
+ The text will only wrap if an explicit width has been set.
+
+ Wrapping is done on word boundaries (i.e. it is a "word-wrap"). Wrapping is off by default.
+*/
+void QmlGraphicsTextEdit::setWrap(bool w)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (w == d->wrap)
+ return;
+ d->wrap = w;
+ d->updateDefaultTextOption();
+ updateSize();
+ emit wrapChanged(d->wrap);
+}
+
+/*!
+ \qmlproperty bool TextEdit::cursorVisible
+ If true the text edit shows a cursor.
+
+ This property is set and unset when the text edit gets focus, but it can also
+ be set directly (useful, for example, if a KeyProxy might forward keys to it).
+*/
+bool QmlGraphicsTextEdit::isCursorVisible() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->cursorVisible;
+}
+
+void QmlGraphicsTextEdit::setCursorVisible(bool on)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
+ if (!on && !d->persistentSelection)
+ d->control->setCursorIsFocusIndicator(true);
+ d->control->processEvent(&focusEvent, QPointF(0, 0));
+ emit cursorVisibleChanged(d->cursorVisible);
+}
+
+/*!
+ \qmlproperty int TextEdit::cursorPosition
+ The position of the cursor in the TextEdit.
+*/
+int QmlGraphicsTextEdit::cursorPosition() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->control->textCursor().position();
+}
+
+void QmlGraphicsTextEdit::setCursorPosition(int pos)
+{
+ Q_D(QmlGraphicsTextEdit);
+ QTextCursor cursor = d->control->textCursor();
+ if (cursor.position() == pos)
+ return;
+ cursor.setPosition(pos);
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ \qmlproperty Component TextEdit::cursorDelegate
+ The delegate for the cursor in the TextEdit.
+
+ If you set a cursorDelegate for a TextEdit, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the text edit when a cursor is
+ needed, and the x and y properties of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QmlGraphicsItem or
+ QmlGraphicsItem derived item.
+*/
+QmlComponent* QmlGraphicsTextEdit::cursorDelegate() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->cursorComponent;
+}
+
+void QmlGraphicsTextEdit::setCursorDelegate(QmlComponent* c)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if(d->cursorComponent){
+ if(d->cursor){
+ disconnect(d->control, SIGNAL(cursorPositionChanged()),
+ this, SLOT(moveCursorDelegate()));
+ d->control->setCursorWidth(-1);
+ dirtyCache(cursorRect());
+ delete d->cursor;
+ d->cursor = 0;
+ }
+ }
+ d->cursorComponent = c;
+ if(c && c->isReady()){
+ loadCursorDelegate();
+ }else{
+ if(c)
+ connect(c, SIGNAL(statusChanged()),
+ this, SLOT(loadCursorDelegate()));
+ }
+
+ emit cursorDelegateChanged();
+}
+
+void QmlGraphicsTextEdit::loadCursorDelegate()
+{
+ Q_D(QmlGraphicsTextEdit);
+ if(d->cursorComponent->isLoading())
+ return;
+ d->cursor = qobject_cast<QmlGraphicsItem*>(d->cursorComponent->create(qmlContext(this)));
+ if(d->cursor){
+ connect(d->control, SIGNAL(cursorPositionChanged()),
+ this, SLOT(moveCursorDelegate()));
+ d->control->setCursorWidth(0);
+ dirtyCache(cursorRect());
+ d->cursor->setParentItem(this);
+ d->cursor->setHeight(QFontMetrics(d->font).height());
+ moveCursorDelegate();
+ }else{
+ qWarning() << QLatin1String("Error loading cursor delegate for TextEdit:") + objectName();
+ }
+}
+
+/*!
+ \qmlproperty int TextEdit::selectionStart
+
+ The cursor position before the first character in the current selection.
+ Setting this and selectionEnd allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionStart to a value outside of
+ the current text, selectionStart will not be changed.
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
+int QmlGraphicsTextEdit::selectionStart() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->control->textCursor().selectionStart();
+}
+
+void QmlGraphicsTextEdit::setSelectionStart(int s)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if(d->lastSelectionStart == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionStart = s;
+ d->updateSelection();// Will emit the relevant signals
+}
+
+/*!
+ \qmlproperty int TextEdit::selectionEnd
+
+ The cursor position after the last character in the current selection.
+ Setting this and selectionStart allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionEnd to a value outside of
+ the current text, selectionEnd will not be changed.
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
+int QmlGraphicsTextEdit::selectionEnd() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->control->textCursor().selectionEnd();
+}
+
+void QmlGraphicsTextEdit::setSelectionEnd(int s)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if(d->lastSelectionEnd == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionEnd = s;
+ d->updateSelection();// Will emit the relevant signals
+}
+
+/*!
+ \qmlproperty string TextEdit::selectedText
+
+ This read-only property provides the text currently selected in the
+ text edit.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+ \code
+ //myTextEdit is the id of the TextEdit
+ myTextEdit.text.toString().substring(myTextEdit.selectionStart,
+ myTextEdit.selectionEnd);
+ \endcode
+*/
+QString QmlGraphicsTextEdit::selectedText() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->control->textCursor().selectedText();
+}
+
+/*!
+ \qmlproperty bool TextEdit::focusOnPress
+
+ Whether the TextEdit should gain focus on a mouse press. By default this is
+ set to true.
+*/
+bool QmlGraphicsTextEdit::focusOnPress() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->focusOnPress;
+}
+
+void QmlGraphicsTextEdit::setFocusOnPress(bool on)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->focusOnPress == on)
+ return;
+ d->focusOnPress = on;
+ emit focusOnPressChanged(d->focusOnPress);
+}
+
+/*!
+ \qmlproperty bool TextEdit::persistentSelection
+
+ Whether the TextEdit should keep the selection visible when it loses focus to another
+ item in the scene. By default this is set to true;
+*/
+bool QmlGraphicsTextEdit::persistentSelection() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->persistentSelection;
+}
+
+void QmlGraphicsTextEdit::setPersistentSelection(bool on)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->persistentSelection == on)
+ return;
+ d->persistentSelection = on;
+ emit persistentSelectionChanged(d->persistentSelection);
+}
+
+qreal QmlGraphicsTextEdit::textMargin() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->textMargin;
+}
+
+void QmlGraphicsTextEdit::setTextMargin(qreal margin)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->textMargin == margin)
+ return;
+ d->textMargin = margin;
+ d->document->setDocumentMargin(d->textMargin);
+ emit textMarginChanged(d->textMargin);
+}
+
+void QmlGraphicsTextEdit::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width())
+ updateSize();
+ QmlGraphicsPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+/*!
+ Ensures any delayed caching or data loading the class
+ needs to performed is complete.
+*/
+void QmlGraphicsTextEdit::componentComplete()
+{
+ Q_D(QmlGraphicsTextEdit);
+ QmlGraphicsPaintedItem::componentComplete();
+ if (d->dirty) {
+ updateSize();
+ d->dirty = false;
+ }
+}
+
+/*!
+ \qmlproperty bool TextEdit::readOnly
+
+ Whether the user an interact with the TextEdit item. If this
+ property is set to true the text cannot be edited by user interaction.
+
+ By default this property is false.
+*/
+void QmlGraphicsTextEdit::setReadOnly(bool r)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (r == isReadOnly())
+ return;
+
+
+ Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
+ if (r) {
+ flags = Qt::TextSelectableByMouse;
+ } else {
+ flags = Qt::TextEditorInteraction;
+ }
+ d->control->setTextInteractionFlags(flags);
+ if (!r)
+ d->control->moveCursor(QTextCursor::End);
+
+ emit readOnlyChanged(r);
+}
+
+bool QmlGraphicsTextEdit::isReadOnly() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return !(d->control->textInteractionFlags() & Qt::TextEditable);
+}
+
+/*!
+ Sets how the text edit should interact with user input to the given
+ \a flags.
+*/
+void QmlGraphicsTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->control->setTextInteractionFlags(flags);
+}
+
+/*!
+ Returns the flags specifying how the text edit should interact
+ with user input.
+*/
+Qt::TextInteractionFlags QmlGraphicsTextEdit::textInteractionFlags() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->control->textInteractionFlags();
+}
+
+/*!
+ Returns the rectangle where the text cursor is rendered
+ within the text edit.
+*/
+QRect QmlGraphicsTextEdit::cursorRect() const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->control->cursorRect().toRect();
+}
+
+
+/*!
+\overload
+Handles the given \a event.
+*/
+bool QmlGraphicsTextEdit::event(QEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (event->type() == QEvent::ShortcutOverride) {
+ d->control->processEvent(event, QPointF(0, 0));
+ return event->isAccepted();
+ }
+ return QmlGraphicsPaintedItem::event(event);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QmlGraphicsTextEdit::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::keyPressEvent(event);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QmlGraphicsTextEdit::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::keyReleaseEvent(event);
+}
+
+/*!
+ \overload
+ Handles changing of the focus property. Focus is applied to the control
+ even if the edit does not have active focus. This is because things
+ like KeyProxy can give the behavior of focus even when hasFocus() isn't
+ true.
+*/
+void QmlGraphicsTextEdit::focusChanged(bool hasFocus)
+{
+ setCursorVisible(hasFocus);
+ QmlGraphicsItem::focusChanged(hasFocus);
+}
+
+/*!
+ Causes all text to be selected.
+*/
+void QmlGraphicsTextEdit::selectAll()
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->control->selectAll();
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QmlGraphicsTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (d->focusOnPress){
+ QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope?
+ while(p) {
+ if(p->flags() & QGraphicsItem::ItemIsFocusScope){
+ p->setFocus();
+ break;
+ }
+ p = p->parentItem();
+ }
+ setFocus(true);
+ }
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QmlGraphicsTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ QWidget *widget = event->widget();
+ if (widget && (d->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos()))
+ qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->focusOnPress);
+
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QmlGraphicsTextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::mouseDoubleClickEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QmlGraphicsTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given input method \a event.
+*/
+void QmlGraphicsTextEdit::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QmlGraphicsTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+}
+
+/*!
+\overload
+Returns the value of the given \a property.
+*/
+QVariant QmlGraphicsTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QmlGraphicsTextEdit);
+ return d->control->inputMethodQuery(property);
+}
+
+/*!
+Draws the contents of the text edit using the given \a painter within
+the given \a bounds.
+*/
+void QmlGraphicsTextEdit::drawContents(QPainter *painter, const QRect &bounds)
+{
+ Q_D(QmlGraphicsTextEdit);
+
+ painter->setRenderHint(QPainter::TextAntialiasing, true);
+
+ d->control->drawContents(painter, bounds);
+}
+
+void QmlGraphicsTextEdit::updateImgCache(const QRectF &r)
+{
+ dirtyCache(r.toRect());
+ emit update();
+}
+
+/*!
+ \qmlproperty bool TextEdit::smooth
+
+ Set this property if you want the text to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+void QmlGraphicsTextEditPrivate::init()
+{
+ Q_Q(QmlGraphicsTextEdit);
+
+ q->setSmooth(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemHasNoContents, false);
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+
+ control = new QTextControl(q);
+ control->setIgnoreUnusedNavigationEvents(true);
+
+ QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
+
+ QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
+
+ document = control->document();
+ document->setDefaultFont(font);
+ document->setDocumentMargin(textMargin);
+ document->setUndoRedoEnabled(false); // flush undo buffer.
+ document->setUndoRedoEnabled(true);
+ updateDefaultTextOption();
+}
+
+void QmlGraphicsTextEdit::q_textChanged()
+{
+ updateSize();
+ emit textChanged(text());
+}
+
+void QmlGraphicsTextEdit::moveCursorDelegate()
+{
+ Q_D(QmlGraphicsTextEdit);
+ if(!d->cursor)
+ return;
+ QRectF cursorRect = d->control->cursorRect();
+ d->cursor->setX(cursorRect.x());
+ d->cursor->setY(cursorRect.y());
+}
+
+void QmlGraphicsTextEditPrivate::updateSelection()
+{
+ Q_Q(QmlGraphicsTextEdit);
+ QTextCursor cursor = control->textCursor();
+ bool startChange = (lastSelectionStart != cursor.selectionStart());
+ bool endChange = (lastSelectionEnd != cursor.selectionEnd());
+ //### Is it worth calculating a more minimal set of movements?
+ cursor.beginEditBlock();
+ cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
+ cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
+ cursor.endEditBlock();
+ control->setTextCursor(cursor);
+ if(startChange)
+ q->selectionStartChanged();
+ if(endChange)
+ q->selectionEndChanged();
+ startChange = (lastSelectionStart != control->textCursor().selectionStart());
+ endChange = (lastSelectionEnd != control->textCursor().selectionEnd());
+ if(startChange || endChange)
+ qWarning() << "QmlGraphicsTextEditPrivate::updateSelection() has failed you.";
+}
+
+void QmlGraphicsTextEdit::updateSelectionMarkers()
+{
+ Q_D(QmlGraphicsTextEdit);
+ if(d->lastSelectionStart != d->control->textCursor().selectionStart()){
+ d->lastSelectionStart = d->control->textCursor().selectionStart();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->textCursor().selectionEnd()){
+ d->lastSelectionEnd = d->control->textCursor().selectionEnd();
+ emit selectionEndChanged();
+ }
+}
+
+//### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
+// need to do all the calculations each time
+void QmlGraphicsTextEdit::updateSize()
+{
+ Q_D(QmlGraphicsTextEdit);
+ if (isComponentComplete()) {
+ QFontMetrics fm = QFontMetrics(d->font);
+ int dy = height();
+ // ### assumes that if the width is set, the text will fill to edges
+ // ### (unless wrap is false, then clipping will occur)
+ if (widthValid())
+ d->document->setTextWidth(width());
+ dy -= (int)d->document->size().height();
+
+ int yoff = 0;
+ if (heightValid()) {
+ if (d->vAlign == AlignBottom)
+ yoff = dy;
+ else if (d->vAlign == AlignVCenter)
+ yoff = dy/2;
+ }
+ setBaselineOffset(fm.ascent() + yoff + d->textMargin);
+
+ //### need to comfirm cost of always setting these
+ int newWidth = (int)d->document->idealWidth();
+ d->document->setTextWidth(newWidth); // ### QTextDoc> Alignment will not work unless textWidth is set. Does Text need this line as well?
+ int cursorWidth = 1;
+ if(d->cursor)
+ cursorWidth = d->cursor->width();
+ newWidth += cursorWidth;
+ if(!d->document->isEmpty())
+ newWidth += 3;// ### Need a better way of accounting for space between char and cursor
+ // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
+ setImplicitWidth(newWidth);
+ setImplicitHeight(d->text.isEmpty() ? fm.height() : (int)d->document->size().height());
+
+ setContentsSize(QSize(width(), height()));
+ } else {
+ d->dirty = true;
+ }
+ emit update();
+}
+
+void QmlGraphicsTextEditPrivate::updateDefaultTextOption()
+{
+ QTextOption opt = document->defaultTextOption();
+ int oldAlignment = opt.alignment();
+ opt.setAlignment((Qt::Alignment)(int)(hAlign | vAlign));
+
+ QTextOption::WrapMode oldWrapMode = opt.wrapMode();
+
+ if (wrap)
+ opt.setWrapMode(QTextOption::WordWrap);
+ else
+ opt.setWrapMode(QTextOption::NoWrap);
+
+ if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
+ return;
+ document->setDefaultTextOption(opt);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicstextedit_p.h b/src/declarative/graphicsitems/qmlgraphicstextedit_p.h
new file mode 100644
index 0000000..e95b077
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstextedit_p.h
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSTEXTEDIT_H
+#define QMLGRAPHICSTEXTEDIT_H
+
+#include "qmlgraphicstext_p.h"
+#include "qmlgraphicspainteditem_p.h"
+
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qtextoption.h>
+#include <QtGui/qtextcursor.h>
+#include <QtGui/qtextformat.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+
+class QmlGraphicsTextEditPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsTextEdit : public QmlGraphicsPaintedItem
+{
+ Q_OBJECT
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(TextFormat)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
+ Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged) //### other wrap modes
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
+ Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QmlComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
+ Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged)
+ Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged)
+ Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY focusOnPressChanged)
+ Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection NOTIFY persistentSelectionChanged)
+ Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
+
+public:
+ QmlGraphicsTextEdit(QmlGraphicsItem *parent=0);
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter
+ };
+
+ enum VAlignment {
+ AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter
+ };
+
+ enum TextFormat {
+ PlainText = Qt::PlainText,
+ RichText = Qt::RichText,
+ AutoText = Qt::AutoText
+ };
+
+ QString text() const;
+ void setText(const QString &);
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor selectionColor() const;
+ void setSelectionColor(const QColor &c);
+
+ QColor selectedTextColor() const;
+ void setSelectedTextColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ bool wrap() const;
+ void setWrap(bool w);
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ int cursorPosition() const;
+ void setCursorPosition(int pos);
+
+ QmlComponent* cursorDelegate() const;
+ void setCursorDelegate(QmlComponent*);
+
+ int selectionStart() const;
+ void setSelectionStart(int);
+
+ int selectionEnd() const;
+ void setSelectionEnd(int);
+
+ QString selectedText() const;
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool on);
+
+ bool persistentSelection() const;
+ void setPersistentSelection(bool on);
+
+ qreal textMargin() const;
+ void setTextMargin(qreal margin);
+
+ virtual void componentComplete();
+
+ /* FROM EDIT */
+ void setReadOnly(bool);
+ bool isReadOnly() const;
+
+ void setTextInteractionFlags(Qt::TextInteractionFlags flags);
+ Qt::TextInteractionFlags textInteractionFlags() const;
+
+ QRect cursorRect() const;
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+Q_SIGNALS:
+ void textChanged(const QString &);
+ void cursorPositionChanged();
+ void selectionStartChanged();
+ void selectionEndChanged();
+ void selectionChanged();
+ void colorChanged(const QColor &color);
+ void selectionColorChanged(const QColor &color);
+ void selectedTextColorChanged(const QColor &color);
+ void fontChanged(const QFont &font);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+ void wrapChanged(bool isWrapped);
+ void textFormatChanged(TextFormat textFormat);
+ void readOnlyChanged(bool isReadOnly);
+ void cursorVisibleChanged(bool isCursorVisible);
+ void cursorDelegateChanged();
+ void focusOnPressChanged(bool focusIsPressed);
+ void persistentSelectionChanged(bool isPersistentSelection);
+ void textMarginChanged(qreal textMargin);
+
+public Q_SLOTS:
+ void selectAll();
+
+private Q_SLOTS:
+ void updateImgCache(const QRectF &rect);
+ void q_textChanged();
+ void updateSelectionMarkers();
+ void moveCursorDelegate();
+ void loadCursorDelegate();
+
+private:
+ void updateSize();
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ bool event(QEvent *);
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+
+ void focusChanged(bool);
+
+ // mouse filter?
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+
+ void inputMethodEvent(QInputMethodEvent *e);
+
+ void drawContents(QPainter *, const QRect &);
+private:
+ Q_DISABLE_COPY(QmlGraphicsTextEdit)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsTextEdit)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsTextEdit)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicstextedit_p_p.h b/src/declarative/graphicsitems/qmlgraphicstextedit_p_p.h
new file mode 100644
index 0000000..8914bfd
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstextedit_p_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSTEXTEDIT_P_H
+#define QMLGRAPHICSTEXTEDIT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlgraphicsitem.h"
+#include "qmlgraphicspainteditem_p_p.h"
+
+#include <qml.h>
+
+QT_BEGIN_NAMESPACE
+class QTextLayout;
+class QTextDocument;
+class QTextControl;
+class QmlGraphicsTextEditPrivate : public QmlGraphicsPaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsTextEdit)
+
+public:
+ QmlGraphicsTextEditPrivate()
+ : color("black"), imgDirty(true), hAlign(QmlGraphicsTextEdit::AlignLeft), vAlign(QmlGraphicsTextEdit::AlignTop),
+ dirty(false), wrap(false), richText(false), cursorVisible(false), focusOnPress(true),
+ persistentSelection(true), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0),
+ cursorComponent(0), cursor(0), format(QmlGraphicsTextEdit::AutoText), document(0)
+ {
+ }
+
+ void init();
+
+ void updateDefaultTextOption();
+ void relayoutDocument();
+ void updateSelection();
+
+ QString text;
+ QFont font;
+ QColor color;
+ QColor selectionColor;
+ QColor selectedTextColor;
+ QString style;
+ QColor styleColor;
+ bool imgDirty;
+ QPixmap imgCache;
+ QPixmap imgStyleCache;
+ QmlGraphicsTextEdit::HAlignment hAlign;
+ QmlGraphicsTextEdit::VAlignment vAlign;
+ bool dirty;
+ bool wrap;
+ bool richText;
+ bool cursorVisible;
+ bool focusOnPress;
+ bool persistentSelection;
+ qreal textMargin;
+ int lastSelectionStart;
+ int lastSelectionEnd;
+ QmlComponent* cursorComponent;
+ QmlGraphicsItem* cursor;
+ QmlGraphicsTextEdit::TextFormat format;
+ QTextDocument *document;
+ QTextControl *control;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicstextinput.cpp b/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
new file mode 100644
index 0000000..6d79c7a
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
@@ -0,0 +1,916 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicstextinput_p.h"
+#include "qmlgraphicstextinput_p_p.h"
+
+#include <qmlinfo.h>
+
+#include <QValidator>
+#include <QApplication>
+#include <QFontMetrics>
+#include <QPainter>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,TextInput,QmlGraphicsTextInput);
+QML_DEFINE_NOCREATE_TYPE(QValidator);
+QML_DEFINE_TYPE(Qt,4,6,QIntValidator,QIntValidator);
+QML_DEFINE_TYPE(Qt,4,6,QDoubleValidator,QDoubleValidator);
+QML_DEFINE_TYPE(Qt,4,6,QRegExpValidator,QRegExpValidator);
+
+/*!
+ \qmlclass TextInput QmlGraphicsTextInput
+ The TextInput item allows you to add an editable line of text to a scene.
+
+ TextInput can only display a single line of text, and can only display
+ plain text. However it can provide addition input constraints on the text.
+
+ Input constraints include setting a QValidator, an input mask, or a
+ maximum input length.
+*/
+QmlGraphicsTextInput::QmlGraphicsTextInput(QmlGraphicsItem* parent)
+ : QmlGraphicsPaintedItem(*(new QmlGraphicsTextInputPrivate), parent)
+{
+ Q_D(QmlGraphicsTextInput);
+ d->init();
+}
+
+QmlGraphicsTextInput::~QmlGraphicsTextInput()
+{
+}
+
+/*!
+ \qmlproperty string TextInput::text
+
+ The text in the TextInput.
+*/
+
+QString QmlGraphicsTextInput::text() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->text();
+}
+
+void QmlGraphicsTextInput::setText(const QString &s)
+{
+ Q_D(QmlGraphicsTextInput);
+ if(s == text())
+ return;
+ d->control->setText(s);
+ //emit textChanged();
+}
+
+/*!
+ \qmlproperty string TextInput::font.family
+ \qmlproperty bool TextInput::font.bold
+ \qmlproperty bool TextInput::font.italic
+ \qmlproperty bool TextInput::font.underline
+ \qmlproperty real TextInput::font.pointSize
+ \qmlproperty int TextInput::font.pixelSize
+
+ Set the TextInput's font attributes.
+*/
+QFont QmlGraphicsTextInput::font() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->font;
+}
+
+void QmlGraphicsTextInput::setFont(const QFont &font)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->font == font)
+ return;
+
+ d->font = font;
+
+ d->control->setFont(d->font);
+ if(d->cursorItem){
+ d->cursorItem->setHeight(QFontMetrics(d->font).height());
+ moveCursor();
+ }
+ updateSize();
+ emit fontChanged(d->font);
+}
+
+/*!
+ \qmlproperty color TextInput::color
+
+ The text color.
+*/
+QColor QmlGraphicsTextInput::color() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->color;
+}
+
+void QmlGraphicsTextInput::setColor(const QColor &c)
+{
+ Q_D(QmlGraphicsTextInput);
+ d->color = c;
+}
+
+
+/*!
+ \qmlproperty color TextInput::selectionColor
+
+ The text highlight color, used behind selections.
+*/
+QColor QmlGraphicsTextInput::selectionColor() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->selectionColor;
+}
+
+void QmlGraphicsTextInput::setSelectionColor(const QColor &color)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->selectionColor == color)
+ return;
+
+ d->selectionColor = color;
+ QPalette p = d->control->palette();
+ p.setColor(QPalette::Highlight, d->selectionColor);
+ d->control->setPalette(p);
+ emit selectionColorChanged(color);
+}
+
+/*!
+ \qmlproperty color TextInput::selectedTextColor
+
+ The highlighted text color, used in selections.
+*/
+QColor QmlGraphicsTextInput::selectedTextColor() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->selectedTextColor;
+}
+
+void QmlGraphicsTextInput::setSelectedTextColor(const QColor &color)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->selectedTextColor == color)
+ return;
+
+ d->selectedTextColor = color;
+ QPalette p = d->control->palette();
+ p.setColor(QPalette::HighlightedText, d->selectedTextColor);
+ d->control->setPalette(p);
+ emit selectedTextColorChanged(color);
+}
+
+/*!
+ \qmlproperty enumeration TextInput::horizontalAlignment
+
+ Sets the horizontal alignment of the text within the TextInput item's
+ width and height. By default, the text is left aligned.
+
+ TextInput does not have vertical alignment, as the natural height is
+ exactly the height of the single line of text. If you set the height
+ manually to something larger, TextInput will always be top aligned
+ vertically. You can use anchors to align it however you want within
+ another item.
+
+ The valid values for \c horizontalAlignment are \c AlignLeft, \c AlignRight and
+ \c AlignHCenter.
+*/
+QmlGraphicsTextInput::HAlignment QmlGraphicsTextInput::hAlign() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->hAlign;
+}
+
+void QmlGraphicsTextInput::setHAlign(HAlignment align)
+{
+ Q_D(QmlGraphicsTextInput);
+ if(align == d->hAlign)
+ return;
+ d->hAlign = align;
+ emit horizontalAlignmentChanged(d->hAlign);
+}
+
+bool QmlGraphicsTextInput::isReadOnly() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->isReadOnly();
+}
+
+void QmlGraphicsTextInput::setReadOnly(bool ro)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->control->isReadOnly() == ro)
+ return;
+
+ d->control->setReadOnly(ro);
+
+ emit readOnlyChanged(ro);
+}
+
+int QmlGraphicsTextInput::maxLength() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->maxLength();
+}
+
+void QmlGraphicsTextInput::setMaxLength(int ml)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->control->maxLength() == ml)
+ return;
+
+ d->control->setMaxLength(ml);
+
+ emit maximumLengthChanged(ml);
+}
+
+/*!
+ \qmlproperty bool TextInput::cursorVisible
+ Set to true when the TextInput shows a cursor.
+
+ This property is set and unset when the TextInput gets focus, so that other
+ properties can be bound to whether the cursor is currently showing. As it
+ gets set and unset automatically, when you set the value yourself you must
+ keep in mind that your value may be overwritten.
+
+ It can be set directly in script, for example if a KeyProxy might
+ forward keys to it and you desire it to look active when this happens
+ (but without actually giving it the focus).
+
+ It should not be set directly on the element, like in the below QML,
+ as the specified value will be overridden an lost on focus changes.
+
+ \code
+ TextInput {
+ text: "Text"
+ cursorVisible: false
+ }
+ \endcode
+
+ In the above snippet the cursor will still become visible when the
+ TextInput gains focus.
+*/
+bool QmlGraphicsTextInput::isCursorVisible() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->cursorVisible;
+}
+
+void QmlGraphicsTextInput::setCursorVisible(bool on)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
+ //d->control should emit the cursor update regions
+ emit cursorVisibleChanged(d->cursorVisible);
+}
+
+/*!
+ \qmlproperty int TextInput::cursorPosition
+ The position of the cursor in the TextInput.
+*/
+int QmlGraphicsTextInput::cursorPosition() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->cursor();
+}
+void QmlGraphicsTextInput::setCursorPosition(int cp)
+{
+ Q_D(QmlGraphicsTextInput);
+ d->control->moveCursor(cp);
+}
+
+/*!
+ \internal
+
+ Returns a Rect which encompasses the cursor, but which may be larger than is
+ required. Ignores custom cursor delegates.
+*/
+QRect QmlGraphicsTextInput::cursorRect() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->cursorRect();
+}
+
+/*!
+ \qmlproperty int TextInput::selectionStart
+
+ The cursor position before the first character in the current selection.
+ Setting this and selectionEnd allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionStart to a value outside of
+ the current text, selectionStart will not be changed.
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
+int QmlGraphicsTextInput::selectionStart() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->lastSelectionStart;
+}
+
+void QmlGraphicsTextInput::setSelectionStart(int s)
+{
+ Q_D(QmlGraphicsTextInput);
+ if(d->lastSelectionStart == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionStart = s;
+ d->control->setSelection(s, d->lastSelectionEnd - s);
+}
+
+/*!
+ \qmlproperty int TextInput::selectionEnd
+
+ The cursor position after the last character in the current selection.
+ Setting this and selectionStart allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionEnd to a value outside of
+ the current text, selectionEnd will not be changed.
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
+int QmlGraphicsTextInput::selectionEnd() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->lastSelectionEnd;
+}
+
+void QmlGraphicsTextInput::setSelectionEnd(int s)
+{
+ Q_D(QmlGraphicsTextInput);
+ if(d->lastSelectionEnd == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionEnd = s;
+ d->control->setSelection(d->lastSelectionStart, s - d->lastSelectionStart);
+}
+
+/*!
+ \qmlproperty string TextInput::selectedText
+
+ This read-only property provides the text currently selected in the
+ text input.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+
+ \qml
+ myTextInput.text.toString().substring(myTextInput.selectionStart,
+ myTextInput.selectionEnd);
+ \endqml
+*/
+QString QmlGraphicsTextInput::selectedText() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->selectedText();
+}
+
+/*!
+ \qmlproperty bool TextInput::focusOnPress
+
+ Whether the TextInput should gain focus on a mouse press. By default this is
+ set to true.
+*/
+bool QmlGraphicsTextInput::focusOnPress() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->focusOnPress;
+}
+
+void QmlGraphicsTextInput::setFocusOnPress(bool b)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->focusOnPress == b)
+ return;
+
+ d->focusOnPress = b;
+
+ emit focusOnPressChanged(d->focusOnPress);
+}
+
+/*!
+ \qmlproperty QValidator* TextInput::validator
+
+ Allows you to set a QValidator on the TextInput. When a validator is set
+ the TextInput will only accept input which leaves the text property in
+ an acceptable or intermediate state. The accepted signal will only be sent
+ if the text is in an acceptable state when enter is pressed.
+
+ Currently supported validators are QIntValidator, QDoubleValidator and
+ QRegExpValidator. For details, refer to their C++ documentation and remember
+ that all Q_PROPERTIES are accessible from Qml. A brief usage guide follows:
+
+ QIntValidator and QDoubleValidator both are controllable through two properties,
+ top and bottom. The difference is that for QIntValidator the top and bottom properties
+ should be integers, and for QDoubleValidator they should be doubles. QRegExpValidator
+ has a single string property, regExp, which should be set to the regular expression to
+ be used for validation. An example of using validators is shown below, which allows
+ input of integers between 11 and 31 into the text input:
+
+ \code
+ import Qt 4.6
+ TextInput{
+ validator: QIntValidator{bottom: 11; top: 31;}
+ focus: true
+ }
+ \endcode
+
+ \sa acceptableInput, inputMask
+*/
+QValidator* QmlGraphicsTextInput::validator() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ //###const cast isn't good, but needed for property system?
+ return const_cast<QValidator*>(d->control->validator());
+}
+
+void QmlGraphicsTextInput::setValidator(QValidator* v)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->control->validator() == v)
+ return;
+
+ d->control->setValidator(v);
+ if(!d->control->hasAcceptableInput()){
+ d->oldValidity = false;
+ emit acceptableInputChanged();
+ }
+
+ emit validatorChanged();
+}
+
+/*!
+ \qmlproperty string TextInput::inputMask
+
+ Allows you to set an input mask on the TextInput, restricting the allowable
+ text inputs. See QLineEdit::inputMask for further details, as the exact
+ same mask strings are used by TextInput.
+
+ \sa acceptableInput, validator
+*/
+QString QmlGraphicsTextInput::inputMask() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->inputMask();
+}
+
+void QmlGraphicsTextInput::setInputMask(const QString &im)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->control->inputMask() == im)
+ return;
+
+ d->control->setInputMask(im);
+ emit inputMaskChanged(d->control->inputMask());
+}
+
+/*!
+ \qmlproperty bool TextInput::acceptableInput
+
+ This property is always true unless a validator or input mask has been set.
+ If a validator or input mask has been set, this property will only be true
+ if the current text is acceptable to the validator or input mask as a final
+ string (not as an intermediate string).
+*/
+bool QmlGraphicsTextInput::hasAcceptableInput() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->hasAcceptableInput();
+}
+
+/*!
+ \qmlproperty TextInput.EchoMode TextInput::echoMode
+
+ Specifies how the text should be displayed in the TextInput.
+ The default is Normal, which displays the text as it is. Other values
+ are Password, which displays asterixes instead of characters, NoEcho,
+ which displays nothing, and PasswordEchoOnEdit, which displays all but the
+ current character as asterixes.
+
+*/
+QmlGraphicsTextInput::EchoMode QmlGraphicsTextInput::echoMode() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return (QmlGraphicsTextInput::EchoMode)d->control->echoMode();
+}
+
+void QmlGraphicsTextInput::setEchoMode(QmlGraphicsTextInput::EchoMode echo)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (echoMode() == echo)
+ return;
+
+ d->control->setEchoMode((uint)echo);
+ emit echoModeChanged(echoMode());
+}
+
+/*!
+ \qmlproperty Component TextInput::cursorDelegate
+ The delegate for the cursor in the TextInput.
+
+ If you set a cursorDelegate for a TextInput, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the TextInput when a cursor is
+ needed, and the x property of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QmlGraphicsItem or
+ QmlGraphicsItem derived item.
+*/
+QmlComponent* QmlGraphicsTextInput::cursorDelegate() const
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->cursorComponent;
+}
+
+void QmlGraphicsTextInput::setCursorDelegate(QmlComponent* c)
+{
+ Q_D(QmlGraphicsTextInput);
+ if (d->cursorComponent == c)
+ return;
+
+ d->cursorComponent = c;
+ if(!c){
+ //note that the components are owned by something else
+ disconnect(d->control, SIGNAL(cursorPositionChanged(int, int)),
+ this, SLOT(moveCursor()));
+ delete d->cursorItem;
+ }else{
+ d->startCreatingCursor();
+ }
+
+ emit cursorDelegateChanged();
+}
+
+void QmlGraphicsTextInputPrivate::startCreatingCursor()
+{
+ Q_Q(QmlGraphicsTextInput);
+ q->connect(control, SIGNAL(cursorPositionChanged(int, int)),
+ q, SLOT(moveCursor()));
+ if(cursorComponent->isReady()){
+ q->createCursor();
+ }else if(cursorComponent->isLoading()){
+ q->connect(cursorComponent, SIGNAL(statusChanged(int)),
+ q, SLOT(createCursor()));
+ }else{//isError
+ qmlInfo(q) << QmlGraphicsTextInput::tr("Could not load cursor delegate");
+ qWarning() << cursorComponent->errors();
+ }
+}
+
+void QmlGraphicsTextInput::createCursor()
+{
+ Q_D(QmlGraphicsTextInput);
+ if(d->cursorComponent->isError()){
+ qmlInfo(this) << tr("Could not load cursor delegate");
+ qWarning() << d->cursorComponent->errors();
+ return;
+ }
+
+ if(!d->cursorComponent->isReady())
+ return;
+
+ if(d->cursorItem)
+ delete d->cursorItem;
+ d->cursorItem = qobject_cast<QmlGraphicsItem*>(d->cursorComponent->create());
+ if(!d->cursorItem){
+ qmlInfo(this) << tr("Could not instantiate cursor delegate");
+ //The failed instantiation should print its own error messages
+ return;
+ }
+
+ d->cursorItem->setParentItem(this);
+ d->cursorItem->setX(d->control->cursorToX());
+ d->cursorItem->setHeight(d->control->height());
+}
+
+void QmlGraphicsTextInput::moveCursor()
+{
+ Q_D(QmlGraphicsTextInput);
+ if(!d->cursorItem)
+ return;
+ d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
+}
+
+int QmlGraphicsTextInput::xToPos(int x)
+{
+ Q_D(const QmlGraphicsTextInput);
+ return d->control->xToPos(x - d->hscroll);
+}
+
+void QmlGraphicsTextInput::focusChanged(bool hasFocus)
+{
+ Q_D(QmlGraphicsTextInput);
+ d->focused = hasFocus;
+ setCursorVisible(hasFocus);
+ QmlGraphicsItem::focusChanged(hasFocus);
+}
+
+void QmlGraphicsTextInput::keyPressEvent(QKeyEvent* ev)
+{
+ Q_D(QmlGraphicsTextInput);
+ if((d->control->cursor() == 0 && ev->key() == Qt::Key_Left)
+ || (d->control->cursor() == d->control->text().length()
+ && ev->key() == Qt::Key_Right)){
+ //ignore when moving off the end
+ ev->ignore();
+ }else{
+ d->control->processKeyEvent(ev);
+ }
+ if (!ev->isAccepted())
+ QmlGraphicsPaintedItem::keyPressEvent(ev);
+}
+
+void QmlGraphicsTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsTextInput);
+ if(d->focusOnPress){
+ QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope?
+ while(p) {
+ if(p->flags() & QGraphicsItem::ItemIsFocusScope){
+ p->setFocus();
+ break;
+ }
+ p = p->parentItem();
+ }
+ setFocus(true);
+ }
+ d->control->processEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QmlGraphicsTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsTextInput);
+ QWidget *widget = event->widget();
+ if (widget && !d->control->isReadOnly() && boundingRect().contains(event->pos()))
+ qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->focusOnPress);
+ d->control->processEvent(event);
+}
+
+bool QmlGraphicsTextInput::event(QEvent* ev)
+{
+ Q_D(QmlGraphicsTextInput);
+ //Anything we don't deal with ourselves, pass to the control
+ bool handled = false;
+ switch(ev->type()){
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease://###Should the control be doing anything with release?
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ break;
+ default:
+ handled = d->control->processEvent(ev);
+ }
+ if(!handled)
+ return QmlGraphicsPaintedItem::event(ev);
+ return true;
+}
+
+void QmlGraphicsTextInput::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width())
+ updateSize();
+ QmlGraphicsPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void QmlGraphicsTextInput::drawContents(QPainter *p, const QRect &r)
+{
+ Q_D(QmlGraphicsTextInput);
+ p->setRenderHint(QPainter::TextAntialiasing, true);
+ p->save();
+ p->setPen(QPen(d->color));
+ int flags = QLineControl::DrawText;
+ if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
+ flags |= QLineControl::DrawCursor;
+ if (d->control->hasSelectedText()){
+ flags |= QLineControl::DrawSelections;
+ }
+
+ QPoint offset = QPoint(0,0);
+ if(d->hAlign != AlignLeft){
+ QFontMetrics fm = QFontMetrics(d->font);
+ //###Is this using bearing appropriately?
+ int minLB = qMax(0, -fm.minLeftBearing());
+ int minRB = qMax(0, -fm.minRightBearing());
+ int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB;
+ int hOffset = 0;
+ if(d->hAlign == AlignRight){
+ hOffset = width() - widthUsed;
+ }else if(d->hAlign == AlignHCenter){
+ hOffset = (width() - widthUsed) / 2;
+ }
+ hOffset -= minLB;
+ offset = QPoint(hOffset, 0);
+ }
+ QRect clipRect = r;
+ d->control->draw(p, offset, clipRect, flags);
+
+ p->restore();
+}
+
+/*!
+\overload
+Returns the value of the given \a property.
+*/
+QVariant QmlGraphicsTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QmlGraphicsTextInput);
+ switch(property) {
+ case Qt::ImFont:
+ return font();
+ case Qt::ImCursorPosition:
+ return QVariant(d->control->cursor());
+ case Qt::ImSurroundingText:
+ return QVariant(text());
+ case Qt::ImCurrentSelection:
+ return QVariant(selectedText());
+ case Qt::ImMaximumTextLength:
+ return QVariant(maxLength());
+ case Qt::ImAnchorPosition:
+ if (d->control->selectionStart() == d->control->selectionEnd())
+ return QVariant(d->control->cursor());
+ else if (d->control->selectionStart() == d->control->cursor())
+ return QVariant(d->control->selectionEnd());
+ else
+ return QVariant(d->control->selectionStart());
+ default:
+ return QVariant();
+ }
+}
+
+void QmlGraphicsTextInput::selectAll()
+{
+ Q_D(QmlGraphicsTextInput);
+ d->control->setSelection(0, d->control->text().length());
+}
+
+
+/*!
+ \qmlproperty bool TextInput::smooth
+
+ Set this property if you want the text to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+void QmlGraphicsTextInputPrivate::init()
+{
+ Q_Q(QmlGraphicsTextInput);
+ control->setCursorWidth(1);
+ control->setPasswordCharacter(QLatin1Char('*'));
+ control->setLayoutDirection(Qt::LeftToRight);
+ q->setSmooth(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemHasNoContents, false);
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(cursorPosChanged()));
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(selectionChanged()));
+ q->connect(control, SIGNAL(textChanged(const QString &)),
+ q, SLOT(q_textChanged()));
+ q->connect(control, SIGNAL(accepted()),
+ q, SIGNAL(accepted()));
+ q->connect(control, SIGNAL(updateNeeded(QRect)),
+ q, SLOT(updateRect(QRect)));
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(updateRect()));//TODO: Only update rect between pos's
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(updateRect()));//TODO: Only update rect in selection
+ //Note that above TODOs probably aren't that big a savings
+ q->updateSize();
+ oldValidity = control->hasAcceptableInput();
+ lastSelectionStart = 0;
+ lastSelectionEnd = 0;
+}
+
+void QmlGraphicsTextInput::cursorPosChanged()
+{
+ Q_D(QmlGraphicsTextInput);
+ emit cursorPositionChanged();
+
+ if(!d->control->hasSelectedText()){
+ if(d->lastSelectionStart != d->control->cursor()){
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->cursor()){
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+ }
+}
+
+void QmlGraphicsTextInput::selectionChanged()
+{
+ Q_D(QmlGraphicsTextInput);
+ emit selectedTextChanged();
+
+ if(d->lastSelectionStart != d->control->selectionStart()){
+ d->lastSelectionStart = d->control->selectionStart();
+ if(d->lastSelectionStart == -1)
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->selectionEnd()){
+ d->lastSelectionEnd = d->control->selectionEnd();
+ if(d->lastSelectionEnd == -1)
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+}
+
+void QmlGraphicsTextInput::q_textChanged()
+{
+ Q_D(QmlGraphicsTextInput);
+ updateSize();
+ emit textChanged();
+ if(hasAcceptableInput() != d->oldValidity){
+ d->oldValidity = hasAcceptableInput();
+ emit acceptableInputChanged();
+ }
+}
+
+void QmlGraphicsTextInput::updateRect(const QRect &r)
+{
+ if(r == QRect())
+ clearCache();
+ else
+ dirtyCache(r);
+ update();
+}
+
+void QmlGraphicsTextInput::updateSize(bool needsRedraw)
+{
+ Q_D(QmlGraphicsTextInput);
+ int w = width();
+ int h = height();
+ setImplicitHeight(d->control->height());
+ int cursorWidth = d->control->cursorWidth();
+ if(d->cursorItem)
+ cursorWidth = d->cursorItem->width();
+ //### Is QFontMetrics too slow?
+ QFontMetricsF fm(d->font);
+ setImplicitWidth(fm.width(d->control->displayText())+cursorWidth);
+ setContentsSize(QSize(width(), height()));//Repaints if changed
+ if(w==width() && h==height() && needsRedraw){
+ clearCache();
+ update();
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/graphicsitems/qmlgraphicstextinput_p.h b/src/declarative/graphicsitems/qmlgraphicstextinput_p.h
new file mode 100644
index 0000000..4708381
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstextinput_p.h
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSTEXTINPUT_H
+#define QMLGRAPHICSTEXTINPUT_H
+
+#include "qmlgraphicstext_p.h"
+#include "qmlgraphicspainteditem_p.h"
+
+#include <QGraphicsSceneMouseEvent>
+#include <QIntValidator>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsTextInputPrivate;
+class QValidator;
+class Q_DECLARATIVE_EXPORT QmlGraphicsTextInput : public QmlGraphicsPaintedItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(EchoMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
+ Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged)
+
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
+ Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QRect cursorRect READ cursorRect NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
+ Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged)
+ Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
+
+ Q_PROPERTY(int maximumLength READ maxLength WRITE setMaxLength NOTIFY maximumLengthChanged)
+ Q_PROPERTY(QValidator* validator READ validator WRITE setValidator NOTIFY validatorChanged)
+ Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
+
+ Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged)
+ Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged)
+ Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY focusOnPressChanged)
+
+public:
+ QmlGraphicsTextInput(QmlGraphicsItem* parent=0);
+ ~QmlGraphicsTextInput();
+
+ enum EchoMode {//To match QLineEdit::EchoMode
+ Normal,
+ NoEcho,
+ Password,
+ PasswordEchoOnEdit
+ };
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter
+ };
+
+ //### Should we have this function, x based properties,
+ //### or copy TextEdit with x instead of QTextCursor?
+ Q_INVOKABLE int xToPos(int x);
+
+ QString text() const;
+ void setText(const QString &);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor selectionColor() const;
+ void setSelectionColor(const QColor &c);
+
+ QColor selectedTextColor() const;
+ void setSelectedTextColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+
+ bool isReadOnly() const;
+ void setReadOnly(bool);
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ int cursorPosition() const;
+ void setCursorPosition(int cp);
+
+ QRect cursorRect() const;
+
+ int selectionStart() const;
+ void setSelectionStart(int);
+
+ int selectionEnd() const;
+ void setSelectionEnd(int);
+
+ QString selectedText() const;
+
+ int maxLength() const;
+ void setMaxLength(int ml);
+
+ QValidator * validator() const;
+ void setValidator(QValidator* v);
+
+ QString inputMask() const;
+ void setInputMask(const QString &im);
+
+ EchoMode echoMode() const;
+ void setEchoMode(EchoMode echo);
+
+ QmlComponent* cursorDelegate() const;
+ void setCursorDelegate(QmlComponent*);
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool);
+
+ bool hasAcceptableInput() const;
+
+ void drawContents(QPainter *p,const QRect &r);
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+Q_SIGNALS:
+ void textChanged();
+ void cursorPositionChanged();
+ void selectionStartChanged();
+ void selectionEndChanged();
+ void selectedTextChanged();
+ void accepted();
+ void acceptableInputChanged();
+ void colorChanged(const QColor &color);
+ void selectionColorChanged(const QColor &color);
+ void selectedTextColorChanged(const QColor &color);
+ void fontChanged(const QFont &font);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void readOnlyChanged(bool isReadOnly);
+ void cursorVisibleChanged(bool isCursorVisible);
+ void cursorDelegateChanged();
+ void maximumLengthChanged(int maximumLength);
+ void validatorChanged();
+ void inputMaskChanged(const QString &inputMask);
+ void echoModeChanged(EchoMode echoMode);
+ void focusOnPressChanged(bool focusOnPress);
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent* ev);
+ bool event(QEvent *e);
+
+ void focusChanged(bool hasFocus);
+
+public Q_SLOTS:
+ void selectAll();
+
+private Q_SLOTS:
+ void updateSize(bool needsRedraw = true);
+ void q_textChanged();
+ void selectionChanged();
+ void createCursor();
+ void moveCursor();
+ void cursorPosChanged();
+ void updateRect(const QRect &r = QRect());
+
+private:
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsTextInput)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsTextInput)
+QML_DECLARE_TYPE(QValidator)
+QML_DECLARE_TYPE(QIntValidator)
+QML_DECLARE_TYPE(QDoubleValidator)
+QML_DECLARE_TYPE(QRegExpValidator)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSTEXTINPUT_H
diff --git a/src/declarative/graphicsitems/qmlgraphicstextinput_p_p.h b/src/declarative/graphicsitems/qmlgraphicstextinput_p_p.h
new file mode 100644
index 0000000..9eb6e07
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicstextinput_p_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSTEXTINPUT_P_H
+#define QMLGRAPHICSTEXTINPUT_P_H
+
+#include "qmlgraphicstextinput_p.h"
+
+#include "qmlgraphicspainteditem_p_p.h"
+
+#include <qml.h>
+
+#include <QPointer>
+
+#include <private/qlinecontrol_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsTextInputPrivate : public QmlGraphicsPaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsTextInput)
+public:
+ QmlGraphicsTextInputPrivate() : control(new QLineControl(QString())),
+ color((QRgb)0), style(QmlGraphicsText::Normal),
+ styleColor((QRgb)0), hAlign(QmlGraphicsTextInput::AlignLeft),
+ hscroll(0), oldScroll(0), focused(false), focusOnPress(true),
+ cursorVisible(false)
+ {
+ }
+
+ ~QmlGraphicsTextInputPrivate()
+ {
+ delete control;
+ }
+
+ void init();
+ void startCreatingCursor();
+
+ QLineControl* control;
+
+ QFont font;
+ QColor color;
+ QColor selectionColor;
+ QColor selectedTextColor;
+ QmlGraphicsText::TextStyle style;
+ QColor styleColor;
+ QmlGraphicsTextInput::HAlignment hAlign;
+ QPointer<QmlComponent> cursorComponent;
+ QPointer<QmlGraphicsItem> cursorItem;
+
+ int lastSelectionStart;
+ int lastSelectionEnd;
+ int oldHeight;
+ int oldWidth;
+ bool oldValidity;
+ int hscroll;
+ int oldScroll;
+ bool focused;
+ bool focusOnPress;
+ bool cursorVisible;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
new file mode 100644
index 0000000..2fc143d
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
@@ -0,0 +1,1155 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicsvisualitemmodel_p.h"
+
+#include "qmlgraphicsitem.h"
+
+#include <qmlcontext.h>
+#include <qmlengine.h>
+#include <qmlexpression.h>
+#include <qmlpackage_p.h>
+#include <qmlopenmetaobject_p.h>
+#include <qmllistaccessor_p.h>
+#include <qmlinfo.h>
+#include <qmldeclarativedata_p.h>
+#include <qmlpropertycache_p.h>
+#include <qmlguard_p.h>
+
+#include <qlistmodelinterface_p.h>
+#include <qhash.h>
+#include <qlist.h>
+#include <qmetaobjectbuilder_p.h>
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QML_DECLARE_TYPE(QListModelInterface)
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsVisualItemModelAttached : public QObject
+{
+ Q_OBJECT
+
+public:
+ QmlGraphicsVisualItemModelAttached(QObject *parent)
+ : QObject(parent), m_index(0) {}
+ ~QmlGraphicsVisualItemModelAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const { return m_index; }
+ void setIndex(int idx) {
+ if (m_index != idx) {
+ m_index = idx;
+ emit indexChanged();
+ }
+ }
+
+ static QmlGraphicsVisualItemModelAttached *properties(QObject *obj) {
+ QmlGraphicsVisualItemModelAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QmlGraphicsVisualItemModelAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+Q_SIGNALS:
+ void indexChanged();
+
+public:
+ int m_index;
+
+ static QHash<QObject*, QmlGraphicsVisualItemModelAttached*> attachedProperties;
+};
+
+QHash<QObject*, QmlGraphicsVisualItemModelAttached*> QmlGraphicsVisualItemModelAttached::attachedProperties;
+
+
+class QmlGraphicsVisualItemModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsVisualItemModel)
+public:
+ QmlGraphicsVisualItemModelPrivate() : QObjectPrivate(), children(this) {}
+
+ struct ItemList : public QmlConcreteList<QmlGraphicsItem *>
+ {
+ ItemList(QmlGraphicsVisualItemModelPrivate *m) : QmlConcreteList<QmlGraphicsItem *>(), model(m) {}
+
+ void append(QmlGraphicsItem *item);
+
+ QmlGraphicsVisualItemModelPrivate *model;
+ };
+
+ void itemAppended() {
+ Q_Q(QmlGraphicsVisualItemModel);
+ QmlGraphicsVisualItemModelAttached *attached = QmlGraphicsVisualItemModelAttached::properties(children.last());
+ attached->setIndex(children.count()-1);
+ emit q->itemsInserted(children.count()-1, 1);
+ emit q->countChanged();
+ }
+
+ void emitChildrenChanged() {
+ Q_Q(QmlGraphicsVisualItemModel);
+ emit q->childrenChanged();
+ }
+ ItemList children;
+};
+
+
+/*!
+ \qmlclass VisualItemModel QmlGraphicsVisualItemModel
+ \brief The VisualItemModel allows items to be provided to a view.
+
+ The children of the VisualItemModel are provided in a model which
+ can be used in a view. Note that no delegate should be
+ provided to a view since the VisualItemModel contains the
+ visual delegate (items).
+
+ An item can determine its index within the
+ model via the VisualItemModel.index attached property.
+
+ The example below places three colored rectangles in a ListView.
+ \code
+ Item {
+ VisualItemModel {
+ id: itemModel
+ Rectangle { height: 30; width: 80; color: "red" }
+ Rectangle { height: 30; width: 80; color: "green" }
+ Rectangle { height: 30; width: 80; color: "blue" }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: itemModel
+ }
+ }
+ \endcode
+*/
+QmlGraphicsVisualItemModel::QmlGraphicsVisualItemModel()
+ : QmlGraphicsVisualModel(*(new QmlGraphicsVisualItemModelPrivate))
+{
+}
+
+QmlList<QmlGraphicsItem *> *QmlGraphicsVisualItemModel::children()
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ return &(d->children);
+}
+
+/*!
+ \qmlproperty int VisualItemModel::count
+
+ The number of items in the model. This property is readonly.
+*/
+int QmlGraphicsVisualItemModel::count() const
+{
+ Q_D(const QmlGraphicsVisualItemModel);
+ return d->children.count();
+}
+
+bool QmlGraphicsVisualItemModel::isValid() const
+{
+ return true;
+}
+
+QmlGraphicsItem *QmlGraphicsVisualItemModel::item(int index, bool)
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ return d->children.at(index);
+}
+
+QmlGraphicsVisualModel::ReleaseFlags QmlGraphicsVisualItemModel::release(QmlGraphicsItem *)
+{
+ // Nothing to do
+ return 0;
+}
+
+void QmlGraphicsVisualItemModel::completeItem()
+{
+ // Nothing to do
+}
+
+QString QmlGraphicsVisualItemModel::stringValue(int index, const QString &name)
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ if (index < 0 || index >= d->children.count())
+ return QString();
+ return QmlEngine::contextForObject(d->children.at(index))->contextProperty(name).toString();
+}
+
+QVariant QmlGraphicsVisualItemModel::evaluate(int index, const QString &expression, QObject *objectContext)
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ if (index < 0 || index >= d->children.count())
+ return QVariant();
+ QmlContext *ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ ctxt->addDefaultObject(d->children.at(index));
+ QmlExpression e(ctxt, expression, objectContext);
+ e.setTrackChange(false);
+ QVariant value = e.value();
+ delete ctxt;
+ return value;
+}
+
+int QmlGraphicsVisualItemModel::indexOf(QmlGraphicsItem *item, QObject *) const
+{
+ Q_D(const QmlGraphicsVisualItemModel);
+ return d->children.indexOf(item);
+}
+
+void QmlGraphicsVisualItemModelPrivate::ItemList::append(QmlGraphicsItem *item)
+{
+ QmlConcreteList<QmlGraphicsItem*>::append(item);
+ item->QObject::setParent(model->q_ptr);
+ model->itemAppended();
+
+ model->emitChildrenChanged();
+}
+
+QmlGraphicsVisualItemModelAttached *QmlGraphicsVisualItemModel::qmlAttachedProperties(QObject *obj)
+{
+ return QmlGraphicsVisualItemModelAttached::properties(obj);
+}
+
+//============================================================================
+
+class VDMDelegateDataType : public QmlOpenMetaObjectType
+{
+public:
+ VDMDelegateDataType(const QMetaObject *base, QmlEngine *engine) : QmlOpenMetaObjectType(base, engine) {}
+
+ void propertyCreated(int, QMetaPropertyBuilder &prop) {
+ prop.setWritable(false);
+ }
+};
+
+class QmlGraphicsVisualDataModelParts;
+class QmlGraphicsVisualDataModelData;
+class QmlGraphicsVisualDataModelPrivate : public QObjectPrivate
+{
+public:
+ QmlGraphicsVisualDataModelPrivate(QmlContext *);
+
+ static QmlGraphicsVisualDataModelPrivate *get(QmlGraphicsVisualDataModel *m) {
+ return static_cast<QmlGraphicsVisualDataModelPrivate *>(QObjectPrivate::get(m));
+ }
+
+ QmlGuard<QListModelInterface> m_listModelInterface;
+ QmlGuard<QAbstractItemModel> m_abstractItemModel;
+ QmlGuard<QmlGraphicsVisualDataModel> m_visualItemModel;
+ QString m_part;
+
+ QmlComponent *m_delegate;
+ QmlContext *m_context;
+ QList<int> m_roles;
+ QHash<QByteArray,int> m_roleNames;
+ void ensureRoles() {
+ if (m_roleNames.isEmpty()) {
+ if (m_listModelInterface) {
+ m_roles = m_listModelInterface->roles();
+ for (int ii = 0; ii < m_roles.count(); ++ii)
+ m_roleNames.insert(m_listModelInterface->toString(m_roles.at(ii)).toUtf8(), m_roles.at(ii));
+ if (m_roles.count() == 1)
+ m_roleNames.insert("modelData", m_roles.at(0));
+ } else if (m_abstractItemModel) {
+ for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin();
+ it != m_abstractItemModel->roleNames().end(); ++it) {
+ m_roles.append(it.key());
+ m_roleNames.insert(*it, it.key());
+ }
+ if (m_roles.count() == 1)
+ m_roleNames.insert("modelData", m_roles.at(0));
+ } else if (m_listAccessor) {
+ m_roleNames.insert("modelData", 0);
+ if (m_listAccessor->type() == QmlListAccessor::Instance) {
+ if (QObject *object = m_listAccessor->at(0).value<QObject*>()) {
+ int count = object->metaObject()->propertyCount();
+ for (int ii = 1; ii < count; ++ii) {
+ const QMetaProperty &prop = object->metaObject()->property(ii);
+ m_roleNames.insert(prop.name(), 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void createMetaData() {
+ if (!m_metaDataCreated) {
+ ensureRoles();
+ QHash<QByteArray, int>::const_iterator it = m_roleNames.begin();
+ while (it != m_roleNames.end()) {
+ m_delegateDataType->createProperty(it.key());
+ ++it;
+ }
+ m_metaDataCreated = true;
+ }
+ }
+
+ struct ObjectRef {
+ ObjectRef(QObject *object=0) : obj(object), ref(1) {}
+ QObject *obj;
+ int ref;
+ };
+ class Cache : public QHash<int, ObjectRef> {
+ public:
+ QObject *getItem(int index) {
+ QObject *item = 0;
+ QHash<int,ObjectRef>::iterator it = find(index);
+ if (it != end()) {
+ (*it).ref++;
+ item = (*it).obj;
+ }
+ return item;
+ }
+ QObject *item(int index) {
+ QObject *item = 0;
+ QHash<int, ObjectRef>::const_iterator it = find(index);
+ if (it != end())
+ item = (*it).obj;
+ return item;
+ }
+ void insertItem(int index, QObject *obj) {
+ insert(index, ObjectRef(obj));
+ }
+ bool releaseItem(QObject *obj) {
+ QHash<int, ObjectRef>::iterator it = begin();
+ for (; it != end(); ++it) {
+ ObjectRef &objRef = *it;
+ if (objRef.obj == obj) {
+ if (--objRef.ref == 0) {
+ erase(it);
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+ };
+
+ int modelCount() const {
+ if (m_visualItemModel)
+ return m_visualItemModel->count();
+ if (m_listModelInterface)
+ return m_listModelInterface->count();
+ if (m_abstractItemModel)
+ return m_abstractItemModel->rowCount();
+ if (m_listAccessor)
+ return m_listAccessor->count();
+ return 0;
+ }
+
+ Cache m_cache;
+ QHash<QObject *, QmlPackage*> m_packaged;
+
+ QmlGraphicsVisualDataModelParts *m_parts;
+ friend class QmlGraphicsVisualItemParts;
+
+ VDMDelegateDataType *m_delegateDataType;
+ friend class QmlGraphicsVisualDataModelData;
+ bool m_metaDataCreated;
+ bool m_metaDataCacheable;
+
+ QmlGraphicsVisualDataModelData *data(QObject *item);
+
+ QVariant m_modelVariant;
+ QmlListAccessor *m_listAccessor;
+};
+
+class QmlGraphicsVisualDataModelDataMetaObject : public QmlOpenMetaObject
+{
+public:
+ QmlGraphicsVisualDataModelDataMetaObject(QObject *parent, QmlOpenMetaObjectType *type)
+ : QmlOpenMetaObject(parent, type) {}
+
+ virtual QVariant initialValue(int);
+ virtual int createProperty(const char *, const char *);
+
+private:
+ friend class QmlGraphicsVisualDataModelData;
+ QHash<int,int> roleToProp;
+};
+
+class QmlGraphicsVisualDataModelData : public QObject
+{
+Q_OBJECT
+public:
+ QmlGraphicsVisualDataModelData(int index, QmlGraphicsVisualDataModel *model);
+ ~QmlGraphicsVisualDataModelData();
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const;
+ void setIndex(int index);
+
+ int propForRole(int) const;
+ void setValue(int, const QVariant &);
+
+Q_SIGNALS:
+ void indexChanged();
+
+private:
+ friend class QmlGraphicsVisualDataModelDataMetaObject;
+ int m_index;
+ QmlGuard<QmlGraphicsVisualDataModel> m_model;
+ QmlGraphicsVisualDataModelDataMetaObject *m_meta;
+};
+
+int QmlGraphicsVisualDataModelData::propForRole(int id) const
+{
+ QHash<int,int>::const_iterator it = m_meta->roleToProp.find(id);
+ if (it != m_meta->roleToProp.end())
+ return m_meta->roleToProp[id];
+ return -1;
+}
+
+void QmlGraphicsVisualDataModelData::setValue(int id, const QVariant &val)
+{
+ m_meta->setValue(id, val);
+}
+
+int QmlGraphicsVisualDataModelDataMetaObject::createProperty(const char *name, const char *type)
+{
+ QmlGraphicsVisualDataModelData *data =
+ static_cast<QmlGraphicsVisualDataModelData *>(object());
+
+ if (!data->m_model)
+ return -1;
+
+ QmlGraphicsVisualDataModelPrivate *model = QmlGraphicsVisualDataModelPrivate::get(data->m_model);
+
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ if (model->m_listAccessor->type() == QmlListAccessor::QmlList
+ || model->m_listAccessor->type() == QmlListAccessor::QListPtr) {
+ model->ensureRoles();
+ QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
+ if (object && object->property(name).isValid())
+ return QmlOpenMetaObject::createProperty(name, type);
+ }
+ }
+ return -1;
+}
+
+QVariant QmlGraphicsVisualDataModelDataMetaObject::initialValue(int propId)
+{
+ QmlGraphicsVisualDataModelData *data =
+ static_cast<QmlGraphicsVisualDataModelData *>(object());
+
+ Q_ASSERT(data->m_model);
+ QmlGraphicsVisualDataModelPrivate *model = QmlGraphicsVisualDataModelPrivate::get(data->m_model);
+
+ QByteArray propName = name(propId);
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ if (propName == "modelData") {
+ if (model->m_listAccessor->type() == QmlListAccessor::Instance) {
+ QObject *object = model->m_listAccessor->at(0).value<QObject*>();
+ return object->metaObject()->property(1).read(object); // the first property after objectName
+ }
+ return model->m_listAccessor->at(data->m_index);
+ } else {
+ // return any property of a single object instance.
+ QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
+ return object->property(propName);
+ }
+ } else if (model->m_listModelInterface) {
+ model->ensureRoles();
+ QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
+ if (it != model->m_roleNames.end()) {
+ roleToProp.insert(*it, propId);
+ QVariant value = model->m_listModelInterface->data(data->m_index, *it);
+ return value;
+ } else if (model->m_roles.count() == 1 && propName == "modelData") {
+ //for compatability with other lists, assign modelData if there is only a single role
+ roleToProp.insert(model->m_roles.first(), propId);
+ QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
+ return value;
+ }
+ } else if (model->m_abstractItemModel) {
+ model->ensureRoles();
+ QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
+ if (it != model->m_roleNames.end()) {
+ roleToProp.insert(*it, propId);
+ QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0);
+ return model->m_abstractItemModel->data(index, *it);
+ }
+ }
+ Q_ASSERT(!"Can never be reached");
+ return QVariant();
+}
+
+QmlGraphicsVisualDataModelData::QmlGraphicsVisualDataModelData(int index,
+ QmlGraphicsVisualDataModel *model)
+: m_index(index), m_model(model),
+m_meta(new QmlGraphicsVisualDataModelDataMetaObject(this, QmlGraphicsVisualDataModelPrivate::get(model)->m_delegateDataType))
+{
+ QmlGraphicsVisualDataModelPrivate *modelPriv = QmlGraphicsVisualDataModelPrivate::get(model);
+ if (modelPriv->m_metaDataCacheable) {
+ if (!modelPriv->m_metaDataCreated)
+ modelPriv->createMetaData();
+ m_meta->setCached(true);
+ }
+}
+
+QmlGraphicsVisualDataModelData::~QmlGraphicsVisualDataModelData()
+{
+}
+
+int QmlGraphicsVisualDataModelData::index() const
+{
+ return m_index;
+}
+
+// This is internal only - it should not be set from qml
+void QmlGraphicsVisualDataModelData::setIndex(int index)
+{
+ m_index = index;
+ emit indexChanged();
+}
+
+//---------------------------------------------------------------------------
+
+class QmlGraphicsVisualDataModelPartsMetaObject : public QmlOpenMetaObject
+{
+public:
+ QmlGraphicsVisualDataModelPartsMetaObject(QObject *parent)
+ : QmlOpenMetaObject(parent) {}
+
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
+ virtual QVariant initialValue(int);
+};
+
+class QmlGraphicsVisualDataModelParts : public QObject
+{
+Q_OBJECT
+public:
+ QmlGraphicsVisualDataModelParts(QmlGraphicsVisualDataModel *parent);
+
+private:
+ friend class QmlGraphicsVisualDataModelPartsMetaObject;
+ QmlGraphicsVisualDataModel *model;
+};
+
+void QmlGraphicsVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+}
+
+QVariant QmlGraphicsVisualDataModelPartsMetaObject::initialValue(int id)
+{
+ QmlGraphicsVisualDataModel *m = new QmlGraphicsVisualDataModel;
+ m->setParent(object());
+ m->setPart(QString::fromUtf8(name(id)));
+ m->setModel(QVariant::fromValue(static_cast<QmlGraphicsVisualDataModelParts *>(object())->model));
+
+ QVariant var = QVariant::fromValue((QObject *)m);
+ return var;
+}
+
+QmlGraphicsVisualDataModelParts::QmlGraphicsVisualDataModelParts(QmlGraphicsVisualDataModel *parent)
+: QObject(parent), model(parent)
+{
+ new QmlGraphicsVisualDataModelPartsMetaObject(this);
+}
+
+QmlGraphicsVisualDataModelPrivate::QmlGraphicsVisualDataModelPrivate(QmlContext *ctxt)
+: m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
+, m_context(ctxt), m_parts(0), m_delegateDataType(0), m_metaDataCreated(false)
+, m_metaDataCacheable(false), m_listAccessor(0)
+{
+}
+
+QmlGraphicsVisualDataModelData *QmlGraphicsVisualDataModelPrivate::data(QObject *item)
+{
+ QmlGraphicsVisualDataModelData *dataItem =
+ item->findChild<QmlGraphicsVisualDataModelData *>();
+ Q_ASSERT(dataItem);
+ return dataItem;
+}
+
+//---------------------------------------------------------------------------
+
+QmlGraphicsVisualDataModel::QmlGraphicsVisualDataModel()
+: QmlGraphicsVisualModel(*(new QmlGraphicsVisualDataModelPrivate(0)))
+{
+}
+
+QmlGraphicsVisualDataModel::QmlGraphicsVisualDataModel(QmlContext *ctxt)
+: QmlGraphicsVisualModel(*(new QmlGraphicsVisualDataModelPrivate(ctxt)))
+{
+}
+
+QmlGraphicsVisualDataModel::~QmlGraphicsVisualDataModel()
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_listAccessor)
+ delete d->m_listAccessor;
+ if (d->m_delegateDataType)
+ d->m_delegateDataType->release();
+}
+
+QVariant QmlGraphicsVisualDataModel::model() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ return d->m_modelVariant;
+}
+
+void QmlGraphicsVisualDataModel::setModel(const QVariant &model)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ delete d->m_listAccessor;
+ d->m_listAccessor = 0;
+ d->m_modelVariant = model;
+ if (d->m_listModelInterface) {
+ // Assume caller has released all items.
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ d->m_listModelInterface = 0;
+ } else if (d->m_abstractItemModel) {
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
+ this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
+ } else if (d->m_visualItemModel) {
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ d->m_visualItemModel = 0;
+ }
+
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+ if (d->m_delegateDataType)
+ d->m_delegateDataType->release();
+ d->m_metaDataCreated = 0;
+ d->m_metaDataCacheable = false;
+ d->m_delegateDataType = new VDMDelegateDataType(&QmlGraphicsVisualDataModelData::staticMetaObject, d->m_context?d->m_context->engine():qmlEngine(this));
+
+ QObject *object = qvariant_cast<QObject *>(model);
+ if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ d->m_metaDataCacheable = true;
+ if (d->m_delegate && d->m_listModelInterface->count())
+ emit itemsInserted(0, d->m_listModelInterface->count());
+ return;
+ } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
+ this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
+ d->m_metaDataCacheable = true;
+ return;
+ }
+ if ((d->m_visualItemModel = qvariant_cast<QmlGraphicsVisualDataModel *>(model))) {
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ return;
+ }
+ d->m_listAccessor = new QmlListAccessor;
+ d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
+ if (d->m_listAccessor->type() != QmlListAccessor::QmlList && d->m_listAccessor->type() != QmlListAccessor::QListPtr)
+ d->m_metaDataCacheable = true;
+ if (d->m_delegate && d->modelCount()) {
+ emit itemsInserted(0, d->modelCount());
+ emit countChanged();
+ }
+}
+
+QmlComponent *QmlGraphicsVisualDataModel::delegate() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->delegate();
+ return d->m_delegate;
+}
+
+void QmlGraphicsVisualDataModel::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ bool wasValid = d->m_delegate != 0;
+ d->m_delegate = delegate;
+ if (!wasValid && d->modelCount() && d->m_delegate) {
+ emit itemsInserted(0, d->modelCount());
+ emit countChanged();
+ }
+ if (wasValid && !d->m_delegate && d->modelCount()) {
+ emit itemsRemoved(0, d->modelCount());
+ emit countChanged();
+ }
+}
+
+QString QmlGraphicsVisualDataModel::part() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ return d->m_part;
+}
+
+void QmlGraphicsVisualDataModel::setPart(const QString &part)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ d->m_part = part;
+}
+
+int QmlGraphicsVisualDataModel::count() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ return d->modelCount();
+}
+
+QmlGraphicsItem *QmlGraphicsVisualDataModel::item(int index, bool complete)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete);
+ return item(index, QByteArray(), complete);
+}
+
+/*
+ Returns ReleaseStatus flags.
+*/
+QmlGraphicsVisualDataModel::ReleaseFlags QmlGraphicsVisualDataModel::release(QmlGraphicsItem *item)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->release(item);
+
+ ReleaseFlags stat = 0;
+ QObject *obj = item;
+ bool inPackage = false;
+
+ QHash<QObject*,QmlPackage*>::iterator it = d->m_packaged.find(item);
+ if (it != d->m_packaged.end()) {
+ QmlPackage *package = *it;
+ d->m_packaged.erase(it);
+ if (d->m_packaged.contains(item))
+ stat |= Referenced;
+ inPackage = true;
+ obj = package; // fall through and delete
+ }
+
+ if (d->m_cache.releaseItem(obj)) {
+ if (inPackage) {
+ emit destroyingPackage(qobject_cast<QmlPackage*>(obj));
+ } else {
+ item->setVisible(false);
+ static_cast<QGraphicsItem*>(item)->setParentItem(0);
+ }
+ stat |= Destroyed;
+ obj->deleteLater();
+ } else if (!inPackage) {
+ stat |= Referenced;
+ }
+
+ return stat;
+}
+
+QObject *QmlGraphicsVisualDataModel::parts()
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (!d->m_parts)
+ d->m_parts = new QmlGraphicsVisualDataModelParts(this);
+ return d->m_parts;
+}
+
+QmlGraphicsItem *QmlGraphicsVisualDataModel::item(int index, const QByteArray &viewId, bool complete)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, viewId, complete);
+
+ if (d->modelCount() <= 0 || !d->m_delegate)
+ return 0;
+
+ QObject *nobj = d->m_cache.getItem(index);
+ if (!nobj) {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QmlGraphicsVisualDataModelData *data = new QmlGraphicsVisualDataModelData(index, this);
+ ctxt->setContextProperty(QLatin1String("model"), data);
+ ctxt->addDefaultObject(data);
+ nobj = d->m_delegate->beginCreate(ctxt);
+ if (complete)
+ d->m_delegate->completeCreate();
+ if (nobj) {
+ ctxt->setParent(nobj);
+ data->setParent(nobj);
+ d->m_cache.insertItem(index, nobj);
+ if (QmlPackage *package = qobject_cast<QmlPackage *>(nobj))
+ emit createdPackage(index, package);
+ } else {
+ delete data;
+ delete ctxt;
+ qWarning() << d->m_delegate->errors();
+ }
+ }
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!item) {
+ QmlPackage *package = qobject_cast<QmlPackage *>(nobj);
+ if (package) {
+ QObject *o = package->part(QString::fromUtf8(viewId));
+ item = qobject_cast<QmlGraphicsItem *>(o);
+ if (item)
+ d->m_packaged.insertMulti(item, package);
+ }
+ }
+ if (!item) {
+ d->m_cache.releaseItem(nobj);
+ qmlInfo(d->m_delegate) << QmlGraphicsVisualDataModel::tr("Delegate component must be Item type.");
+ }
+
+ return item;
+}
+
+void QmlGraphicsVisualDataModel::completeItem()
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel) {
+ d->m_visualItemModel->completeItem();
+ return;
+ }
+
+ d->m_delegate->completeCreate();
+}
+
+QString QmlGraphicsVisualDataModel::stringValue(int index, const QString &name)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->stringValue(index, name);
+
+ if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
+ return QString();
+
+ QString val;
+ QObject *data = 0;
+ bool tempData = false;
+
+ if (QObject *nobj = d->m_cache.item(index))
+ data = d->data(nobj);
+ if (!data) {
+ data = new QmlGraphicsVisualDataModelData(index, this);
+ tempData = true;
+ }
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(data);
+ if (ddata && ddata->propertyCache) {
+ QmlPropertyCache::Data *prop = ddata->propertyCache->property(name);
+ if (prop) {
+ if (prop->propType == QVariant::String) {
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
+ } else if (prop->propType == qMetaTypeId<QVariant>()) {
+ QVariant v;
+ void *args[] = { &v, 0 };
+ QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
+ val = v.toString();
+ }
+ } else {
+ val = data->property(name.toUtf8()).toString();
+ }
+ } else {
+ val = data->property(name.toUtf8()).toString();
+ }
+
+ if (tempData)
+ delete data;
+
+ return val;
+}
+
+QVariant QmlGraphicsVisualDataModel::evaluate(int index, const QString &expression, QObject *objectContext)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->evaluate(index, expression, objectContext);
+
+ if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
+ return QVariant();
+
+ QVariant value;
+ QObject *nobj = d->m_cache.item(index);
+ if (nobj) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (item) {
+ QmlExpression e(qmlContext(item), expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ }
+ } else {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QmlGraphicsVisualDataModelData *data = new QmlGraphicsVisualDataModelData(index, this);
+ ctxt->addDefaultObject(data);
+ QmlExpression e(ctxt, expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ delete data;
+ delete ctxt;
+ }
+
+ return value;
+}
+
+int QmlGraphicsVisualDataModel::indexOf(QmlGraphicsItem *item, QObject *) const
+{
+ QVariant val = QmlEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
+ return val.toInt();
+ return -1;
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsChanged(int index, int count,
+ const QList<int> &roles)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ for (int ii = index; ii < index + count; ++ii) {
+
+ if (QObject *item = d->m_cache.item(ii)) {
+ QmlGraphicsVisualDataModelData *data = d->data(item);
+
+ for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
+ int role = roles.at(roleIdx);
+ int propId = data->propForRole(role);
+ if (propId != -1) {
+ if (d->m_listModelInterface) {
+ data->setValue(propId, d->m_listModelInterface->data(ii, QList<int>() << role).value(role));
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(ii, 0);
+ data->setValue(propId, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ }
+ }
+ }
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsInserted(int index, int count)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= index) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + count;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsInserted(index, count);
+ emit countChanged();
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsRemoved(int index, int count)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ QHash<int, QmlGraphicsVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int, QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ if (iter.key() >= index && iter.key() < index + count) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ iter = d->m_cache.erase(iter);
+ items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(-1);
+ } else if (iter.key() >= index + count) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - count;
+ iter = d->m_cache.erase(iter);
+ items.insert(index, objRef);
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+
+ d->m_cache.unite(items);
+ emit itemsRemoved(index, count);
+ emit countChanged();
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsMoved(int from, int to, int count)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= from && iter.key() < from + count) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - from + to;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ for (QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ int diff = from > to ? count : -count;
+ if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + diff;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsMoved(from, to, count);
+}
+
+void QmlGraphicsVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
+{
+ if (!parent.isValid())
+ _q_itemsInserted(begin, end - begin + 1);
+}
+
+void QmlGraphicsVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
+{
+ if (!parent.isValid())
+ _q_itemsRemoved(begin, end - begin + 1);
+}
+
+void QmlGraphicsVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+{
+ const int count = sourceEnd - sourceStart + 1;
+ if (!destinationParent.isValid() && !sourceParent.isValid()) {
+ _q_itemsMoved(sourceStart, destinationRow, count);
+ } else if (!sourceParent.isValid()) {
+ _q_itemsRemoved(sourceStart, count);
+ } else if (!destinationParent.isValid()) {
+ _q_itemsInserted(destinationRow, count);
+ }
+}
+
+void QmlGraphicsVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (!begin.parent().isValid())
+ _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
+}
+
+void QmlGraphicsVisualDataModel::_q_createdPackage(int index, QmlPackage *package)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ emit createdItem(index, qobject_cast<QmlGraphicsItem*>(package->part(d->m_part)));
+}
+
+void QmlGraphicsVisualDataModel::_q_destroyingPackage(QmlPackage *package)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ emit destroyingItem(qobject_cast<QmlGraphicsItem*>(package->part(d->m_part)));
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsVisualModel);
+QML_DEFINE_TYPE(Qt,4,6,VisualItemModel,QmlGraphicsVisualItemModel)
+QML_DEFINE_TYPE(Qt,4,6,VisualDataModel,QmlGraphicsVisualDataModel)
+
+QT_END_NAMESPACE
+
+#include <qmlgraphicsvisualitemmodel.moc>
diff --git a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h
new file mode 100644
index 0000000..ef849b0
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSVISUALDATAMODEL_H
+#define QMLGRAPHICSVISUALDATAMODEL_H
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractitemmodel.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+/*****************************************************************************
+ *****************************************************************************
+ XXX Experimental
+ *****************************************************************************
+*****************************************************************************/
+
+class QmlGraphicsItem;
+class QmlComponent;
+class QmlPackage;
+class QmlGraphicsVisualDataModelPrivate;
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsVisualModel : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ QmlGraphicsVisualModel() {}
+ virtual ~QmlGraphicsVisualModel() {}
+
+ enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
+ Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
+
+ virtual int count() const = 0;
+ virtual bool isValid() const = 0;
+ virtual QmlGraphicsItem *item(int index, bool complete=true) = 0;
+ virtual ReleaseFlags release(QmlGraphicsItem *item) = 0;
+ virtual void completeItem() = 0;
+ virtual QVariant evaluate(int index, const QString &expression, QObject *objectContext) = 0;
+ virtual QString stringValue(int, const QString &) { return QString(); }
+
+ virtual int indexOf(QmlGraphicsItem *item, QObject *objectContext) const = 0;
+
+Q_SIGNALS:
+ void countChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void createdItem(int index, QmlGraphicsItem *item);
+ void destroyingItem(QmlGraphicsItem *item);
+
+protected:
+ QmlGraphicsVisualModel(QObjectPrivate &dd, QObject *parent = 0)
+ : QObject(dd, parent) {}
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsVisualModel)
+};
+
+class QmlGraphicsVisualItemModelAttached;
+class QmlGraphicsVisualItemModelPrivate;
+class Q_DECLARATIVE_EXPORT QmlGraphicsVisualItemModel : public QmlGraphicsVisualModel
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlGraphicsVisualItemModel)
+
+ Q_PROPERTY(QmlList<QmlGraphicsItem *>* children READ children NOTIFY childrenChanged DESIGNABLE false)
+ Q_CLASSINFO("DefaultProperty", "children")
+
+public:
+ QmlGraphicsVisualItemModel();
+ virtual ~QmlGraphicsVisualItemModel() {}
+
+ virtual int count() const;
+ virtual bool isValid() const;
+ virtual QmlGraphicsItem *item(int index, bool complete=true);
+ virtual ReleaseFlags release(QmlGraphicsItem *item);
+ virtual void completeItem();
+ virtual QString stringValue(int index, const QString &role);
+ virtual QVariant evaluate(int index, const QString &expression, QObject *objectContext);
+
+ virtual int indexOf(QmlGraphicsItem *item, QObject *objectContext) const;
+
+ QmlList<QmlGraphicsItem *> *children();
+
+ static QmlGraphicsVisualItemModelAttached *qmlAttachedProperties(QObject *obj);
+
+Q_SIGNALS:
+ void childrenChanged();
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsVisualItemModel)
+};
+
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsVisualDataModel : public QmlGraphicsVisualModel
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlGraphicsVisualDataModel)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(QString part READ part WRITE setPart)
+ Q_PROPERTY(QObject *parts READ parts CONSTANT)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+public:
+ QmlGraphicsVisualDataModel();
+ QmlGraphicsVisualDataModel(QmlContext *);
+ virtual ~QmlGraphicsVisualDataModel();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ QString part() const;
+ void setPart(const QString &);
+
+ int count() const;
+ bool isValid() const { return delegate() != 0; }
+ QmlGraphicsItem *item(int index, bool complete=true);
+ QmlGraphicsItem *item(int index, const QByteArray &, bool complete=true);
+ ReleaseFlags release(QmlGraphicsItem *item);
+ void completeItem();
+ virtual QString stringValue(int index, const QString &role);
+ QVariant evaluate(int index, const QString &expression, QObject *objectContext);
+
+ int indexOf(QmlGraphicsItem *item, QObject *objectContext) const;
+
+ QObject *parts();
+
+Q_SIGNALS:
+ void createdPackage(int index, QmlPackage *package);
+ void destroyingPackage(QmlPackage *package);
+
+private Q_SLOTS:
+ void _q_itemsChanged(int, int, const QList<int> &);
+ void _q_itemsInserted(int index, int count);
+ void _q_itemsRemoved(int index, int count);
+ void _q_itemsMoved(int from, int to, int count);
+ void _q_rowsInserted(const QModelIndex &,int,int);
+ void _q_rowsRemoved(const QModelIndex &,int,int);
+ void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
+ void _q_dataChanged(const QModelIndex&,const QModelIndex&);
+ void _q_createdPackage(int index, QmlPackage *package);
+ void _q_destroyingPackage(QmlPackage *package);
+
+private:
+ Q_DISABLE_COPY(QmlGraphicsVisualDataModel)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsVisualModel)
+QML_DECLARE_TYPE(QmlGraphicsVisualItemModel)
+QML_DECLARE_TYPEINFO(QmlGraphicsVisualItemModel, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QmlGraphicsVisualDataModel)
+
+QT_END_HEADER
+
+#endif // QMLGRAPHICSVISUALDATAMODEL_H
diff --git a/src/declarative/graphicsitems/qmlgraphicswebview.cpp b/src/declarative/graphicsitems/qmlgraphicswebview.cpp
new file mode 100644
index 0000000..85fd0d7
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicswebview.cpp
@@ -0,0 +1,1351 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlgraphicswebview_p.h"
+#include "qmlgraphicswebview_p_p.h"
+
+#include "qmlgraphicspainteditem_p_p.h"
+
+#include <qml.h>
+#include <qmlengine.h>
+#include <qmlstate_p.h>
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QMouseEvent>
+#include <QKeyEvent>
+#include <QBasicTimer>
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtWebKit/QWebPage>
+#include <QtWebKit/QWebFrame>
+#include <QtWebKit/QWebElement>
+#include <QtWebKit/QWebSettings>
+#include <qlistmodelinterface_p.h>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(Qt,4,6,WebView,QmlGraphicsWebView)
+QML_DEFINE_NOCREATE_TYPE(QAction)
+
+static const int MAX_DOUBLECLICK_TIME=500; // XXX need better gesture system
+
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsWebSettings)
+
+class QmlGraphicsWebViewPrivate : public QmlGraphicsPaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsWebView)
+
+public:
+ QmlGraphicsWebViewPrivate()
+ : QmlGraphicsPaintedItemPrivate(), page(0), preferredwidth(0), preferredheight(0),
+ progress(1.0), status(QmlGraphicsWebView::Null), pending(PendingNone),
+ newWindowComponent(0), newWindowParent(0),
+ pressTime(400),
+ windowObjects(this),
+ rendering(true)
+ {
+ }
+
+ QUrl url; // page url might be different if it has not loaded yet
+ QWebPage *page;
+
+ int preferredwidth, preferredheight;
+ qreal progress;
+ QmlGraphicsWebView::Status status;
+ QString statusText;
+ enum { PendingNone, PendingUrl, PendingHtml, PendingContent } pending;
+ QUrl pending_url;
+ QString pending_string;
+ QByteArray pending_data;
+ mutable QmlGraphicsWebSettings settings;
+ QmlComponent *newWindowComponent;
+ QmlGraphicsItem *newWindowParent;
+
+ QBasicTimer pressTimer;
+ QPoint pressPoint;
+ int pressTime; // milliseconds before it's a "hold"
+
+ void updateWindowObjects();
+ class WindowObjectList : public QmlConcreteList<QObject *>
+ {
+ public:
+ WindowObjectList(QmlGraphicsWebViewPrivate *p)
+ : priv(p) {}
+ virtual void append(QObject *v) {
+ QmlConcreteList<QObject *>::append(v);
+ priv->updateWindowObjects();
+ }
+ private:
+ QmlGraphicsWebViewPrivate *priv;
+ } windowObjects;
+
+ bool rendering;
+};
+
+/*!
+ \qmlclass WebView QmlGraphicsWebView
+ \brief The WebView item allows you to add web content to a canvas.
+ \inherits Item
+
+ A WebView renders web content based on a URL.
+
+ If the width and height of the item is not set, they will
+ dynamically adjust to a size appropriate for the content.
+ This width may be large for typical online web pages.
+
+ If the preferredWidth is set, the width will be this amount or larger,
+ usually laying out the web content to fit the preferredWidth.
+
+ \qml
+ WebView {
+ url: "http://www.nokia.com"
+ width: 490
+ height: 400
+ scale: 0.5
+ smooth: false
+ smoothCache: true
+ }
+ \endqml
+
+ \image webview.png
+
+ The item includes no scrolling, scaling,
+ toolbars, etc., those must be implemented around WebView. See the WebBrowser example
+ for a demonstration of this.
+*/
+
+/*!
+ \internal
+ \class QmlGraphicsWebView
+ \brief The QmlGraphicsWebView class allows you to add web content to a QmlView.
+
+ A WebView renders web content base on a URL.
+
+ \image webview.png
+
+ The item includes no scrolling, scaling,
+ toolbars, etc., those must be implemented around WebView. See the WebBrowser example
+ for a demonstration of this.
+
+ A QmlGraphicsWebView object can be instantiated in Qml using the tag \l WebView.
+*/
+
+QmlGraphicsWebView::QmlGraphicsWebView(QmlGraphicsItem *parent)
+ : QmlGraphicsPaintedItem(*(new QmlGraphicsWebViewPrivate), parent)
+{
+ init();
+}
+
+QmlGraphicsWebView::~QmlGraphicsWebView()
+{
+ Q_D(QmlGraphicsWebView);
+ delete d->page;
+}
+
+void QmlGraphicsWebView::init()
+{
+ Q_D(QmlGraphicsWebView);
+
+ setAcceptHoverEvents(true);
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+
+ d->page = 0;
+}
+
+void QmlGraphicsWebView::componentComplete()
+{
+ QmlGraphicsPaintedItem::componentComplete();
+ Q_D(QmlGraphicsWebView);
+ switch (d->pending) {
+ case QmlGraphicsWebViewPrivate::PendingUrl:
+ setUrl(d->pending_url);
+ break;
+ case QmlGraphicsWebViewPrivate::PendingHtml:
+ setHtml(d->pending_string, d->pending_url);
+ break;
+ case QmlGraphicsWebViewPrivate::PendingContent:
+ setContent(d->pending_data, d->pending_string, d->pending_url);
+ break;
+ default:
+ break;
+ }
+ d->pending = QmlGraphicsWebViewPrivate::PendingNone;
+ d->updateWindowObjects();
+}
+
+QmlGraphicsWebView::Status QmlGraphicsWebView::status() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->status;
+}
+
+
+/*!
+ \qmlproperty real WebView::progress
+ This property holds the progress of loading the current URL, from 0 to 1.
+
+ If you just want to know when progress gets to 1, use
+ WebView::onLoadFinished() or WebView::onLoadFailed() instead.
+*/
+qreal QmlGraphicsWebView::progress() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->progress;
+}
+
+void QmlGraphicsWebView::doLoadStarted()
+{
+ Q_D(QmlGraphicsWebView);
+
+ if (!d->url.isEmpty()) {
+ d->status = Loading;
+ emit statusChanged(d->status);
+ }
+ emit loadStarted();
+}
+
+void QmlGraphicsWebView::doLoadProgress(int p)
+{
+ Q_D(QmlGraphicsWebView);
+ if (d->progress == p/100.0)
+ return;
+ d->progress = p/100.0;
+ emit progressChanged();
+}
+
+void QmlGraphicsWebView::pageUrlChanged()
+{
+ Q_D(QmlGraphicsWebView);
+
+ page()->setViewportSize(QSize(
+ d->preferredwidth>0 ? d->preferredwidth : width(),
+ d->preferredheight>0 ? d->preferredheight : height()));
+ expandToWebPage();
+
+ if ((d->url.isEmpty() && page()->mainFrame()->url() != QUrl(QLatin1String("about:blank")))
+ || (d->url != page()->mainFrame()->url() && !page()->mainFrame()->url().isEmpty()))
+ {
+ d->url = page()->mainFrame()->url();
+ if (d->url == QUrl(QLatin1String("about:blank")))
+ d->url = QUrl();
+ emit urlChanged();
+ }
+}
+
+void QmlGraphicsWebView::doLoadFinished(bool ok)
+{
+ Q_D(QmlGraphicsWebView);
+
+ if (title().isEmpty())
+ pageUrlChanged(); // XXX bug 232556 - pages with no title never get urlChanged()
+
+ if (ok) {
+ d->status = d->url.isEmpty() ? Null : Ready;
+ emit loadFinished();
+ } else {
+ d->status = Error;
+ emit loadFailed();
+ }
+ emit statusChanged(d->status);
+}
+
+/*!
+ \qmlproperty url WebView::url
+ This property holds the URL to the page displayed in this item. It can be set,
+ but also can change spontaneously (eg. because of network redirection).
+
+ If the url is empty, the page is blank.
+
+ The url is always absolute (QML will resolve relative URL strings in the context
+ of the containing QML document).
+*/
+QUrl QmlGraphicsWebView::url() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->url;
+}
+
+void QmlGraphicsWebView::setUrl(const QUrl &url)
+{
+ Q_D(QmlGraphicsWebView);
+ if (url == d->url)
+ return;
+
+ if (isComponentComplete()) {
+ d->url = url;
+ page()->setViewportSize(QSize(
+ d->preferredwidth>0 ? d->preferredwidth : width(),
+ d->preferredheight>0 ? d->preferredheight : height()));
+ QUrl seturl = url;
+ if (seturl.isEmpty())
+ seturl = QUrl(QLatin1String("about:blank"));
+
+ Q_ASSERT(!seturl.isRelative());
+
+ page()->mainFrame()->load(seturl);
+
+ emit urlChanged();
+ } else {
+ d->pending = d->PendingUrl;
+ d->pending_url = url;
+ }
+}
+
+/*!
+ \qmlproperty int WebView::preferredWidth
+ This property holds the ideal width for displaying the current URL.
+*/
+int QmlGraphicsWebView::preferredWidth() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->preferredwidth;
+}
+
+void QmlGraphicsWebView::setPreferredWidth(int iw)
+{
+ Q_D(QmlGraphicsWebView);
+ if (d->preferredwidth == iw) return;
+ d->preferredwidth = iw;
+ //expandToWebPage();
+ emit preferredWidthChanged();
+}
+
+/*!
+ \qmlproperty int WebView::preferredHeight
+ This property holds the ideal height for displaying the current URL.
+ This only affects the area zoomed by heuristicZoom().
+*/
+int QmlGraphicsWebView::preferredHeight() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->preferredheight;
+}
+void QmlGraphicsWebView::setPreferredHeight(int ih)
+{
+ Q_D(QmlGraphicsWebView);
+ if (d->preferredheight == ih) return;
+ d->preferredheight = ih;
+ emit preferredHeightChanged();
+}
+
+/*!
+ \qmlmethod bool WebView::evaluateJavaScript(string)
+
+ Evaluates the \a scriptSource JavaScript inside the context of the
+ main web frame, and returns the result of the last executed statement.
+
+ Note that this JavaScript does \e not have any access to QML objects
+ except as made available as windowObjects.
+*/
+QVariant QmlGraphicsWebView::evaluateJavaScript(const QString &scriptSource)
+{
+ return this->page()->mainFrame()->evaluateJavaScript(scriptSource);
+}
+
+void QmlGraphicsWebView::focusChanged(bool hasFocus)
+{
+ QFocusEvent e(hasFocus ? QEvent::FocusIn : QEvent::FocusOut);
+ page()->event(&e);
+ QmlGraphicsItem::focusChanged(hasFocus);
+}
+
+void QmlGraphicsWebView::initialLayout()
+{
+ // nothing useful to do at this point
+}
+
+void QmlGraphicsWebView::noteContentsSizeChanged(const QSize&)
+{
+ expandToWebPage();
+}
+
+void QmlGraphicsWebView::expandToWebPage()
+{
+ Q_D(QmlGraphicsWebView);
+ QSize cs = page()->mainFrame()->contentsSize();
+ if (cs.width() < d->preferredwidth)
+ cs.setWidth(d->preferredwidth);
+ if (cs.height() < d->preferredheight)
+ cs.setHeight(d->preferredheight);
+ if (widthValid())
+ cs.setWidth(width());
+ if (heightValid())
+ cs.setHeight(height());
+ if (cs != page()->viewportSize()) {
+ page()->setViewportSize(cs);
+ }
+ if (cs != contentsSize())
+ setContentsSize(cs);
+}
+
+void QmlGraphicsWebView::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.size() != oldGeometry.size())
+ expandToWebPage();
+ QmlGraphicsPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void QmlGraphicsWebView::paintPage(const QRect& r)
+{
+ dirtyCache(r);
+ update();
+}
+
+/*!
+ \qmlproperty list<object> WebView::javaScriptWindowObjects
+
+ This property is a list of object that are available from within
+ the webview's JavaScript context.
+
+ The \a object will be inserted as a child of the frame's window
+ object, under the name given by the attached property \c WebView.windowObjectName.
+
+ \qml
+ WebView {
+ javaScriptWindowObjects: Object {
+ WebView.windowObjectName: "coordinates"
+ }
+ }
+ \endqml
+
+ Properties of the object will be exposed as JavaScript properties and slots as
+ JavaScript methods.
+
+ If Javascript is not enabled for this page, then this property does nothing.
+*/
+QmlList<QObject *> *QmlGraphicsWebView::javaScriptWindowObjects()
+{
+ Q_D(QmlGraphicsWebView);
+ return &d->windowObjects;
+}
+
+class QmlGraphicsWebViewAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString windowObjectName READ windowObjectName WRITE setWindowObjectName)
+public:
+ QmlGraphicsWebViewAttached(QObject *parent)
+ : QObject(parent)
+ {
+ }
+
+ QString windowObjectName() const
+ {
+ return m_windowObjectName;
+ }
+
+ void setWindowObjectName(const QString &n)
+ {
+ m_windowObjectName = n;
+ }
+
+private:
+ QString m_windowObjectName;
+};
+
+QmlGraphicsWebViewAttached *QmlGraphicsWebView::qmlAttachedProperties(QObject *o)
+{
+ return new QmlGraphicsWebViewAttached(o);
+}
+
+void QmlGraphicsWebViewPrivate::updateWindowObjects()
+{
+ Q_Q(QmlGraphicsWebView);
+ if (!q->isComponentComplete() || !page)
+ return;
+
+ for (int ii = 0; ii < windowObjects.count(); ++ii) {
+ QObject *object = windowObjects.at(ii);
+ QmlGraphicsWebViewAttached *attached = static_cast<QmlGraphicsWebViewAttached *>(qmlAttachedPropertiesObject<QmlGraphicsWebView>(object));
+ if (attached && !attached->windowObjectName().isEmpty()) {
+ page->mainFrame()->addToJavaScriptWindowObject(attached->windowObjectName(), object);
+ }
+ }
+}
+
+bool QmlGraphicsWebView::renderingEnabled() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->rendering;
+}
+
+void QmlGraphicsWebView::setRenderingEnabled(bool enabled)
+{
+ Q_D(QmlGraphicsWebView);
+ if (d->rendering == enabled)
+ return;
+ d->rendering = enabled;
+ setCacheFrozen(!enabled);
+ if (enabled)
+ clearCache();
+}
+
+
+void QmlGraphicsWebView::drawContents(QPainter *p, const QRect &r)
+{
+ Q_D(QmlGraphicsWebView);
+ if (d->rendering)
+ page()->mainFrame()->render(p,r);
+}
+
+QMouseEvent *QmlGraphicsWebView::sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e)
+{
+ QEvent::Type t;
+ switch(e->type()) {
+ default:
+ case QEvent::GraphicsSceneMousePress:
+ t = QEvent::MouseButtonPress;
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ t = QEvent::MouseButtonRelease;
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ t = QEvent::MouseMove;
+ break;
+ case QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick:
+ t = QEvent::MouseButtonDblClick;
+ break;
+ }
+
+ QMouseEvent *me = new QMouseEvent(t, (e->pos()/contentsScale()).toPoint(), e->button(), e->buttons(), 0);
+ return me;
+}
+
+QMouseEvent *QmlGraphicsWebView::sceneHoverMoveEventToMouseEvent(QGraphicsSceneHoverEvent *e)
+{
+ QEvent::Type t = QEvent::MouseMove;
+
+ QMouseEvent *me = new QMouseEvent(t, (e->pos()/contentsScale()).toPoint(), Qt::NoButton, Qt::NoButton, 0);
+
+ return me;
+}
+
+
+/*!
+ \qmlsignal WebView::onDoubleClick(clickx,clicky)
+
+ The WebView does not pass double-click events to the web engine, but rather
+ emits this signals.
+*/
+
+void QmlGraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ emit doubleClick(me->x(),me->y());
+ delete me;
+}
+
+/*!
+ \qmlmethod bool WebView::heuristicZoom(clickX,clickY,maxzoom)
+
+ Finds a zoom that:
+ \list
+ \i shows a whole item
+ \i includes (\a clickX, \a clickY)
+ \i fits into the preferredWidth and preferredHeight
+ \i zooms by no more than \a maxzoom
+ \i is more than 10% above the current zoom
+ \endlist
+
+ If such a zoom exists, emits zoomTo(zoom,centerX,centerY) and returns true; otherwise,
+ no signal is emitted and returns false.
+*/
+bool QmlGraphicsWebView::heuristicZoom(int clickX, int clickY, qreal maxzoom)
+{
+ Q_D(QmlGraphicsWebView);
+ if (contentsScale() >= maxzoom/zoomFactor())
+ return false;
+ qreal ozf = contentsScale();
+ QRect showarea = elementAreaAt(clickX, clickY, d->preferredwidth/maxzoom, d->preferredheight/maxzoom);
+ qreal z = qMin(qreal(d->preferredwidth)/showarea.width(),qreal(d->preferredheight)/showarea.height());
+ if (z > maxzoom/zoomFactor())
+ z = maxzoom/zoomFactor();
+ if (z/ozf > 1.2) {
+ QRectF r(showarea.left()*z, showarea.top()*z, showarea.width()*z, showarea.height()*z);
+ emit zoomTo(z,r.x()+r.width()/2, r.y()+r.height()/2);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*!
+ \qmlproperty int WebView::pressGrabTime
+
+ The number of milliseconds the user must press before the WebView
+ starts passing move events through to the web engine (rather than
+ letting other QML elements such as a Flickable take them).
+
+ Defaults to 400ms. Set to 0 to always grab and pass move events to
+ the web engine.
+*/
+int QmlGraphicsWebView::pressGrabTime() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->pressTime;
+}
+
+void QmlGraphicsWebView::setPressGrabTime(int ms)
+{
+ Q_D(QmlGraphicsWebView);
+ d->pressTime = ms;
+}
+
+void QmlGraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsWebView);
+
+ setFocus (true);
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+
+ d->pressPoint = me->pos();
+ if (d->pressTime) {
+ d->pressTimer.start(d->pressTime,this);
+ setKeepMouseGrab(false);
+ } else {
+ grabMouse();
+ setKeepMouseGrab(true);
+ }
+
+ page()->event(me);
+ event->setAccepted(
+/*
+ It is not correct to send the press event upwards, if it is not accepted by WebKit
+ e.g. push button does not work, if done so as QGraphicsScene will not send the release event at all to WebKit
+ Might be a bug in WebKit, though
+ */
+#if 1 //QT_VERSION <= 0x040500 // XXX see bug 230835
+ true
+#else
+ me->isAccepted()
+#endif
+ );
+ delete me;
+ if (!event->isAccepted()) {
+ QmlGraphicsPaintedItem::mousePressEvent(event);
+ }
+}
+
+void QmlGraphicsWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsWebView);
+
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ page()->event(me);
+ d->pressTimer.stop();
+ event->setAccepted(
+/*
+ It is not correct to send the press event upwards, if it is not accepted by WebKit
+ e.g. push button does not work, if done so as QGraphicsScene will not send all the events to WebKit
+ */
+#if 1 //QT_VERSION <= 0x040500 // XXX see bug 230835
+ true
+#else
+ me->isAccepted()
+#endif
+ );
+ delete me;
+ if (!event->isAccepted()) {
+ QmlGraphicsPaintedItem::mouseReleaseEvent(event);
+ }
+ setKeepMouseGrab(false);
+ ungrabMouse();
+}
+
+void QmlGraphicsWebView::timerEvent(QTimerEvent *event)
+{
+ Q_D(QmlGraphicsWebView);
+ if (event->timerId() == d->pressTimer.timerId()) {
+ d->pressTimer.stop();
+ grabMouse();
+ setKeepMouseGrab(true);
+ }
+}
+
+void QmlGraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QmlGraphicsWebView);
+
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ if (d->pressTimer.isActive()) {
+ if ((me->pos() - d->pressPoint).manhattanLength() > QApplication::startDragDistance()) {
+ d->pressTimer.stop();
+ }
+ }
+ if (keepMouseGrab()) {
+ page()->event(me);
+ event->setAccepted(
+/*
+ It is not correct to send the press event upwards, if it is not accepted by WebKit
+ e.g. push button does not work, if done so as QGraphicsScene will not send the release event at all to WebKit
+ Might be a bug in WebKit, though
+ */
+#if 1 // QT_VERSION <= 0x040500 // XXX see bug 230835
+ true
+#else
+ me->isAccepted()
+#endif
+ );
+ }
+ delete me;
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::mouseMoveEvent(event);
+
+}
+void QmlGraphicsWebView::hoverMoveEvent (QGraphicsSceneHoverEvent * event)
+{
+ QMouseEvent *me = sceneHoverMoveEventToMouseEvent(event);
+ page()->event(me);
+ event->setAccepted(
+#if QT_VERSION <= 0x040500 // XXX see bug 230835
+ true
+#else
+ me->isAccepted()
+#endif
+ );
+ delete me;
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::hoverMoveEvent(event);
+}
+
+void QmlGraphicsWebView::keyPressEvent(QKeyEvent* event)
+{
+ page()->event(event);
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::keyPressEvent(event);
+}
+
+void QmlGraphicsWebView::keyReleaseEvent(QKeyEvent* event)
+{
+ page()->event(event);
+ if (!event->isAccepted())
+ QmlGraphicsPaintedItem::keyReleaseEvent(event);
+}
+
+bool QmlGraphicsWebView::sceneEvent(QEvent *event)
+{
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *k = static_cast<QKeyEvent *>(event);
+ if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
+ if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
+ page()->event(event);
+ if (event->isAccepted())
+ return true;
+ }
+ }
+ }
+ return QmlGraphicsPaintedItem::sceneEvent(event);
+}
+
+
+/*!
+ \qmlproperty action WebView::back
+ This property holds the action for causing the previous URL in the history to be displayed.
+*/
+QAction *QmlGraphicsWebView::backAction() const
+{
+ return page()->action(QWebPage::Back);
+}
+
+/*!
+ \qmlproperty action WebView::forward
+ This property holds the action for causing the next URL in the history to be displayed.
+*/
+QAction *QmlGraphicsWebView::forwardAction() const
+{
+ return page()->action(QWebPage::Forward);
+}
+
+/*!
+ \qmlproperty action WebView::reload
+ This property holds the action for reloading with the current URL
+*/
+QAction *QmlGraphicsWebView::reloadAction() const
+{
+ return page()->action(QWebPage::Reload);
+}
+
+/*!
+ \qmlproperty action WebView::stop
+ This property holds the action for stopping loading with the current URL
+*/
+QAction *QmlGraphicsWebView::stopAction() const
+{
+ return page()->action(QWebPage::Stop);
+}
+
+/*!
+ \qmlproperty real WebView::title
+ This property holds the title of the web page currently viewed
+
+ By default, this property contains an empty string.
+*/
+QString QmlGraphicsWebView::title() const
+{
+ return page()->mainFrame()->title();
+}
+
+
+
+/*!
+ \qmlproperty pixmap WebView::icon
+ This property holds the icon associated with the web page currently viewed
+*/
+QPixmap QmlGraphicsWebView::icon() const
+{
+ return page()->mainFrame()->icon().pixmap(QSize(256,256));
+}
+
+
+/*!
+ \qmlproperty real WebView::zoomFactor
+ This property holds the multiplier used to scale the contents of a Web page.
+*/
+void QmlGraphicsWebView::setZoomFactor(qreal factor)
+{
+ Q_D(QmlGraphicsWebView);
+ if (factor == page()->mainFrame()->zoomFactor())
+ return;
+
+ page()->mainFrame()->setZoomFactor(factor);
+ page()->setViewportSize(QSize(
+ d->preferredwidth>0 ? d->preferredwidth*factor : width()*factor,
+ d->preferredheight>0 ? d->preferredheight*factor : height()*factor));
+ expandToWebPage();
+
+ emit zoomFactorChanged();
+}
+
+qreal QmlGraphicsWebView::zoomFactor() const
+{
+ return page()->mainFrame()->zoomFactor();
+}
+
+/*!
+ \qmlproperty string WebView::statusText
+
+ This property is the current status suggested by the current web page. In a web browser,
+ such status is often shown in some kind of status bar.
+*/
+void QmlGraphicsWebView::setStatusText(const QString& s)
+{
+ Q_D(QmlGraphicsWebView);
+ d->statusText = s;
+ emit statusTextChanged();
+}
+
+void QmlGraphicsWebView::windowObjectCleared()
+{
+ Q_D(QmlGraphicsWebView);
+ d->updateWindowObjects();
+}
+
+QString QmlGraphicsWebView::statusText() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->statusText;
+}
+
+QWebPage *QmlGraphicsWebView::page() const
+{
+ Q_D(const QmlGraphicsWebView);
+
+ if (!d->page) {
+ QmlGraphicsWebView *self = const_cast<QmlGraphicsWebView*>(this);
+ QWebPage *wp = new QmlGraphicsWebPage(self);
+
+ // QML items don't default to having a background,
+ // even though most we pages will set one anyway.
+ QPalette pal = QApplication::palette();
+ pal.setBrush(QPalette::Base, QColor::fromRgbF(0, 0, 0, 0));
+ wp->setPalette(pal);
+
+ wp->setNetworkAccessManager(qmlEngine(this)->networkAccessManager());
+
+ self->setPage(wp);
+
+ return wp;
+ }
+
+ return d->page;
+}
+
+
+// The QObject interface to settings().
+/*!
+ \qmlproperty string WebView::settings.standardFontFamily
+ \qmlproperty string WebView::settings.fixedFontFamily
+ \qmlproperty string WebView::settings.serifFontFamily
+ \qmlproperty string WebView::settings.sansSerifFontFamily
+ \qmlproperty string WebView::settings.cursiveFontFamily
+ \qmlproperty string WebView::settings.fantasyFontFamily
+
+ \qmlproperty int WebView::settings.minimumFontSize
+ \qmlproperty int WebView::settings.minimumLogicalFontSize
+ \qmlproperty int WebView::settings.defaultFontSize
+ \qmlproperty int WebView::settings.defaultFixedFontSize
+
+ \qmlproperty bool WebView::settings.autoLoadImages
+ \qmlproperty bool WebView::settings.javascriptEnabled
+ \qmlproperty bool WebView::settings.javaEnabled
+ \qmlproperty bool WebView::settings.pluginsEnabled
+ \qmlproperty bool WebView::settings.privateBrowsingEnabled
+ \qmlproperty bool WebView::settings.javascriptCanOpenWindows
+ \qmlproperty bool WebView::settings.javascriptCanAccessClipboard
+ \qmlproperty bool WebView::settings.developerExtrasEnabled
+ \qmlproperty bool WebView::settings.linksIncludedInFocusChain
+ \qmlproperty bool WebView::settings.zoomTextOnly
+ \qmlproperty bool WebView::settings.printElementBackgrounds
+ \qmlproperty bool WebView::settings.offlineStorageDatabaseEnabled
+ \qmlproperty bool WebView::settings.offlineWebApplicationCacheEnabled
+ \qmlproperty bool WebView::settings.localStorageDatabaseEnabled
+ \qmlproperty bool WebView::settings.localContentCanAccessRemoteUrls
+
+ These properties give access to the settings controlling the web view.
+
+ See QWebSettings for details of these properties.
+
+ \qml
+ WebView {
+ settings.pluginsEnabled: true
+ settings.standardFontFamily: "Arial"
+ ...
+ }
+ \endqml
+*/
+QmlGraphicsWebSettings *QmlGraphicsWebView::settingsObject() const
+{
+ Q_D(const QmlGraphicsWebView);
+ d->settings.s = page()->settings();
+ return &d->settings;
+}
+
+void QmlGraphicsWebView::setPage(QWebPage *page)
+{
+ Q_D(QmlGraphicsWebView);
+ if (d->page == page)
+ return;
+ if (d->page) {
+ if (d->page->parent() == this) {
+ delete d->page;
+ } else {
+ d->page->disconnect(this);
+ }
+ }
+ d->page = page;
+ d->page->setViewportSize(QSize(
+ d->preferredwidth>0 ? d->preferredwidth : width(),
+ d->preferredheight>0 ? d->preferredheight : height()));
+ d->page->mainFrame()->setScrollBarPolicy(Qt::Horizontal,Qt::ScrollBarAlwaysOff);
+ d->page->mainFrame()->setScrollBarPolicy(Qt::Vertical,Qt::ScrollBarAlwaysOff);
+ connect(d->page,SIGNAL(repaintRequested(QRect)),this,SLOT(paintPage(QRect)));
+ connect(d->page->mainFrame(),SIGNAL(urlChanged(QUrl)),this,SLOT(pageUrlChanged()));
+ connect(d->page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
+ connect(d->page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged()));
+ connect(d->page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SLOT(noteContentsSizeChanged(QSize)));
+ connect(d->page->mainFrame(), SIGNAL(initialLayoutCompleted()), this, SLOT(initialLayout()));
+
+ connect(d->page,SIGNAL(loadStarted()),this,SLOT(doLoadStarted()));
+ connect(d->page,SIGNAL(loadProgress(int)),this,SLOT(doLoadProgress(int)));
+ connect(d->page,SIGNAL(loadFinished(bool)),this,SLOT(doLoadFinished(bool)));
+ connect(d->page,SIGNAL(statusBarMessage(QString)),this,SLOT(setStatusText(QString)));
+
+ connect(d->page->mainFrame(),SIGNAL(javaScriptWindowObjectCleared()),this,SLOT(windowObjectCleared()));
+}
+
+/*!
+ \qmlsignal WebView::onLoadStarted()
+
+ This handler is called when the web engine begins loading
+ a page. Later, WebView::onLoadFinished() or WebView::onLoadFailed()
+ will be emitted.
+*/
+
+/*!
+ \qmlsignal WebView::onLoadFinished()
+
+ This handler is called when the web engine \e successfully
+ finishes loading a page, including any component content
+ (WebView::onLoadFailed() will be emitted otherwise).
+
+ \sa progress
+*/
+
+/*!
+ \qmlsignal WebView::onLoadFailed()
+
+ This handler is called when the web engine fails loading
+ a page or any component content
+ (WebView::onLoadFinished() will be emitted on success).
+*/
+
+void QmlGraphicsWebView::load(const QNetworkRequest &request,
+ QNetworkAccessManager::Operation operation,
+ const QByteArray &body)
+{
+ page()->mainFrame()->load(request, operation, body);
+}
+
+QString QmlGraphicsWebView::html() const
+{
+ return page()->mainFrame()->toHtml();
+}
+
+/*!
+ \qmlproperty string WebView::html
+ This property holds HTML text set directly
+
+ The html property can be set as a string.
+
+ \qml
+ WebView {
+ html: "<p>This is <b>HTML</b>."
+ }
+ \endqml
+*/
+void QmlGraphicsWebView::setHtml(const QString &html, const QUrl &baseUrl)
+{
+ Q_D(QmlGraphicsWebView);
+ page()->setViewportSize(QSize(
+ d->preferredwidth>0 ? d->preferredwidth : width(),
+ d->preferredheight>0 ? d->preferredheight : height()));
+ if (isComponentComplete())
+ page()->mainFrame()->setHtml(html, baseUrl);
+ else {
+ d->pending = d->PendingHtml;
+ d->pending_url = baseUrl;
+ d->pending_string = html;
+ }
+}
+
+void QmlGraphicsWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
+{
+ Q_D(QmlGraphicsWebView);
+ page()->setViewportSize(QSize(
+ d->preferredwidth>0 ? d->preferredwidth : width(),
+ d->preferredheight>0 ? d->preferredheight : height()));
+
+ if (isComponentComplete())
+ page()->mainFrame()->setContent(data,mimeType,qmlContext(this)->resolvedUrl(baseUrl));
+ else {
+ d->pending = d->PendingContent;
+ d->pending_url = baseUrl;
+ d->pending_string = mimeType;
+ d->pending_data = data;
+ }
+}
+
+QWebHistory *QmlGraphicsWebView::history() const
+{
+ return page()->history();
+}
+
+QWebSettings *QmlGraphicsWebView::settings() const
+{
+ return page()->settings();
+}
+
+QmlGraphicsWebView *QmlGraphicsWebView::createWindow(QWebPage::WebWindowType type)
+{
+ Q_D(QmlGraphicsWebView);
+ switch (type) {
+ case QWebPage::WebBrowserWindow: {
+ if (!d->newWindowComponent && d->newWindowParent)
+ qWarning("WebView::newWindowComponent not set - WebView::newWindowParent ignored");
+ else if (d->newWindowComponent && !d->newWindowParent)
+ qWarning("WebView::newWindowParent not set - WebView::newWindowComponent ignored");
+ else if (d->newWindowComponent && d->newWindowParent) {
+ QmlGraphicsWebView *webview = 0;
+ QmlContext *windowContext = new QmlContext(qmlContext(this));
+
+ QObject *nobj = d->newWindowComponent->create(windowContext);
+ if (nobj) {
+ windowContext->setParent(nobj);
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!item) {
+ delete nobj;
+ } else {
+ webview = item->findChild<QmlGraphicsWebView*>();
+ if (!webview) {
+ delete item;
+ } else {
+ item->setParent(d->newWindowParent);
+ }
+ }
+ } else {
+ delete windowContext;
+ }
+
+ return webview;
+ }
+ }
+ break;
+ case QWebPage::WebModalDialog: {
+ // Not supported
+ }
+ }
+ return 0;
+}
+
+/*!
+ \qmlproperty component WebView::newWindowComponent
+
+ This property holds the component to use for new windows.
+ The component must have a WebView somewhere in its structure.
+
+ When the web engine requests a new window, it will be an instance of
+ this component.
+
+ The parent of the new window is set by newWindowParent. It must be set.
+*/
+QmlComponent *QmlGraphicsWebView::newWindowComponent() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->newWindowComponent;
+}
+
+void QmlGraphicsWebView::setNewWindowComponent(QmlComponent *newWindow)
+{
+ Q_D(QmlGraphicsWebView);
+ delete d->newWindowComponent;
+ d->newWindowComponent = newWindow;
+}
+
+
+/*!
+ \qmlproperty item WebView::newWindowParent
+
+ The parent item for new windows.
+
+ \sa newWindowComponent
+*/
+QmlGraphicsItem *QmlGraphicsWebView::newWindowParent() const
+{
+ Q_D(const QmlGraphicsWebView);
+ return d->newWindowParent;
+}
+
+void QmlGraphicsWebView::setNewWindowParent(QmlGraphicsItem *parent)
+{
+ Q_D(QmlGraphicsWebView);
+ delete d->newWindowParent;
+ d->newWindowParent = parent;
+}
+
+/*!
+ Returns the area of the largest element at position (\a x,\a y) that is no larger
+ than \a maxwidth by \a maxheight pixels.
+
+ May return an area larger in the case when no smaller element is at the position.
+*/
+QRect QmlGraphicsWebView::elementAreaAt(int x, int y, int maxwidth, int maxheight) const
+{
+ QWebHitTestResult hit = page()->mainFrame()->hitTestContent(QPoint(x,y));
+ QRect rv = hit.boundingRect();
+ QWebElement element = hit.enclosingBlockElement();
+ if (maxwidth<=0) maxwidth = INT_MAX;
+ if (maxheight<=0) maxheight = INT_MAX;
+ while (!element.parent().isNull() && element.geometry().width() <= maxwidth && element.geometry().height() <= maxheight) {
+ rv = element.geometry();
+ element = element.parent();
+ }
+ return rv;
+}
+
+/*!
+ \internal
+ \class QmlGraphicsWebPage
+ \brief The QmlGraphicsWebPage class is a QWebPage that can create QML plugins.
+
+ \sa QmlGraphicsWebView
+*/
+QmlGraphicsWebPage::QmlGraphicsWebPage(QmlGraphicsWebView *parent) :
+ QWebPage(parent)
+{
+}
+
+QmlGraphicsWebPage::~QmlGraphicsWebPage()
+{
+}
+
+void QmlGraphicsWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
+{
+ qWarning() << sourceID << ':' << lineNumber << ':' << message;
+}
+
+QString QmlGraphicsWebPage::chooseFile(QWebFrame *originatingFrame, const QString& oldFile)
+{
+ // Not supported (it's modal)
+ Q_UNUSED(originatingFrame)
+ Q_UNUSED(oldFile)
+ return oldFile;
+}
+
+void QmlGraphicsWebPage::javaScriptAlert(QWebFrame *originatingFrame, const QString& msg)
+{
+ Q_UNUSED(originatingFrame)
+ emit viewItem()->alert(msg);
+}
+
+bool QmlGraphicsWebPage::javaScriptConfirm(QWebFrame *originatingFrame, const QString& msg)
+{
+ // Not supported (it's modal)
+ Q_UNUSED(originatingFrame)
+ Q_UNUSED(msg)
+ return false;
+}
+
+bool QmlGraphicsWebPage::javaScriptPrompt(QWebFrame *originatingFrame, const QString& msg, const QString& defaultValue, QString* result)
+{
+ // Not supported (it's modal)
+ Q_UNUSED(originatingFrame)
+ Q_UNUSED(msg)
+ Q_UNUSED(defaultValue)
+ Q_UNUSED(result)
+ return false;
+}
+
+
+/*
+ Qt WebKit does not understand non-QWidget plugins, so dummy widgets
+ are created, parented to a single dummy tool window.
+
+ The requirements for QML object plugins are input to the Qt WebKit
+ non-QWidget plugin support, which will obsolete this kludge.
+*/
+class QWidget_Dummy_Plugin : public QWidget
+{
+ Q_OBJECT
+public:
+ static QWidget *dummy_shared_parent()
+ {
+ static QWidget *dsp = 0;
+ if (!dsp) {
+ dsp = new QWidget(0,Qt::Tool);
+ dsp->setGeometry(-10000,-10000,0,0);
+ dsp->show();
+ }
+ return dsp;
+ }
+ QWidget_Dummy_Plugin(const QUrl& url, QmlGraphicsWebView *view, const QStringList &paramNames, const QStringList &paramValues) :
+ QWidget(dummy_shared_parent()),
+ propertyNames(paramNames),
+ propertyValues(paramValues),
+ webview(view)
+ {
+ QmlEngine *engine = qmlEngine(webview);
+ component = new QmlComponent(engine, url, this);
+ item = 0;
+ if (component->isLoading())
+ connect(component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(qmlLoaded()));
+ else
+ qmlLoaded();
+ }
+
+public Q_SLOTS:
+ void qmlLoaded()
+ {
+ if (component->isError()) {
+ // ### Could instead give these errors to the WebView to handle.
+ qWarning() << component->errors();
+ return;
+ }
+ item = qobject_cast<QmlGraphicsItem*>(component->create(qmlContext(webview)));
+ item->setParent(webview);
+ QString jsObjName;
+ for (int i=0; i<propertyNames.count(); ++i) {
+ if (propertyNames[i] != QLatin1String("type") && propertyNames[i] != QLatin1String("data")) {
+ item->setProperty(propertyNames[i].toUtf8(),propertyValues[i]);
+ if (propertyNames[i] == QLatin1String("objectname"))
+ jsObjName = propertyValues[i];
+ }
+ }
+ if (!jsObjName.isNull()) {
+ QWebFrame *f = webview->page()->mainFrame();
+ f->addToJavaScriptWindowObject(jsObjName, item);
+ }
+ resizeEvent(0);
+ delete component;
+ component = 0;
+ }
+ void resizeEvent(QResizeEvent*)
+ {
+ if (item) {
+ item->setX(x());
+ item->setY(y());
+ item->setWidth(width());
+ item->setHeight(height());
+ }
+ }
+
+private:
+ QmlComponent *component;
+ QmlGraphicsItem *item;
+ QStringList propertyNames, propertyValues;
+ QmlGraphicsWebView *webview;
+};
+
+QmlGraphicsWebView *QmlGraphicsWebPage::viewItem()
+{
+ return static_cast<QmlGraphicsWebView*>(parent());
+}
+
+QObject *QmlGraphicsWebPage::createPlugin(const QString &, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
+{
+ QUrl comp = qmlContext(viewItem())->resolvedUrl(url);
+ return new QWidget_Dummy_Plugin(comp,viewItem(),paramNames,paramValues);
+}
+
+QWebPage *QmlGraphicsWebPage::createWindow(WebWindowType type)
+{
+ QmlGraphicsWebView *newView = viewItem()->createWindow(type);
+ if (newView)
+ return newView->page();
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include <qmlgraphicswebview.moc>
diff --git a/src/declarative/graphicsitems/qmlgraphicswebview_p.h b/src/declarative/graphicsitems/qmlgraphicswebview_p.h
new file mode 100644
index 0000000..f5edb7a
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicswebview_p.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSWEBVIEW_H
+#define QMLGRAPHICSWEBVIEW_H
+
+#include "qmlgraphicspainteditem_p.h"
+
+#include <QtGui/QAction>
+#include <QtCore/QUrl>
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtWebKit/QWebPage>
+
+QT_BEGIN_HEADER
+
+class QWebHistory;
+class QWebSettings;
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlGraphicsWebViewPrivate;
+class QNetworkRequest;
+class QmlGraphicsWebView;
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsWebPage : public QWebPage
+{
+ Q_OBJECT
+public:
+ explicit QmlGraphicsWebPage(QmlGraphicsWebView *parent);
+ ~QmlGraphicsWebPage();
+protected:
+ QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues);
+ QWebPage *createWindow(WebWindowType type);
+ void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID);
+ QString chooseFile(QWebFrame *originatingFrame, const QString& oldFile);
+ void javaScriptAlert(QWebFrame *originatingFrame, const QString& msg);
+ bool javaScriptConfirm(QWebFrame *originatingFrame, const QString& msg);
+ bool javaScriptPrompt(QWebFrame *originatingFrame, const QString& msg, const QString& defaultValue, QString* result);
+
+private:
+ QmlGraphicsWebView *viewItem();
+};
+
+
+class QmlGraphicsWebViewAttached;
+class QmlGraphicsWebSettings;
+
+//### TODO: browser plugins
+
+class Q_DECLARATIVE_EXPORT QmlGraphicsWebView : public QmlGraphicsPaintedItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(Status SelectionMode)
+
+ Q_PROPERTY(QString title READ title NOTIFY titleChanged)
+ Q_PROPERTY(QPixmap icon READ icon NOTIFY iconChanged)
+ Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged)
+ Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged)
+
+ Q_PROPERTY(QString html READ html WRITE setHtml)
+
+ Q_PROPERTY(int pressGrabTime READ pressGrabTime WRITE setPressGrabTime)
+
+ Q_PROPERTY(int preferredWidth READ preferredWidth WRITE setPreferredWidth NOTIFY preferredWidthChanged)
+ Q_PROPERTY(int preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged)
+ Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+ Q_PROPERTY(QAction* reload READ reloadAction CONSTANT)
+ Q_PROPERTY(QAction* back READ backAction CONSTANT)
+ Q_PROPERTY(QAction* forward READ forwardAction CONSTANT)
+ Q_PROPERTY(QAction* stop READ stopAction CONSTANT)
+
+ Q_PROPERTY(QmlGraphicsWebSettings* settings READ settingsObject CONSTANT)
+
+ Q_PROPERTY(QmlList<QObject *>* javaScriptWindowObjects READ javaScriptWindowObjects CONSTANT)
+
+ Q_PROPERTY(QmlComponent* newWindowComponent READ newWindowComponent WRITE setNewWindowComponent)
+ Q_PROPERTY(QmlGraphicsItem* newWindowParent READ newWindowParent WRITE setNewWindowParent)
+
+ Q_PROPERTY(bool renderingEnabled READ renderingEnabled WRITE setRenderingEnabled)
+
+public:
+ QmlGraphicsWebView(QmlGraphicsItem *parent=0);
+ ~QmlGraphicsWebView();
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+
+ QString title() const;
+
+ QPixmap icon() const;
+
+ qreal zoomFactor() const;
+ void setZoomFactor(qreal);
+ Q_INVOKABLE bool heuristicZoom(int clickX, int clickY, qreal maxzoom);
+ QRect elementAreaAt(int x, int y, int minwidth, int minheight) const;
+
+ int pressGrabTime() const;
+ void setPressGrabTime(int);
+
+ int preferredWidth() const;
+ void setPreferredWidth(int);
+ int preferredHeight() const;
+ void setPreferredHeight(int);
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+ QString statusText() const;
+
+ QAction *reloadAction() const;
+ QAction *backAction() const;
+ QAction *forwardAction() const;
+ QAction *stopAction() const;
+
+ QWebPage *page() const;
+ void setPage(QWebPage *page);
+
+ void load(const QNetworkRequest &request,
+ QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
+ const QByteArray &body = QByteArray());
+
+ QString html() const;
+
+ void setHtml(const QString &html, const QUrl &baseUrl = QUrl());
+ void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl());
+
+ QWebHistory *history() const;
+ QWebSettings *settings() const;
+ QmlGraphicsWebSettings *settingsObject() const;
+
+ bool renderingEnabled() const;
+ void setRenderingEnabled(bool);
+
+ QmlList<QObject *> *javaScriptWindowObjects();
+
+ static QmlGraphicsWebViewAttached *qmlAttachedProperties(QObject *);
+
+ QmlComponent *newWindowComponent() const;
+ void setNewWindowComponent(QmlComponent *newWindow);
+ QmlGraphicsItem *newWindowParent() const;
+ void setNewWindowParent(QmlGraphicsItem *newWindow);
+
+Q_SIGNALS:
+ void preferredWidthChanged();
+ void preferredHeightChanged();
+ void urlChanged();
+ void progressChanged();
+ void statusChanged(Status);
+ void titleChanged(const QString&);
+ void iconChanged();
+ void statusTextChanged();
+ void zoomFactorChanged();
+
+ void loadStarted();
+ void loadFinished();
+ void loadFailed();
+
+ void doubleClick(int clickX, int clickY);
+
+ void zoomTo(qreal zoom, int centerX, int centerY);
+
+ void alert(const QString& message);
+
+public Q_SLOTS:
+ QVariant evaluateJavaScript(const QString&);
+
+private Q_SLOTS:
+ void expandToWebPage();
+ void paintPage(const QRect&);
+ void doLoadStarted();
+ void doLoadProgress(int p);
+ void doLoadFinished(bool ok);
+ void setStatusText(const QString&);
+ void windowObjectCleared();
+ void pageUrlChanged();
+ void noteContentsSizeChanged(const QSize&);
+ void initialLayout();
+
+protected:
+ void drawContents(QPainter *, const QRect &);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void timerEvent(QTimerEvent *event);
+ void hoverMoveEvent (QGraphicsSceneHoverEvent * event);
+ void keyPressEvent(QKeyEvent* event);
+ void keyReleaseEvent(QKeyEvent* event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual void focusChanged(bool);
+ virtual bool sceneEvent(QEvent *event);
+ QmlGraphicsWebView *createWindow(QWebPage::WebWindowType type);
+
+private:
+ void init();
+ virtual void componentComplete();
+ Q_DISABLE_COPY(QmlGraphicsWebView)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsWebView)
+ QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *);
+ QMouseEvent *sceneHoverMoveEventToMouseEvent(QGraphicsSceneHoverEvent *);
+ friend class QmlGraphicsWebPage;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsWebView)
+QML_DECLARE_TYPEINFO(QmlGraphicsWebView, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QAction)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qmlgraphicswebview_p_p.h b/src/declarative/graphicsitems/qmlgraphicswebview_p_p.h
new file mode 100644
index 0000000..5659059
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicswebview_p_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSWEBVIEW_P_H
+#define QMLGRAPHICSWEBVIEW_P_H
+
+#include <qml.h>
+
+#include <QtWebKit/QWebPage>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsWebSettings : public QObject {
+ Q_OBJECT
+
+ Q_PROPERTY(QString standardFontFamily READ standardFontFamily WRITE setStandardFontFamily)
+ Q_PROPERTY(QString fixedFontFamily READ fixedFontFamily WRITE setFixedFontFamily)
+ Q_PROPERTY(QString serifFontFamily READ serifFontFamily WRITE setSerifFontFamily)
+ Q_PROPERTY(QString sansSerifFontFamily READ sansSerifFontFamily WRITE setSansSerifFontFamily)
+ Q_PROPERTY(QString cursiveFontFamily READ cursiveFontFamily WRITE setCursiveFontFamily)
+ Q_PROPERTY(QString fantasyFontFamily READ fantasyFontFamily WRITE setFantasyFontFamily)
+
+ Q_PROPERTY(int minimumFontSize READ minimumFontSize WRITE setMinimumFontSize)
+ Q_PROPERTY(int minimumLogicalFontSize READ minimumLogicalFontSize WRITE setMinimumLogicalFontSize)
+ Q_PROPERTY(int defaultFontSize READ defaultFontSize WRITE setDefaultFontSize)
+ Q_PROPERTY(int defaultFixedFontSize READ defaultFixedFontSize WRITE setDefaultFixedFontSize)
+
+ Q_PROPERTY(bool autoLoadImages READ autoLoadImages WRITE setAutoLoadImages)
+ Q_PROPERTY(bool javascriptEnabled READ javascriptEnabled WRITE setJavascriptEnabled)
+ Q_PROPERTY(bool javaEnabled READ javaEnabled WRITE setJavaEnabled)
+ Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled)
+ Q_PROPERTY(bool privateBrowsingEnabled READ privateBrowsingEnabled WRITE setPrivateBrowsingEnabled)
+ Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows)
+ Q_PROPERTY(bool javascriptCanAccessClipboard READ javascriptCanAccessClipboard WRITE setJavascriptCanAccessClipboard)
+ Q_PROPERTY(bool developerExtrasEnabled READ developerExtrasEnabled WRITE setDeveloperExtrasEnabled)
+ Q_PROPERTY(bool linksIncludedInFocusChain READ linksIncludedInFocusChain WRITE setLinksIncludedInFocusChain)
+ Q_PROPERTY(bool zoomTextOnly READ zoomTextOnly WRITE setZoomTextOnly)
+ Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds)
+ Q_PROPERTY(bool offlineStorageDatabaseEnabled READ offlineStorageDatabaseEnabled WRITE setOfflineStorageDatabaseEnabled)
+ Q_PROPERTY(bool offlineWebApplicationCacheEnabled READ offlineWebApplicationCacheEnabled WRITE setOfflineWebApplicationCacheEnabled)
+ Q_PROPERTY(bool localStorageDatabaseEnabled READ localStorageDatabaseEnabled WRITE setLocalStorageDatabaseEnabled)
+ Q_PROPERTY(bool localContentCanAccessRemoteUrls READ localContentCanAccessRemoteUrls WRITE setLocalContentCanAccessRemoteUrls)
+
+public:
+ QmlGraphicsWebSettings() {}
+
+ QString standardFontFamily() const { return s->fontFamily(QWebSettings::StandardFont); }
+ void setStandardFontFamily(const QString& f) { s->setFontFamily(QWebSettings::StandardFont,f); }
+ QString fixedFontFamily() const { return s->fontFamily(QWebSettings::FixedFont); }
+ void setFixedFontFamily(const QString& f) { s->setFontFamily(QWebSettings::FixedFont,f); }
+ QString serifFontFamily() const { return s->fontFamily(QWebSettings::SerifFont); }
+ void setSerifFontFamily(const QString& f) { s->setFontFamily(QWebSettings::SerifFont,f); }
+ QString sansSerifFontFamily() const { return s->fontFamily(QWebSettings::SansSerifFont); }
+ void setSansSerifFontFamily(const QString& f) { s->setFontFamily(QWebSettings::SansSerifFont,f); }
+ QString cursiveFontFamily() const { return s->fontFamily(QWebSettings::CursiveFont); }
+ void setCursiveFontFamily(const QString& f) { s->setFontFamily(QWebSettings::CursiveFont,f); }
+ QString fantasyFontFamily() const { return s->fontFamily(QWebSettings::FantasyFont); }
+ void setFantasyFontFamily(const QString& f) { s->setFontFamily(QWebSettings::FantasyFont,f); }
+
+ int minimumFontSize() const { return s->fontSize(QWebSettings::MinimumFontSize); }
+ void setMinimumFontSize(int size) { s->setFontSize(QWebSettings::MinimumFontSize,size); }
+ int minimumLogicalFontSize() const { return s->fontSize(QWebSettings::MinimumLogicalFontSize); }
+ void setMinimumLogicalFontSize(int size) { s->setFontSize(QWebSettings::MinimumLogicalFontSize,size); }
+ int defaultFontSize() const { return s->fontSize(QWebSettings::DefaultFontSize); }
+ void setDefaultFontSize(int size) { s->setFontSize(QWebSettings::DefaultFontSize,size); }
+ int defaultFixedFontSize() const { return s->fontSize(QWebSettings::DefaultFixedFontSize); }
+ void setDefaultFixedFontSize(int size) { s->setFontSize(QWebSettings::DefaultFixedFontSize,size); }
+
+ bool autoLoadImages() const { return s->testAttribute(QWebSettings::AutoLoadImages); }
+ void setAutoLoadImages(bool on) { s->setAttribute(QWebSettings::AutoLoadImages, on); }
+ bool javascriptEnabled() const { return s->testAttribute(QWebSettings::JavascriptEnabled); }
+ void setJavascriptEnabled(bool on) { s->setAttribute(QWebSettings::JavascriptEnabled, on); }
+ bool javaEnabled() const { return s->testAttribute(QWebSettings::JavaEnabled); }
+ void setJavaEnabled(bool on) { s->setAttribute(QWebSettings::JavaEnabled, on); }
+ bool pluginsEnabled() const { return s->testAttribute(QWebSettings::PluginsEnabled); }
+ void setPluginsEnabled(bool on) { s->setAttribute(QWebSettings::PluginsEnabled, on); }
+ bool privateBrowsingEnabled() const { return s->testAttribute(QWebSettings::PrivateBrowsingEnabled); }
+ void setPrivateBrowsingEnabled(bool on) { s->setAttribute(QWebSettings::PrivateBrowsingEnabled, on); }
+ bool javascriptCanOpenWindows() const { return s->testAttribute(QWebSettings::JavascriptCanOpenWindows); }
+ void setJavascriptCanOpenWindows(bool on) { s->setAttribute(QWebSettings::JavascriptCanOpenWindows, on); }
+ bool javascriptCanAccessClipboard() const { return s->testAttribute(QWebSettings::JavascriptCanAccessClipboard); }
+ void setJavascriptCanAccessClipboard(bool on) { s->setAttribute(QWebSettings::JavascriptCanAccessClipboard, on); }
+ bool developerExtrasEnabled() const { return s->testAttribute(QWebSettings::DeveloperExtrasEnabled); }
+ void setDeveloperExtrasEnabled(bool on) { s->setAttribute(QWebSettings::DeveloperExtrasEnabled, on); }
+ bool linksIncludedInFocusChain() const { return s->testAttribute(QWebSettings::LinksIncludedInFocusChain); }
+ void setLinksIncludedInFocusChain(bool on) { s->setAttribute(QWebSettings::LinksIncludedInFocusChain, on); }
+ bool zoomTextOnly() const { return s->testAttribute(QWebSettings::ZoomTextOnly); }
+ void setZoomTextOnly(bool on) { s->setAttribute(QWebSettings::ZoomTextOnly, on); }
+ bool printElementBackgrounds() const { return s->testAttribute(QWebSettings::PrintElementBackgrounds); }
+ void setPrintElementBackgrounds(bool on) { s->setAttribute(QWebSettings::PrintElementBackgrounds, on); }
+ bool offlineStorageDatabaseEnabled() const { return s->testAttribute(QWebSettings::OfflineStorageDatabaseEnabled); }
+ void setOfflineStorageDatabaseEnabled(bool on) { s->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, on); }
+ bool offlineWebApplicationCacheEnabled() const { return s->testAttribute(QWebSettings::OfflineWebApplicationCacheEnabled); }
+ void setOfflineWebApplicationCacheEnabled(bool on) { s->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, on); }
+ bool localStorageDatabaseEnabled() const { return s->testAttribute(QWebSettings::LocalStorageDatabaseEnabled); }
+ void setLocalStorageDatabaseEnabled(bool on) { s->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, on); }
+ bool localContentCanAccessRemoteUrls() const { return s->testAttribute(QWebSettings::LocalContentCanAccessRemoteUrls); }
+ void setLocalContentCanAccessRemoteUrls(bool on) { s->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, on); }
+
+ QWebSettings *s;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlGraphicsWebSettings)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/qml/parser/parser.pri b/src/declarative/qml/parser/parser.pri
new file mode 100644
index 0000000..4530479
--- /dev/null
+++ b/src/declarative/qml/parser/parser.pri
@@ -0,0 +1,21 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qmljsast_p.h \
+ $$PWD/qmljsastfwd_p.h \
+ $$PWD/qmljsastvisitor_p.h \
+ $$PWD/qmljsengine_p.h \
+ $$PWD/qmljsgrammar_p.h \
+ $$PWD/qmljslexer_p.h \
+ $$PWD/qmljsmemorypool_p.h \
+ $$PWD/qmljsnodepool_p.h \
+ $$PWD/qmljsparser_p.h \
+ $$PWD/qmljsglobal_p.h
+
+SOURCES += \
+ $$PWD/qmljsast.cpp \
+ $$PWD/qmljsastvisitor.cpp \
+ $$PWD/qmljsengine_p.cpp \
+ $$PWD/qmljsgrammar.cpp \
+ $$PWD/qmljslexer.cpp \
+ $$PWD/qmljsparser.cpp
diff --git a/src/declarative/qml/parser/qmljs.g b/src/declarative/qml/parser/qmljs.g
new file mode 100644
index 0000000..90949d5
--- /dev/null
+++ b/src/declarative/qml/parser/qmljs.g
@@ -0,0 +1,3075 @@
+----------------------------------------------------------------------------
+--
+-- Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+-- All rights reserved.
+-- Contact: Nokia Corporation (qt-info@nokia.com)
+--
+-- This file is part of the QtDeclarative module of the Qt Toolkit.
+--
+-- $QT_BEGIN_LICENSE:LGPL-ONLY$
+-- GNU Lesser General Public License Usage
+-- 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.
+--
+-- If you have questions regarding the use of this file, please contact
+-- Nokia at qt-info@nokia.com.
+-- $QT_END_LICENSE$
+--
+----------------------------------------------------------------------------
+
+%parser QmlJSGrammar
+%decl qmljsparser_p.h
+%impl qmljsparser.cpp
+%expect 2
+%expect-rr 2
+
+%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&="
+%token T_BREAK "break" T_CASE "case" T_CATCH "catch"
+%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue"
+%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/"
+%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
+%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
+%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
+%token T_FUNCTION "function" T_GE ">=" T_GT ">"
+%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
+%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
+%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{"
+%token T_LBRACKET "[" T_LE "<=" T_LPAREN "("
+%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<="
+%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--"
+%token T_NEW "new" T_NOT "!" T_NOT_EQ "!="
+%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|"
+%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+"
+%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?"
+%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
+%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")"
+%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*"
+%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal"
+%token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly"
+%token T_SWITCH "switch" T_THIS "this" T_THROW "throw"
+%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof"
+%token T_VAR "var" T_VOID "void" T_WHILE "while"
+%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
+%token T_NULL "null" T_TRUE "true" T_FALSE "false"
+%token T_CONST "const"
+%token T_DEBUGGER "debugger"
+%token T_RESERVED_WORD "reserved word"
+%token T_MULTILINE_STRING_LITERAL "multiline string literal"
+%token T_COMMENT "comment"
+
+--- context keywords.
+%token T_PUBLIC "public"
+%token T_IMPORT "import"
+%token T_AS "as"
+
+--- feed tokens
+%token T_FEED_UI_PROGRAM
+%token T_FEED_UI_OBJECT_MEMBER
+%token T_FEED_JS_STATEMENT
+%token T_FEED_JS_EXPRESSION
+%token T_FEED_JS_SOURCE_ELEMENT
+%token T_FEED_JS_PROGRAM
+
+%nonassoc SHIFT_THERE
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY
+%nonassoc REDUCE_HERE
+
+%start TopLevel
+
+/./****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtDebug>
+#include <QtGui/QApplication>
+
+#include <string.h>
+
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsast_p.h"
+#include "qmljsnodepool_p.h"
+
+./
+
+/:/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+//
+// 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.
+//
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+#ifndef QMLJSPARSER_P_H
+#define QMLJSPARSER_P_H
+
+#include "qmljsglobal_p.h"
+#include "qmljsgrammar_p.h"
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class QML_PARSER_EXPORT Parser: protected $table
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ NameId *sval;
+ AST::ArgumentList *ArgumentList;
+ AST::CaseBlock *CaseBlock;
+ AST::CaseClause *CaseClause;
+ AST::CaseClauses *CaseClauses;
+ AST::Catch *Catch;
+ AST::DefaultClause *DefaultClause;
+ AST::ElementList *ElementList;
+ AST::Elision *Elision;
+ AST::ExpressionNode *Expression;
+ AST::Finally *Finally;
+ AST::FormalParameterList *FormalParameterList;
+ AST::FunctionBody *FunctionBody;
+ AST::FunctionDeclaration *FunctionDeclaration;
+ AST::Node *Node;
+ AST::PropertyName *PropertyName;
+ AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ AST::SourceElement *SourceElement;
+ AST::SourceElements *SourceElements;
+ AST::Statement *Statement;
+ AST::StatementList *StatementList;
+ AST::Block *Block;
+ AST::VariableDeclaration *VariableDeclaration;
+ AST::VariableDeclarationList *VariableDeclarationList;
+
+ AST::UiProgram *UiProgram;
+ AST::UiImportList *UiImportList;
+ AST::UiImport *UiImport;
+ AST::UiParameterList *UiParameterList;
+ AST::UiPublicMember *UiPublicMember;
+ AST::UiObjectDefinition *UiObjectDefinition;
+ AST::UiObjectInitializer *UiObjectInitializer;
+ AST::UiObjectBinding *UiObjectBinding;
+ AST::UiScriptBinding *UiScriptBinding;
+ AST::UiArrayBinding *UiArrayBinding;
+ AST::UiObjectMember *UiObjectMember;
+ AST::UiObjectMemberList *UiObjectMemberList;
+ AST::UiArrayMemberList *UiArrayMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ AST::UiSignature *UiSignature;
+ AST::UiFormalList *UiFormalList;
+ AST::UiFormal *UiFormal;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ // parse a UI program
+ bool parse() { return parse(T_FEED_UI_PROGRAM); }
+ bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
+ bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
+ bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); }
+ bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
+ bool parseProgram() { return parse(T_FEED_JS_PROGRAM); }
+
+ AST::UiProgram *ast() const
+ { return AST::cast<AST::UiProgram *>(program); }
+
+ AST::Statement *statement() const
+ {
+ if (! program)
+ return 0;
+
+ return program->statementCast();
+ }
+
+ AST::ExpressionNode *expression() const
+ {
+ if (! program)
+ return 0;
+
+ return program->expressionCast();
+ }
+
+ AST::UiObjectMember *uiObjectMember() const
+ {
+ if (! program)
+ return 0;
+
+ return program->uiObjectMemberCast();
+ }
+
+ AST::Node *rootNode() const
+ { return program; }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ bool parse(int startToken);
+
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+ AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
+
+protected:
+ Engine *driver;
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ AST::SourceLocation *location_stack;
+
+ AST::Node *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ AST::SourceLocation loc;
+ };
+
+ double yylval;
+ AST::SourceLocation yylloc;
+ AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+} // end of namespace QmlJS
+
+
+:/
+
+
+/.
+
+#include "qmljsparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+using namespace QmlJS;
+
+QT_QML_BEGIN_NAMESPACE
+
+void Parser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(Engine *driver, int token)
+{
+ return token == $table::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+Parser::Parser(Engine *engine):
+ driver(engine),
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+Parser::~Parser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
+{
+ QVarLengthArray<NameId *, 4> nameIds;
+ QVarLengthArray<AST::SourceLocation, 4> locations;
+
+ AST::ExpressionNode *it = expr;
+ while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) {
+ nameIds.append(m->name);
+ locations.append(m->identifierToken);
+ it = m->base;
+ }
+
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
+ AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name);
+ q->identifierToken = idExpr->identifierToken;
+
+ AST::UiQualifiedId *currentId = q;
+ for (int i = nameIds.size() - 1; i != -1; --i) {
+ currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]);
+ currentId->identifierToken = locations[i];
+ }
+
+ return currentId->finish();
+ }
+
+ return 0;
+}
+
+bool Parser::parse(int startToken)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ token_buffer[0].token = startToken;
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+./
+
+--------------------------------------------------------------------------------------------------------
+-- Declarative UI
+--------------------------------------------------------------------------------------------------------
+
+TopLevel: T_FEED_UI_PROGRAM UiProgram ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_STATEMENT Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_EXPRESSION Expression ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_SOURCE_ELEMENT SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_PROGRAM Program ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+UiProgram: UiImportListOpt UiRootMember ;
+/.
+case $rule_number: {
+ sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+} break;
+./
+
+UiImportListOpt: Empty ;
+UiImportListOpt: UiImportList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+./
+
+UiImportList: UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+./
+
+UiImportList: UiImportList UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+./
+
+ImportId: MemberExpression ;
+
+UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->semicolonToken = loc(2);
+} break;
+./
+
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->semicolonToken = loc(3);
+} break;
+./
+
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->asToken = loc(3);
+ sym(1).UiImport->importIdToken = loc(4);
+ sym(1).UiImport->importId = sym(4).sval;
+ sym(1).UiImport->semicolonToken = loc(5);
+} break;
+./
+
+UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->asToken = loc(2);
+ sym(1).UiImport->importIdToken = loc(3);
+ sym(1).UiImport->importId = sym(3).sval;
+ sym(1).UiImport->semicolonToken = loc(4);
+} break;
+./
+
+
+UiImportHead: T_IMPORT ImportId ;
+/.
+case $rule_number: {
+ AST::UiImport *node = 0;
+
+ if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
+ node->fileNameToken = loc(2);
+ } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
+ QString text;
+ for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
+ text += q->name->asString();
+ if (q->next) text += QLatin1String(".");
+ }
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
+ node->fileNameToken = loc(2);
+ }
+
+ sym(1).Node = node;
+
+ if (! node) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id or a string literal")));
+
+ return false; // ### remove me
+ }
+} break;
+./
+
+Empty: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+UiRootMember: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMember ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMemberList UiObjectMember ;
+/.
+case $rule_number: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+./
+
+UiArrayMemberList: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ;
+/.
+case $rule_number: {
+ AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(),
+ sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectDefinition: UiQualifiedId UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId,
+ sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiObjectDefinition ;
+
+UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON Block ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON EmptyStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding?
+/.case $rule_number:./
+
+/.
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiPropertyType: T_VAR ;
+/.
+case $rule_number:
+./
+UiPropertyType: T_RESERVED_WORD ;
+/.
+case $rule_number: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+./
+
+UiPropertyType: T_IDENTIFIER ;
+
+UiParameterListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+UiParameterListOpt: UiParameterList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).UiParameterList->finish ();
+} break;
+./
+
+UiParameterList: UiPropertyType JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->parameters = sym(4).UiParameterList;
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval);
+ node->typeModifier = sym(2).sval;
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_READONLY T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_READONLY T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+UiObjectMember: VariableStatement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+JsIdentifier: T_IDENTIFIER;
+
+JsIdentifier: T_PROPERTY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_SIGNAL ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_READONLY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+--------------------------------------------------------------------------------------------------------
+-- Expressions
+--------------------------------------------------------------------------------------------------------
+
+PrimaryExpression: T_THIS ;
+/.
+case $rule_number: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NULL ;
+/.
+case $rule_number: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_TRUE ;
+/.
+case $rule_number: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_FALSE ;
+/.
+case $rule_number: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_MULTILINE_STRING_LITERAL ;
+/.case $rule_number:./
+
+PrimaryExpression: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_EQ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET Elision T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ sym(4).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+-- PrimaryExpression: T_LBRACE T_RBRACE ;
+-- /.
+-- case $rule_number: {
+-- sym(1).Node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+-- } break;
+-- ./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LPAREN Expression T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiQualifiedId: MemberExpression ;
+/.
+case $rule_number: {
+ if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
+ QLatin1String("Ignored annotation")));
+
+ sym(1).Expression = mem->base;
+ }
+
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false; // ### recover
+ }
+} break;
+./
+
+ElementList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression);
+} break;
+./
+
+ElementList: Elision AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression);
+} break;
+./
+
+ElementList: ElementList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList,
+ (AST::Elision *) 0, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ElementList: ElementList T_COMMA Elision AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(),
+ sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: Elision T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_IDENTIFIER %prec REDUCE_HERE ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_SIGNAL ;
+/.case $rule_number:./
+
+PropertyName: T_PROPERTY ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: ReservedIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ReservedIdentifier: T_BREAK ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CASE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CATCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONTINUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEFAULT ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DELETE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DO ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_ELSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FALSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FINALLY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FOR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FUNCTION ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_INSTANCEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NEW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NULL ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RETURN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_SWITCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THIS ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THROW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TYPEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VAR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VOID ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WHILE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONST ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEBUGGER ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RESERVED_WORD ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WITH ;
+/.
+case $rule_number:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+./
+
+PropertyIdentifier: JsIdentifier ;
+PropertyIdentifier: ReservedIdentifier ;
+
+MemberExpression: PrimaryExpression ;
+MemberExpression: FunctionExpression ;
+
+MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: MemberExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+NewExpression: MemberExpression ;
+
+NewExpression: T_NEW NewExpression ;
+/.
+case $rule_number: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ArgumentListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ArgumentListOpt: ArgumentList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+./
+
+ArgumentList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+./
+
+ArgumentList: ArgumentList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LeftHandSideExpression: NewExpression ;
+LeftHandSideExpression: CallExpression ;
+PostfixExpression: LeftHandSideExpression ;
+
+PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ;
+/.
+case $rule_number: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ;
+/.
+case $rule_number: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: PostfixExpression ;
+
+UnaryExpression: T_DELETE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_VOID UnaryExpression ;
+/.
+case $rule_number: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TYPEOF UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TILDE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_NOT UnaryExpression ;
+/.
+case $rule_number: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: UnaryExpression ;
+
+MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: MultiplicativeExpression ;
+
+AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: AdditiveExpression ;
+
+ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: ShiftExpression ;
+
+RelationalExpression: RelationalExpression T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_IN ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: ShiftExpression ;
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: RelationalExpression ;
+
+EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: RelationalExpressionNotIn ;
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpression: EqualityExpression ;
+
+BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpressionNotIn: EqualityExpressionNotIn ;
+
+BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpression: BitwiseANDExpression ;
+
+BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ;
+
+BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpression: BitwiseXORExpression ;
+
+BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ;
+
+BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpression: BitwiseORExpression ;
+
+LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ;
+
+LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpression: LogicalANDExpression ;
+
+LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpressionNotIn: LogicalANDExpressionNotIn ;
+
+LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpression: LogicalORExpression ;
+
+ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn ;
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpression: ConditionalExpression ;
+
+AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpressionNotIn: ConditionalExpressionNotIn ;
+
+AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentOperator: T_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+./
+
+AssignmentOperator: T_STAR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+./
+
+AssignmentOperator: T_DIVIDE_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+./
+
+AssignmentOperator: T_REMAINDER_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+./
+
+AssignmentOperator: T_PLUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+./
+
+AssignmentOperator: T_MINUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+./
+
+AssignmentOperator: T_LT_LT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+./
+
+AssignmentOperator: T_AND_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+./
+
+AssignmentOperator: T_XOR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+./
+
+AssignmentOperator: T_OR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+./
+
+Expression: AssignmentExpression ;
+
+Expression: Expression T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionOpt: Expression ;
+
+ExpressionNotIn: AssignmentExpressionNotIn ;
+
+ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionNotInOpt: ExpressionNotIn ;
+
+Statement: Block ;
+Statement: VariableStatement ;
+Statement: EmptyStatement ;
+Statement: ExpressionStatement ;
+Statement: IfStatement ;
+Statement: IterationStatement ;
+Statement: ContinueStatement ;
+Statement: BreakStatement ;
+Statement: ReturnStatement ;
+Statement: WithStatement ;
+Statement: LabelledStatement ;
+Statement: SwitchStatement ;
+Statement: ThrowStatement ;
+Statement: TryStatement ;
+Statement: DebuggerStatement ;
+
+
+Block: T_LBRACE StatementListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+StatementList: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+StatementList: StatementList Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+./
+
+StatementListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+StatementListOpt: StatementList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+./
+
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationKind: T_CONST ;
+/.
+case $rule_number: {
+ sym(1).ival = T_CONST;
+} break;
+./
+
+VariableDeclarationKind: T_VAR ;
+/.
+case $rule_number: {
+ sym(1).ival = T_VAR;
+} break;
+./
+
+VariableDeclarationList: VariableDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ;
+/.
+case $rule_number: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+./
+
+VariableDeclaration: JsIdentifier InitialiserOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Initialiser: T_EQ AssignmentExpression ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserOpt: Initialiser ;
+
+InitialiserNotIn: T_EQ AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserNotInOpt: InitialiserNotIn ;
+
+EmptyStatement: T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ExpressionStatement: Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ;
+/.
+case $rule_number: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+CaseClauses: CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+./
+
+CaseClauses: CaseClauses CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+./
+
+CaseClausesOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+CaseClausesOpt: CaseClauses ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+./
+
+CaseClause: T_CASE Expression T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+DefaultClause: T_DEFAULT T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_SIGNAL T_COLON Statement ;
+/.case $rule_number:./
+
+LabelledStatement: T_PROPERTY T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_IDENTIFIER T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ThrowStatement: T_THROW Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ;
+/.
+case $rule_number: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+Finally: T_FINALLY Block ;
+/.
+case $rule_number: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+DebuggerStatement: T_DEBUGGER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: FormalParameterList T_COMMA JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FormalParameterListOpt: FormalParameterList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+./
+
+FunctionBodyOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FunctionBodyOpt: FunctionBody ;
+
+FunctionBody: SourceElements ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+./
+
+Program: SourceElements ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+./
+
+SourceElements: SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+./
+
+SourceElements: SourceElements SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+./
+
+SourceElement: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+SourceElement: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+./
+
+IdentifierOpt: ;
+/.
+case $rule_number: {
+ sym(1).sval = 0;
+} break;
+./
+
+IdentifierOpt: JsIdentifier ;
+
+PropertyNameAndValueListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+PropertyNameAndValueListOpt: PropertyNameAndValueList ;
+
+/.
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = qApp->translate("QmlParser", "Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ QString msg;
+ int token = token_buffer[0].token;
+ if (token < 0 || token >= TERMINAL_COUNT)
+ msg = qApp->translate("QmlParser", "Syntax error");
+ else
+ msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM ||
+ tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION ||
+ tk == T_FEED_JS_SOURCE_ELEMENT)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = qApp->translate("QmlParser", "Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_QML_END_NAMESPACE
+
+
+./
+/:
+QT_QML_END_NAMESPACE
+
+
+
+#endif // QMLJSPARSER_P_H
+:/
diff --git a/src/declarative/qml/parser/qmljsast.cpp b/src/declarative/qml/parser/qmljsast.cpp
new file mode 100644
index 0000000..e80b05e
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsast.cpp
@@ -0,0 +1,955 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmljsast_p.h"
+
+#include "qmljsastvisitor_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+void Node::accept(Visitor *visitor)
+{
+ if (visitor->preVisit(this)) {
+ accept0(visitor);
+ }
+ visitor->postVisit(this);
+}
+
+void Node::accept(Node *node, Visitor *visitor)
+{
+ if (node)
+ node->accept(visitor);
+}
+
+ExpressionNode *Node::expressionCast()
+{
+ return 0;
+}
+
+BinaryExpression *Node::binaryExpressionCast()
+{
+ return 0;
+}
+
+Statement *Node::statementCast()
+{
+ return 0;
+}
+
+UiObjectMember *Node::uiObjectMemberCast()
+{
+ return 0;
+}
+
+ExpressionNode *ExpressionNode::expressionCast()
+{
+ return this;
+}
+
+BinaryExpression *BinaryExpression::binaryExpressionCast()
+{
+ return this;
+}
+
+Statement *Statement::statementCast()
+{
+ return this;
+}
+
+UiObjectMember *UiObjectMember::uiObjectMemberCast()
+{
+ return this;
+}
+
+void NestedExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void ThisExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NullExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void TrueLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void FalseLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void RegExpLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elements, visitor);
+ accept(elision, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ObjectLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(properties, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ElementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ElementList *it = this; it; it = it->next) {
+ accept(it->elision, visitor);
+ accept(it->expression, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void Elision::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void PropertyNameAndValueList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (PropertyNameAndValueList *it = this; it; it = it->next) {
+ accept(it->name, visitor);
+ accept(it->value, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FieldMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CallExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArgumentList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ArgumentList *it = this; it; it = it->next) {
+ accept(it->expression, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DeleteExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VoidExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TypeOfExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryPlusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryMinusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TildeExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NotExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void BinaryExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left, visitor);
+ accept(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ConditionalExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(ok, visitor);
+ accept(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Expression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left, visitor);
+ accept(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Block::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (StatementList *it = this; it; it = it->next) {
+ accept(it->statement, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarations, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclarationList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (VariableDeclarationList *it = this; it; it = it->next) {
+ accept(it->declaration, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void EmptyStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ExpressionStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void IfStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(ok, visitor);
+ accept(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DoWhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(initialiser, visitor);
+ accept(condition, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarations, visitor);
+ accept(condition, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(initialiser, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ContinueStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void BreakStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ReturnStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WithStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SwitchStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(block, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseBlock::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(clauses, visitor);
+ accept(defaultClause, visitor);
+ accept(moreClauses, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClauses::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (CaseClauses *it = this; it; it = it->next) {
+ accept(it->clause, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DefaultClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LabelledStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ThrowStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TryStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(catchExpression, visitor);
+ accept(finallyExpression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Catch::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Finally::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ accept(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ accept(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FormalParameterList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionBody::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Program::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SourceElements::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SourceElements *it = this; it; it = it->next) {
+ accept(it->element, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DebuggerStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiProgram::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(imports, visitor);
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSignature::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void UiFormalList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiFormalList *it = this; it; it = it->next) {
+ accept(it->formal, visitor);
+ }
+ }
+ visitor->endVisit(this);
+}
+
+void UiFormal::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+ visitor->endVisit(this);
+}
+
+void UiPublicMember::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectDefinition::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedTypeNameId, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectInitializer::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(qualifiedTypeNameId, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiScriptBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = this; it; it = it->next)
+ accept(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiArrayMemberList *it = this; it; it = it->next)
+ accept(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiQualifiedId::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImport::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(importUri, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImportList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(import, visitor);
+ accept(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(sourceElement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+} } // namespace QmlJS::AST
+
+QT_QML_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/qmljsast_p.h b/src/declarative/qml/parser/qmljsast_p.h
new file mode 100644
index 0000000..032fbb1
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsast_p.h
@@ -0,0 +1,2678 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLJSAST_P_H
+#define QMLJSAST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmljsastvisitor_p.h"
+#include "qmljsglobal_p.h"
+
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+#define QMLJS_DECLARE_AST_NODE(name) \
+ enum { K = Kind_##name };
+
+namespace QSOperator // ### rename
+{
+
+enum Op {
+ Add,
+ And,
+ InplaceAnd,
+ Assign,
+ BitAnd,
+ BitOr,
+ BitXor,
+ InplaceSub,
+ Div,
+ InplaceDiv,
+ Equal,
+ Ge,
+ Gt,
+ In,
+ InplaceAdd,
+ InstanceOf,
+ Le,
+ LShift,
+ InplaceLeftShift,
+ Lt,
+ Mod,
+ InplaceMod,
+ Mul,
+ InplaceMul,
+ NotEqual,
+ Or,
+ InplaceOr,
+ RShift,
+ InplaceRightShift,
+ StrictEqual,
+ StrictNotEqual,
+ Sub,
+ URShift,
+ InplaceURightShift,
+ InplaceXor
+};
+
+} // namespace QSOperator
+
+namespace QmlJS {
+class NameId;
+namespace AST {
+
+template <typename _T1, typename _T2>
+_T1 cast(_T2 *ast)
+{
+ if (ast && ast->kind == static_cast<_T1>(0)->K)
+ return static_cast<_T1>(ast);
+
+ return 0;
+}
+
+class QML_PARSER_EXPORT Node
+{
+public:
+ enum Kind {
+ Kind_Undefined,
+
+ Kind_ArgumentList,
+ Kind_ArrayLiteral,
+ Kind_ArrayMemberExpression,
+ Kind_BinaryExpression,
+ Kind_Block,
+ Kind_BreakStatement,
+ Kind_CallExpression,
+ Kind_CaseBlock,
+ Kind_CaseClause,
+ Kind_CaseClauses,
+ Kind_Catch,
+ Kind_ConditionalExpression,
+ Kind_ContinueStatement,
+ Kind_DebuggerStatement,
+ Kind_DefaultClause,
+ Kind_DeleteExpression,
+ Kind_DoWhileStatement,
+ Kind_ElementList,
+ Kind_Elision,
+ Kind_EmptyStatement,
+ Kind_Expression,
+ Kind_ExpressionStatement,
+ Kind_FalseLiteral,
+ Kind_FieldMemberExpression,
+ Kind_Finally,
+ Kind_ForEachStatement,
+ Kind_ForStatement,
+ Kind_FormalParameterList,
+ Kind_FunctionBody,
+ Kind_FunctionDeclaration,
+ Kind_FunctionExpression,
+ Kind_FunctionSourceElement,
+ Kind_IdentifierExpression,
+ Kind_IdentifierPropertyName,
+ Kind_IfStatement,
+ Kind_LabelledStatement,
+ Kind_LocalForEachStatement,
+ Kind_LocalForStatement,
+ Kind_NewExpression,
+ Kind_NewMemberExpression,
+ Kind_NotExpression,
+ Kind_NullExpression,
+ Kind_NumericLiteral,
+ Kind_NumericLiteralPropertyName,
+ Kind_ObjectLiteral,
+ Kind_PostDecrementExpression,
+ Kind_PostIncrementExpression,
+ Kind_PreDecrementExpression,
+ Kind_PreIncrementExpression,
+ Kind_Program,
+ Kind_PropertyName,
+ Kind_PropertyNameAndValueList,
+ Kind_RegExpLiteral,
+ Kind_ReturnStatement,
+ Kind_SourceElement,
+ Kind_SourceElements,
+ Kind_StatementList,
+ Kind_StatementSourceElement,
+ Kind_StringLiteral,
+ Kind_StringLiteralPropertyName,
+ Kind_SwitchStatement,
+ Kind_ThisExpression,
+ Kind_ThrowStatement,
+ Kind_TildeExpression,
+ Kind_TrueLiteral,
+ Kind_TryStatement,
+ Kind_TypeOfExpression,
+ Kind_UnaryMinusExpression,
+ Kind_UnaryPlusExpression,
+ Kind_VariableDeclaration,
+ Kind_VariableDeclarationList,
+ Kind_VariableStatement,
+ Kind_VoidExpression,
+ Kind_WhileStatement,
+ Kind_WithStatement,
+ Kind_NestedExpression,
+
+ Kind_UiArrayBinding,
+ Kind_UiImport,
+ Kind_UiImportList,
+ Kind_UiObjectBinding,
+ Kind_UiObjectDefinition,
+ Kind_UiObjectInitializer,
+ Kind_UiObjectMemberList,
+ Kind_UiArrayMemberList,
+ Kind_UiProgram,
+ Kind_UiParameterList,
+ Kind_UiPublicMember,
+ Kind_UiQualifiedId,
+ Kind_UiScriptBinding,
+ Kind_UiSourceElement,
+ Kind_UiFormal,
+ Kind_UiFormalList,
+ Kind_UiSignature
+ };
+
+ inline Node()
+ : kind(Kind_Undefined) {}
+
+ virtual ~Node() {}
+
+ virtual ExpressionNode *expressionCast();
+ virtual BinaryExpression *binaryExpressionCast();
+ virtual Statement *statementCast();
+ virtual UiObjectMember *uiObjectMemberCast();
+
+ void accept(Visitor *visitor);
+ static void accept(Node *node, Visitor *visitor);
+
+ inline static void acceptChild(Node *node, Visitor *visitor)
+ { return accept(node, visitor); } // ### remove
+
+ virtual void accept0(Visitor *visitor) = 0;
+
+// attributes
+ int kind;
+};
+
+class QML_PARSER_EXPORT ExpressionNode: public Node
+{
+public:
+ ExpressionNode() {}
+ virtual ~ExpressionNode() {}
+
+ virtual ExpressionNode *expressionCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class QML_PARSER_EXPORT Statement: public Node
+{
+public:
+ Statement() {}
+ virtual ~Statement() {}
+
+ virtual Statement *statementCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class QML_PARSER_EXPORT UiFormal: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiFormal)
+
+ UiFormal(NameId *name, NameId *alias = 0)
+ : name(name), alias(alias)
+ { }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ NameId *alias;
+ SourceLocation identifierToken;
+ SourceLocation asToken;
+ SourceLocation aliasToken;
+};
+
+class QML_PARSER_EXPORT UiFormalList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiFormalList)
+
+ UiFormalList(UiFormal *formal)
+ : formal(formal), next(this) {}
+
+ UiFormalList(UiFormalList *previous, UiFormal *formal)
+ : formal(formal)
+ {
+ next = previous->next;
+ previous->next = this;
+ }
+
+ UiFormalList *finish()
+ {
+ UiFormalList *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiFormal *formal;
+ UiFormalList *next;
+};
+
+class QML_PARSER_EXPORT UiSignature: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiSignature)
+
+ UiSignature(UiFormalList *formals = 0)
+ : formals(formals)
+ { }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lparenToken;
+ UiFormalList *formals;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT NestedExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NestedExpression)
+
+ NestedExpression(ExpressionNode *expression)
+ : expression(expression)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lparenToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT ThisExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ThisExpression)
+
+ ThisExpression() { kind = K; }
+ virtual ~ThisExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return thisToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return thisToken; }
+
+// attributes
+ SourceLocation thisToken;
+};
+
+class QML_PARSER_EXPORT IdentifierExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(IdentifierExpression)
+
+ IdentifierExpression(NameId *n):
+ name (n) { kind = K; }
+
+ virtual ~IdentifierExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+// attributes
+ NameId *name;
+ SourceLocation identifierToken;
+};
+
+class QML_PARSER_EXPORT NullExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NullExpression)
+
+ NullExpression() { kind = K; }
+ virtual ~NullExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return nullToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return nullToken; }
+
+// attributes
+ SourceLocation nullToken;
+};
+
+class QML_PARSER_EXPORT TrueLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TrueLiteral)
+
+ TrueLiteral() { kind = K; }
+ virtual ~TrueLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return trueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return trueToken; }
+
+// attributes
+ SourceLocation trueToken;
+};
+
+class QML_PARSER_EXPORT FalseLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FalseLiteral)
+
+ FalseLiteral() { kind = K; }
+ virtual ~FalseLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return falseToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return falseToken; }
+
+// attributes
+ SourceLocation falseToken;
+};
+
+class QML_PARSER_EXPORT NumericLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NumericLiteral)
+
+ NumericLiteral(double v):
+ value(v) { kind = K; }
+ virtual ~NumericLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ double value;
+ SourceLocation literalToken;
+};
+
+class QML_PARSER_EXPORT StringLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StringLiteral)
+
+ StringLiteral(NameId *v):
+ value (v) { kind = K; }
+
+ virtual ~StringLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ NameId *value;
+ SourceLocation literalToken;
+};
+
+class QML_PARSER_EXPORT RegExpLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(RegExpLiteral)
+
+ RegExpLiteral(NameId *p, int f):
+ pattern (p), flags (f) { kind = K; }
+
+ virtual ~RegExpLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ NameId *pattern;
+ int flags;
+ SourceLocation literalToken;
+};
+
+class QML_PARSER_EXPORT ArrayLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ArrayLiteral)
+
+ ArrayLiteral(Elision *e):
+ elements (0), elision (e)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts):
+ elements (elts), elision (0)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts, Elision *e):
+ elements (elts), elision (e)
+ { kind = K; }
+
+ virtual ~ArrayLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbracketToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ElementList *elements;
+ Elision *elision;
+ SourceLocation lbracketToken;
+ SourceLocation commaToken;
+ SourceLocation rbracketToken;
+};
+
+class QML_PARSER_EXPORT ObjectLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ObjectLiteral)
+
+ ObjectLiteral():
+ properties (0) { kind = K; }
+
+ ObjectLiteral(PropertyNameAndValueList *plist):
+ properties (plist) { kind = K; }
+
+ virtual ~ObjectLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ PropertyNameAndValueList *properties;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class QML_PARSER_EXPORT ElementList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ElementList)
+
+ ElementList(Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr), next (this)
+ { kind = K; }
+
+ ElementList(ElementList *previous, Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ElementList() {}
+
+ inline ElementList *finish ()
+ {
+ ElementList *front = next;
+ next = 0;
+ return front;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Elision *elision;
+ ExpressionNode *expression;
+ ElementList *next;
+ SourceLocation commaToken;
+};
+
+class QML_PARSER_EXPORT Elision: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Elision)
+
+ Elision():
+ next (this) { kind = K; }
+
+ Elision(Elision *previous)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~Elision() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline Elision *finish ()
+ {
+ Elision *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Elision *next;
+ SourceLocation commaToken;
+};
+
+class QML_PARSER_EXPORT PropertyNameAndValueList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PropertyNameAndValueList)
+
+ PropertyNameAndValueList(PropertyName *n, ExpressionNode *v):
+ name (n), value (v), next (this)
+ { kind = K; }
+
+ PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v):
+ name (n), value (v)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~PropertyNameAndValueList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline PropertyNameAndValueList *finish ()
+ {
+ PropertyNameAndValueList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ PropertyName *name;
+ ExpressionNode *value;
+ PropertyNameAndValueList *next;
+ SourceLocation colonToken;
+ SourceLocation commaToken;
+};
+
+class QML_PARSER_EXPORT PropertyName: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PropertyName)
+
+ PropertyName() { kind = K; }
+ virtual ~PropertyName() {}
+
+// attributes
+ SourceLocation propertyNameToken;
+};
+
+class QML_PARSER_EXPORT IdentifierPropertyName: public PropertyName
+{
+public:
+ QMLJS_DECLARE_AST_NODE(IdentifierPropertyName)
+
+ IdentifierPropertyName(NameId *n):
+ id (n) { kind = K; }
+
+ virtual ~IdentifierPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *id;
+};
+
+class QML_PARSER_EXPORT StringLiteralPropertyName: public PropertyName
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StringLiteralPropertyName)
+
+ StringLiteralPropertyName(NameId *n):
+ id (n) { kind = K; }
+ virtual ~StringLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *id;
+};
+
+class QML_PARSER_EXPORT NumericLiteralPropertyName: public PropertyName
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NumericLiteralPropertyName)
+
+ NumericLiteralPropertyName(double n):
+ id (n) { kind = K; }
+ virtual ~NumericLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ double id;
+};
+
+class QML_PARSER_EXPORT ArrayMemberExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ArrayMemberExpression)
+
+ ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e):
+ base (b), expression (e)
+ { kind = K; }
+
+ virtual ~ArrayMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ExpressionNode *base;
+ ExpressionNode *expression;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+class QML_PARSER_EXPORT FieldMemberExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FieldMemberExpression)
+
+ FieldMemberExpression(ExpressionNode *b, NameId *n):
+ base (b), name (n)
+ { kind = K; }
+
+ virtual ~FieldMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+ // attributes
+ ExpressionNode *base;
+ NameId *name;
+ SourceLocation dotToken;
+ SourceLocation identifierToken;
+};
+
+class QML_PARSER_EXPORT NewMemberExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NewMemberExpression)
+
+ NewMemberExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~NewMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+ // attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation newToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT NewExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NewExpression)
+
+ NewExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NewExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation newToken;
+};
+
+class QML_PARSER_EXPORT CallExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CallExpression)
+
+ CallExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~CallExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT ArgumentList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ArgumentList)
+
+ ArgumentList(ExpressionNode *e):
+ expression (e), next (this)
+ { kind = K; }
+
+ ArgumentList(ArgumentList *previous, ExpressionNode *e):
+ expression (e)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ArgumentList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline ArgumentList *finish ()
+ {
+ ArgumentList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ ExpressionNode *expression;
+ ArgumentList *next;
+ SourceLocation commaToken;
+};
+
+class QML_PARSER_EXPORT PostIncrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PostIncrementExpression)
+
+ PostIncrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return incrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation incrementToken;
+};
+
+class QML_PARSER_EXPORT PostDecrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PostDecrementExpression)
+
+ PostDecrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return decrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation decrementToken;
+};
+
+class QML_PARSER_EXPORT DeleteExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DeleteExpression)
+
+ DeleteExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+ virtual ~DeleteExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return deleteToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation deleteToken;
+};
+
+class QML_PARSER_EXPORT VoidExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VoidExpression)
+
+ VoidExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~VoidExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return voidToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation voidToken;
+};
+
+class QML_PARSER_EXPORT TypeOfExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TypeOfExpression)
+
+ TypeOfExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TypeOfExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return typeofToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation typeofToken;
+};
+
+class QML_PARSER_EXPORT PreIncrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PreIncrementExpression)
+
+ PreIncrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return incrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation incrementToken;
+};
+
+class QML_PARSER_EXPORT PreDecrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PreDecrementExpression)
+
+ PreDecrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return decrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation decrementToken;
+};
+
+class QML_PARSER_EXPORT UnaryPlusExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UnaryPlusExpression)
+
+ UnaryPlusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryPlusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return plusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation plusToken;
+};
+
+class QML_PARSER_EXPORT UnaryMinusExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UnaryMinusExpression)
+
+ UnaryMinusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryMinusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return minusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation minusToken;
+};
+
+class QML_PARSER_EXPORT TildeExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TildeExpression)
+
+ TildeExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TildeExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tildeToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation tildeToken;
+};
+
+class QML_PARSER_EXPORT NotExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NotExpression)
+
+ NotExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NotExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return notToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation notToken;
+};
+
+class QML_PARSER_EXPORT BinaryExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(BinaryExpression)
+
+ BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r):
+ left (l), op (o), right (r)
+ { kind = K; }
+
+ virtual ~BinaryExpression() {}
+
+ virtual BinaryExpression *binaryExpressionCast();
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ int op;
+ ExpressionNode *right;
+ SourceLocation operatorToken;
+};
+
+class QML_PARSER_EXPORT ConditionalExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ConditionalExpression)
+
+ ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~ConditionalExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return ko->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ ExpressionNode *ok;
+ ExpressionNode *ko;
+ SourceLocation questionToken;
+ SourceLocation colonToken;
+};
+
+class QML_PARSER_EXPORT Expression: public ExpressionNode // ### rename
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Expression)
+
+ Expression(ExpressionNode *l, ExpressionNode *r):
+ left (l), right (r) { kind = K; }
+
+ virtual ~Expression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ ExpressionNode *right;
+ SourceLocation commaToken;
+};
+
+class QML_PARSER_EXPORT Block: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Block)
+
+ Block(StatementList *slist):
+ statements (slist) { kind = K; }
+
+ virtual ~Block() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+ // attributes
+ StatementList *statements;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class QML_PARSER_EXPORT StatementList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StatementList)
+
+ StatementList(Statement *stmt):
+ statement (stmt), next (this)
+ { kind = K; }
+
+ StatementList(StatementList *previous, Statement *stmt):
+ statement (stmt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~StatementList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline StatementList *finish ()
+ {
+ StatementList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Statement *statement;
+ StatementList *next;
+};
+
+class QML_PARSER_EXPORT VariableStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VariableStatement)
+
+ VariableStatement(VariableDeclarationList *vlist):
+ declarations (vlist)
+ { kind = K; }
+
+ virtual ~VariableStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return declarationKindToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ VariableDeclarationList *declarations;
+ SourceLocation declarationKindToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT VariableDeclaration: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VariableDeclaration)
+
+ VariableDeclaration(NameId *n, ExpressionNode *e):
+ name (n), expression (e), readOnly(false)
+ { kind = K; }
+
+ virtual ~VariableDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ ExpressionNode *expression;
+ bool readOnly;
+ SourceLocation identifierToken;
+};
+
+class QML_PARSER_EXPORT VariableDeclarationList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VariableDeclarationList)
+
+ VariableDeclarationList(VariableDeclaration *decl):
+ declaration (decl), next (this)
+ { kind = K; }
+
+ VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl):
+ declaration (decl)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~VariableDeclarationList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline VariableDeclarationList *finish (bool readOnly)
+ {
+ VariableDeclarationList *front = next;
+ next = 0;
+ if (readOnly) {
+ VariableDeclarationList *vdl;
+ for (vdl = front; vdl != 0; vdl = vdl->next)
+ vdl->declaration->readOnly = true;
+ }
+ return front;
+ }
+
+// attributes
+ VariableDeclaration *declaration;
+ VariableDeclarationList *next;
+ SourceLocation commaToken;
+};
+
+class QML_PARSER_EXPORT EmptyStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(EmptyStatement)
+
+ EmptyStatement() { kind = K; }
+ virtual ~EmptyStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return semicolonToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT ExpressionStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ExpressionStatement)
+
+ ExpressionStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ExpressionStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT IfStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(IfStatement)
+
+ IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~IfStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return ifToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (ko)
+ return ko->lastSourceLocation();
+
+ return ok->lastSourceLocation();
+ }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *ok;
+ Statement *ko;
+ SourceLocation ifToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation elseToken;
+};
+
+class QML_PARSER_EXPORT DoWhileStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DoWhileStatement)
+
+ DoWhileStatement(Statement *stmt, ExpressionNode *e):
+ statement (stmt), expression (e)
+ { kind = K; }
+
+ virtual ~DoWhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return doToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ Statement *statement;
+ ExpressionNode *expression;
+ SourceLocation doToken;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT WhileStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(WhileStatement)
+
+ WhileStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return whileToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT ForStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ForStatement)
+
+ ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ initialiser (i), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT LocalForStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(LocalForStatement)
+
+ LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ declarations (vlist), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclarationList *declarations;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT ForEachStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ForEachStatement)
+
+ ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt):
+ initialiser (i), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT LocalForEachStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(LocalForEachStatement)
+
+ LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt):
+ declaration (v), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclaration *declaration;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT ContinueStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ContinueStatement)
+
+ ContinueStatement(NameId *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~ContinueStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return continueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ NameId *label;
+ SourceLocation continueToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT BreakStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(BreakStatement)
+
+ BreakStatement(NameId *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~BreakStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return breakToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ NameId *label;
+ SourceLocation breakToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT ReturnStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ReturnStatement)
+
+ ReturnStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ReturnStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return returnToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation returnToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT WithStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(WithStatement)
+
+ WithStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WithStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return withToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation withToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT CaseBlock: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CaseBlock)
+
+ CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0):
+ clauses (c), defaultClause (d), moreClauses (r)
+ { kind = K; }
+
+ virtual ~CaseBlock() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ CaseClauses *clauses;
+ DefaultClause *defaultClause;
+ CaseClauses *moreClauses;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class QML_PARSER_EXPORT SwitchStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(SwitchStatement)
+
+ SwitchStatement(ExpressionNode *e, CaseBlock *b):
+ expression (e), block (b)
+ { kind = K; }
+
+ virtual ~SwitchStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return switchToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return block->rbraceToken; }
+
+// attributes
+ ExpressionNode *expression;
+ CaseBlock *block;
+ SourceLocation switchToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT CaseClauses: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CaseClauses)
+
+ CaseClauses(CaseClause *c):
+ clause (c), next (this)
+ { kind = K; }
+
+ CaseClauses(CaseClauses *previous, CaseClause *c):
+ clause (c)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~CaseClauses() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline CaseClauses *finish ()
+ {
+ CaseClauses *front = next;
+ next = 0;
+ return front;
+ }
+
+//attributes
+ CaseClause *clause;
+ CaseClauses *next;
+};
+
+class QML_PARSER_EXPORT CaseClause: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CaseClause)
+
+ CaseClause(ExpressionNode *e, StatementList *slist):
+ expression (e), statements (slist)
+ { kind = K; }
+
+ virtual ~CaseClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ ExpressionNode *expression;
+ StatementList *statements;
+ SourceLocation caseToken;
+ SourceLocation colonToken;
+};
+
+class QML_PARSER_EXPORT DefaultClause: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DefaultClause)
+
+ DefaultClause(StatementList *slist):
+ statements (slist)
+ { kind = K; }
+
+ virtual ~DefaultClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ StatementList *statements;
+ SourceLocation defaultToken;
+ SourceLocation colonToken;
+};
+
+class QML_PARSER_EXPORT LabelledStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(LabelledStatement)
+
+ LabelledStatement(NameId *l, Statement *stmt):
+ label (l), statement (stmt)
+ { kind = K; }
+
+ virtual ~LabelledStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ NameId *label;
+ Statement *statement;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+};
+
+class QML_PARSER_EXPORT ThrowStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ThrowStatement)
+
+ ThrowStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ThrowStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return throwToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ ExpressionNode *expression;
+ SourceLocation throwToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT Catch: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Catch)
+
+ Catch(NameId *n, Block *stmt):
+ name (n), statement (stmt)
+ { kind = K; }
+
+ virtual ~Catch() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ Block *statement;
+ SourceLocation catchToken;
+ SourceLocation lparenToken;
+ SourceLocation identifierToken;
+ SourceLocation rparenToken;
+};
+
+class QML_PARSER_EXPORT Finally: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Finally)
+
+ Finally(Block *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~Finally() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Block *statement;
+ SourceLocation finallyToken;
+};
+
+class QML_PARSER_EXPORT TryStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TryStatement)
+
+ TryStatement(Statement *stmt, Catch *c, Finally *f):
+ statement (stmt), catchExpression (c), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Finally *f):
+ statement (stmt), catchExpression (0), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Catch *c):
+ statement (stmt), catchExpression (c), finallyExpression (0)
+ { kind = K; }
+
+ virtual ~TryStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tryToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (finallyExpression)
+ return finallyExpression->statement->rbraceToken;
+ else if (catchExpression)
+ return catchExpression->statement->rbraceToken;
+
+ return statement->lastSourceLocation();
+ }
+
+// attributes
+ Statement *statement;
+ Catch *catchExpression;
+ Finally *finallyExpression;
+ SourceLocation tryToken;
+};
+
+class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionExpression)
+
+ FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b):
+ name (n), formals (f), body (b)
+ { kind = K; }
+
+ virtual ~FunctionExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return functionToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ NameId *name;
+ FormalParameterList *formals;
+ FunctionBody *body;
+ SourceLocation functionToken;
+ SourceLocation identifierToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionDeclaration)
+
+ FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b):
+ FunctionExpression(n, f, b)
+ { kind = K; }
+
+ virtual ~FunctionDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+};
+
+class QML_PARSER_EXPORT FormalParameterList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FormalParameterList)
+
+ FormalParameterList(NameId *n):
+ name (n), next (this)
+ { kind = K; }
+
+ FormalParameterList(FormalParameterList *previous, NameId *n):
+ name (n)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~FormalParameterList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline FormalParameterList *finish ()
+ {
+ FormalParameterList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ NameId *name;
+ FormalParameterList *next;
+ SourceLocation commaToken;
+ SourceLocation identifierToken;
+};
+
+class QML_PARSER_EXPORT FunctionBody: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionBody)
+
+ FunctionBody(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~FunctionBody() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class QML_PARSER_EXPORT Program: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Program)
+
+ Program(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~Program() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class QML_PARSER_EXPORT SourceElements: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(SourceElements)
+
+ SourceElements(SourceElement *elt):
+ element (elt), next (this)
+ { kind = K; }
+
+ SourceElements(SourceElements *previous, SourceElement *elt):
+ element (elt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~SourceElements() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline SourceElements *finish ()
+ {
+ SourceElements *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ SourceElement *element;
+ SourceElements *next;
+};
+
+class QML_PARSER_EXPORT SourceElement: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(SourceElement)
+
+ inline SourceElement()
+ { kind = K; }
+
+ virtual ~SourceElement() {}
+};
+
+class QML_PARSER_EXPORT FunctionSourceElement: public SourceElement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionSourceElement)
+
+ FunctionSourceElement(FunctionDeclaration *f):
+ declaration (f)
+ { kind = K; }
+
+ virtual ~FunctionSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ FunctionDeclaration *declaration;
+};
+
+class QML_PARSER_EXPORT StatementSourceElement: public SourceElement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StatementSourceElement)
+
+ StatementSourceElement(Statement *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~StatementSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Statement *statement;
+};
+
+class QML_PARSER_EXPORT DebuggerStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DebuggerStatement)
+
+ DebuggerStatement()
+ { kind = K; }
+
+ virtual ~DebuggerStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return debuggerToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation debuggerToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT UiProgram: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiProgram)
+
+ UiProgram(UiImportList *imports, UiObjectMemberList *members)
+ : imports(imports), members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImportList *imports;
+ UiObjectMemberList *members;
+};
+
+class QML_PARSER_EXPORT UiQualifiedId: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiQualifiedId)
+
+ UiQualifiedId(NameId *name)
+ : next(this), name(name)
+ { kind = K; }
+
+ UiQualifiedId(UiQualifiedId *previous, NameId *name)
+ : name(name)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~UiQualifiedId() {}
+
+ UiQualifiedId *finish()
+ {
+ UiQualifiedId *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *next;
+ NameId *name;
+ SourceLocation identifierToken;
+};
+
+class QML_PARSER_EXPORT UiImport: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiImport)
+
+ UiImport(NameId *fileName)
+ : fileName(fileName), importUri(0), importId(0)
+ { kind = K; }
+
+ UiImport(UiQualifiedId *uri)
+ : fileName(0), importUri(uri), importId(0)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return importToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *fileName;
+ UiQualifiedId *importUri;
+ NameId *importId;
+ SourceLocation importToken;
+ SourceLocation fileNameToken;
+ SourceLocation versionToken;
+ SourceLocation asToken;
+ SourceLocation importIdToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT UiImportList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiImportList)
+
+ UiImportList(UiImport *import)
+ : import(import),
+ next(this)
+ { kind = K; }
+
+ UiImportList(UiImportList *previous, UiImport *import)
+ : import(import)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (import) return import->firstSourceLocation();
+ else return SourceLocation();
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ for (const UiImportList *it = this; it; it = it->next)
+ if (!it->next && it->import)
+ return it->import->lastSourceLocation();
+
+ return SourceLocation();
+ }
+
+ UiImportList *finish()
+ {
+ UiImportList *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImport *import;
+ UiImportList *next;
+};
+
+class QML_PARSER_EXPORT UiObjectMember: public Node
+{
+public:
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+
+ virtual UiObjectMember *uiObjectMemberCast();
+};
+
+class QML_PARSER_EXPORT UiObjectMemberList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectMemberList)
+
+ UiObjectMemberList(UiObjectMember *member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+ UiObjectMemberList *finish()
+ {
+ UiObjectMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiObjectMemberList *next;
+ UiObjectMember *member;
+};
+
+class QML_PARSER_EXPORT UiArrayMemberList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiArrayMemberList)
+
+ UiArrayMemberList(UiObjectMember *member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+ UiArrayMemberList *finish()
+ {
+ UiArrayMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiArrayMemberList *next;
+ UiObjectMember *member;
+ SourceLocation commaToken;
+};
+
+class QML_PARSER_EXPORT UiObjectInitializer: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectInitializer)
+
+ UiObjectInitializer(UiObjectMemberList *members)
+ : members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lbraceToken;
+ UiObjectMemberList *members;
+ SourceLocation rbraceToken;
+};
+
+class QML_PARSER_EXPORT UiParameterList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiParameterList)
+
+ UiParameterList(NameId *t, NameId *n):
+ type (t), name (n), next (this)
+ { kind = K; }
+
+ UiParameterList(UiParameterList *previous, NameId *t, NameId *n):
+ type (t), name (n)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~UiParameterList() {}
+
+ virtual void accept0(Visitor *) {}
+
+ inline UiParameterList *finish ()
+ {
+ UiParameterList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ NameId *type;
+ NameId *name;
+ UiParameterList *next;
+ SourceLocation commaToken;
+ SourceLocation identifierToken;
+};
+
+class QML_PARSER_EXPORT UiPublicMember: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiPublicMember)
+
+ UiPublicMember(NameId *memberType,
+ NameId *name)
+ : type(Property), typeModifier(0), memberType(memberType), name(name), expression(0), isDefaultMember(false), isReadonlyMember(false), parameters(0)
+ { kind = K; }
+
+ UiPublicMember(NameId *memberType,
+ NameId *name,
+ ExpressionNode *expression)
+ : type(Property), typeModifier(0), memberType(memberType), name(name), expression(expression), isDefaultMember(false), isReadonlyMember(false), parameters(0)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (defaultToken.isValid())
+ return defaultToken;
+ else if (readonlyToken.isValid())
+ return readonlyToken;
+
+ return propertyToken;
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ return semicolonToken;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ enum { Signal, Property } type;
+ NameId *typeModifier;
+ NameId *memberType;
+ NameId *name;
+ ExpressionNode *expression;
+ bool isDefaultMember;
+ bool isReadonlyMember;
+ UiParameterList *parameters;
+ SourceLocation defaultToken;
+ SourceLocation readonlyToken;
+ SourceLocation propertyToken;
+ SourceLocation typeModifierToken;
+ SourceLocation typeToken;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+ SourceLocation semicolonToken;
+};
+
+class QML_PARSER_EXPORT UiObjectDefinition: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectDefinition)
+
+ UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId,
+ UiObjectInitializer *initializer)
+ : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedTypeNameId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return initializer->rbraceToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedTypeNameId;
+ UiObjectInitializer *initializer;
+};
+
+class QML_PARSER_EXPORT UiSourceElement: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiSourceElement)
+
+ UiSourceElement(Node *sourceElement)
+ : sourceElement(sourceElement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->firstSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->firstSourceLocation();
+
+ return SourceLocation();
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->lastSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->lastSourceLocation();
+
+ return SourceLocation();
+ }
+
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Node *sourceElement;
+};
+
+class QML_PARSER_EXPORT UiObjectBinding: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectBinding)
+
+ UiObjectBinding(UiQualifiedId *qualifiedId,
+ UiQualifiedId *qualifiedTypeNameId,
+ UiObjectInitializer *initializer)
+ : qualifiedId(qualifiedId),
+ qualifiedTypeNameId(qualifiedTypeNameId),
+ initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return initializer->rbraceToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiQualifiedId *qualifiedTypeNameId;
+ UiObjectInitializer *initializer;
+ SourceLocation colonToken;
+};
+
+class QML_PARSER_EXPORT UiScriptBinding: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiScriptBinding)
+
+ UiScriptBinding(UiQualifiedId *qualifiedId,
+ Statement *statement)
+ : qualifiedId(qualifiedId),
+ statement(statement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ Statement *statement;
+ SourceLocation colonToken;
+};
+
+class QML_PARSER_EXPORT UiArrayBinding: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiArrayBinding)
+
+ UiArrayBinding(UiQualifiedId *qualifiedId,
+ UiArrayMemberList *members)
+ : qualifiedId(qualifiedId),
+ members(members)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiArrayMemberList *members;
+ SourceLocation colonToken;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+} } // namespace AST
+
+
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsastfwd_p.h b/src/declarative/qml/parser/qmljsastfwd_p.h
new file mode 100644
index 0000000..f571a2e
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsastfwd_p.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLJSAST_FWD_P_H
+#define QMLJSAST_FWD_P_H
+
+#include "qmljsglobal_p.h"
+
+#include <QtCore/qglobal.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+class SourceLocation
+{
+public:
+ SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
+ : offset(offset), length(length),
+ startLine(line), startColumn(column)
+ { }
+
+ bool isValid() const { return length != 0; }
+
+ quint32 begin() const { return offset; }
+ quint32 end() const { return offset + length; }
+
+// attributes
+ // ### encode
+ quint32 offset;
+ quint32 length;
+ quint32 startLine;
+ quint32 startColumn;
+};
+
+class Visitor;
+class Node;
+class ExpressionNode;
+class Statement;
+class ThisExpression;
+class IdentifierExpression;
+class NullExpression;
+class TrueLiteral;
+class FalseLiteral;
+class NumericLiteral;
+class StringLiteral;
+class RegExpLiteral;
+class ArrayLiteral;
+class ObjectLiteral;
+class ElementList;
+class Elision;
+class PropertyNameAndValueList;
+class PropertyName;
+class IdentifierPropertyName;
+class StringLiteralPropertyName;
+class NumericLiteralPropertyName;
+class ArrayMemberExpression;
+class FieldMemberExpression;
+class NewMemberExpression;
+class NewExpression;
+class CallExpression;
+class ArgumentList;
+class PostIncrementExpression;
+class PostDecrementExpression;
+class DeleteExpression;
+class VoidExpression;
+class TypeOfExpression;
+class PreIncrementExpression;
+class PreDecrementExpression;
+class UnaryPlusExpression;
+class UnaryMinusExpression;
+class TildeExpression;
+class NotExpression;
+class BinaryExpression;
+class ConditionalExpression;
+class Expression; // ### rename
+class Block;
+class StatementList;
+class VariableStatement;
+class VariableDeclarationList;
+class VariableDeclaration;
+class EmptyStatement;
+class ExpressionStatement;
+class IfStatement;
+class DoWhileStatement;
+class WhileStatement;
+class ForStatement;
+class LocalForStatement;
+class ForEachStatement;
+class LocalForEachStatement;
+class ContinueStatement;
+class BreakStatement;
+class ReturnStatement;
+class WithStatement;
+class SwitchStatement;
+class CaseBlock;
+class CaseClauses;
+class CaseClause;
+class DefaultClause;
+class LabelledStatement;
+class ThrowStatement;
+class TryStatement;
+class Catch;
+class Finally;
+class FunctionDeclaration;
+class FunctionExpression;
+class FormalParameterList;
+class FunctionBody;
+class Program;
+class SourceElements;
+class SourceElement;
+class FunctionSourceElement;
+class StatementSourceElement;
+class DebuggerStatement;
+class NestedExpression;
+
+// ui elements
+class UiProgram;
+class UiImportList;
+class UiImport;
+class UiPublicMember;
+class UiObjectDefinition;
+class UiObjectInitializer;
+class UiObjectBinding;
+class UiScriptBinding;
+class UiSourceElement;
+class UiArrayBinding;
+class UiObjectMember;
+class UiObjectMemberList;
+class UiArrayMemberList;
+class UiQualifiedId;
+class UiFormalList;
+class UiFormal;
+class UiSignature;
+
+} } // namespace AST
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsastvisitor.cpp b/src/declarative/qml/parser/qmljsastvisitor.cpp
new file mode 100644
index 0000000..1290c89
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsastvisitor.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmljsastvisitor_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+} } // namespace QmlJS::AST
+
+QT_QML_END_NAMESPACE
diff --git a/src/declarative/qml/parser/qmljsastvisitor_p.h b/src/declarative/qml/parser/qmljsastvisitor_p.h
new file mode 100644
index 0000000..1b50bcc
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsastvisitor_p.h
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLJSASTVISITOR_P_H
+#define QMLJSASTVISITOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmljsastfwd_p.h"
+#include "qmljsglobal_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+class QML_PARSER_EXPORT Visitor
+{
+public:
+ Visitor();
+ virtual ~Visitor();
+
+ virtual bool preVisit(Node *) { return true; }
+ virtual void postVisit(Node *) {}
+
+ // Ui
+ virtual bool visit(UiProgram *) { return true; }
+ virtual bool visit(UiImportList *) { return true; }
+ virtual bool visit(UiImport *) { return true; }
+ virtual bool visit(UiPublicMember *) { return true; }
+ virtual bool visit(UiSourceElement *) { return true; }
+ virtual bool visit(UiObjectDefinition *) { return true; }
+ virtual bool visit(UiObjectInitializer *) { return true; }
+ virtual bool visit(UiObjectBinding *) { return true; }
+ virtual bool visit(UiScriptBinding *) { return true; }
+ virtual bool visit(UiArrayBinding *) { return true; }
+ virtual bool visit(UiObjectMemberList *) { return true; }
+ virtual bool visit(UiArrayMemberList *) { return true; }
+ virtual bool visit(UiQualifiedId *) { return true; }
+ virtual bool visit(UiSignature *) { return true; }
+ virtual bool visit(UiFormalList *) { return true; }
+ virtual bool visit(UiFormal *) { return true; }
+
+ virtual void endVisit(UiProgram *) {}
+ virtual void endVisit(UiImportList *) {}
+ virtual void endVisit(UiImport *) {}
+ virtual void endVisit(UiPublicMember *) {}
+ virtual void endVisit(UiSourceElement *) {}
+ virtual void endVisit(UiObjectDefinition *) {}
+ virtual void endVisit(UiObjectInitializer *) {}
+ virtual void endVisit(UiObjectBinding *) {}
+ virtual void endVisit(UiScriptBinding *) {}
+ virtual void endVisit(UiArrayBinding *) {}
+ virtual void endVisit(UiObjectMemberList *) {}
+ virtual void endVisit(UiArrayMemberList *) {}
+ virtual void endVisit(UiQualifiedId *) {}
+ virtual void endVisit(UiSignature *) {}
+ virtual void endVisit(UiFormalList *) {}
+ virtual void endVisit(UiFormal *) {}
+
+ // QmlJS
+ virtual bool visit(ThisExpression *) { return true; }
+ virtual void endVisit(ThisExpression *) {}
+
+ virtual bool visit(IdentifierExpression *) { return true; }
+ virtual void endVisit(IdentifierExpression *) {}
+
+ virtual bool visit(NullExpression *) { return true; }
+ virtual void endVisit(NullExpression *) {}
+
+ virtual bool visit(TrueLiteral *) { return true; }
+ virtual void endVisit(TrueLiteral *) {}
+
+ virtual bool visit(FalseLiteral *) { return true; }
+ virtual void endVisit(FalseLiteral *) {}
+
+ virtual bool visit(StringLiteral *) { return true; }
+ virtual void endVisit(StringLiteral *) {}
+
+ virtual bool visit(NumericLiteral *) { return true; }
+ virtual void endVisit(NumericLiteral *) {}
+
+ virtual bool visit(RegExpLiteral *) { return true; }
+ virtual void endVisit(RegExpLiteral *) {}
+
+ virtual bool visit(ArrayLiteral *) { return true; }
+ virtual void endVisit(ArrayLiteral *) {}
+
+ virtual bool visit(ObjectLiteral *) { return true; }
+ virtual void endVisit(ObjectLiteral *) {}
+
+ virtual bool visit(ElementList *) { return true; }
+ virtual void endVisit(ElementList *) {}
+
+ virtual bool visit(Elision *) { return true; }
+ virtual void endVisit(Elision *) {}
+
+ virtual bool visit(PropertyNameAndValueList *) { return true; }
+ virtual void endVisit(PropertyNameAndValueList *) {}
+
+ virtual bool visit(NestedExpression *) { return true; }
+ virtual void endVisit(NestedExpression *) {}
+
+ virtual bool visit(IdentifierPropertyName *) { return true; }
+ virtual void endVisit(IdentifierPropertyName *) {}
+
+ virtual bool visit(StringLiteralPropertyName *) { return true; }
+ virtual void endVisit(StringLiteralPropertyName *) {}
+
+ virtual bool visit(NumericLiteralPropertyName *) { return true; }
+ virtual void endVisit(NumericLiteralPropertyName *) {}
+
+ virtual bool visit(ArrayMemberExpression *) { return true; }
+ virtual void endVisit(ArrayMemberExpression *) {}
+
+ virtual bool visit(FieldMemberExpression *) { return true; }
+ virtual void endVisit(FieldMemberExpression *) {}
+
+ virtual bool visit(NewMemberExpression *) { return true; }
+ virtual void endVisit(NewMemberExpression *) {}
+
+ virtual bool visit(NewExpression *) { return true; }
+ virtual void endVisit(NewExpression *) {}
+
+ virtual bool visit(CallExpression *) { return true; }
+ virtual void endVisit(CallExpression *) {}
+
+ virtual bool visit(ArgumentList *) { return true; }
+ virtual void endVisit(ArgumentList *) {}
+
+ virtual bool visit(PostIncrementExpression *) { return true; }
+ virtual void endVisit(PostIncrementExpression *) {}
+
+ virtual bool visit(PostDecrementExpression *) { return true; }
+ virtual void endVisit(PostDecrementExpression *) {}
+
+ virtual bool visit(DeleteExpression *) { return true; }
+ virtual void endVisit(DeleteExpression *) {}
+
+ virtual bool visit(VoidExpression *) { return true; }
+ virtual void endVisit(VoidExpression *) {}
+
+ virtual bool visit(TypeOfExpression *) { return true; }
+ virtual void endVisit(TypeOfExpression *) {}
+
+ virtual bool visit(PreIncrementExpression *) { return true; }
+ virtual void endVisit(PreIncrementExpression *) {}
+
+ virtual bool visit(PreDecrementExpression *) { return true; }
+ virtual void endVisit(PreDecrementExpression *) {}
+
+ virtual bool visit(UnaryPlusExpression *) { return true; }
+ virtual void endVisit(UnaryPlusExpression *) {}
+
+ virtual bool visit(UnaryMinusExpression *) { return true; }
+ virtual void endVisit(UnaryMinusExpression *) {}
+
+ virtual bool visit(TildeExpression *) { return true; }
+ virtual void endVisit(TildeExpression *) {}
+
+ virtual bool visit(NotExpression *) { return true; }
+ virtual void endVisit(NotExpression *) {}
+
+ virtual bool visit(BinaryExpression *) { return true; }
+ virtual void endVisit(BinaryExpression *) {}
+
+ virtual bool visit(ConditionalExpression *) { return true; }
+ virtual void endVisit(ConditionalExpression *) {}
+
+ virtual bool visit(Expression *) { return true; }
+ virtual void endVisit(Expression *) {}
+
+ virtual bool visit(Block *) { return true; }
+ virtual void endVisit(Block *) {}
+
+ virtual bool visit(StatementList *) { return true; }
+ virtual void endVisit(StatementList *) {}
+
+ virtual bool visit(VariableStatement *) { return true; }
+ virtual void endVisit(VariableStatement *) {}
+
+ virtual bool visit(VariableDeclarationList *) { return true; }
+ virtual void endVisit(VariableDeclarationList *) {}
+
+ virtual bool visit(VariableDeclaration *) { return true; }
+ virtual void endVisit(VariableDeclaration *) {}
+
+ virtual bool visit(EmptyStatement *) { return true; }
+ virtual void endVisit(EmptyStatement *) {}
+
+ virtual bool visit(ExpressionStatement *) { return true; }
+ virtual void endVisit(ExpressionStatement *) {}
+
+ virtual bool visit(IfStatement *) { return true; }
+ virtual void endVisit(IfStatement *) {}
+
+ virtual bool visit(DoWhileStatement *) { return true; }
+ virtual void endVisit(DoWhileStatement *) {}
+
+ virtual bool visit(WhileStatement *) { return true; }
+ virtual void endVisit(WhileStatement *) {}
+
+ virtual bool visit(ForStatement *) { return true; }
+ virtual void endVisit(ForStatement *) {}
+
+ virtual bool visit(LocalForStatement *) { return true; }
+ virtual void endVisit(LocalForStatement *) {}
+
+ virtual bool visit(ForEachStatement *) { return true; }
+ virtual void endVisit(ForEachStatement *) {}
+
+ virtual bool visit(LocalForEachStatement *) { return true; }
+ virtual void endVisit(LocalForEachStatement *) {}
+
+ virtual bool visit(ContinueStatement *) { return true; }
+ virtual void endVisit(ContinueStatement *) {}
+
+ virtual bool visit(BreakStatement *) { return true; }
+ virtual void endVisit(BreakStatement *) {}
+
+ virtual bool visit(ReturnStatement *) { return true; }
+ virtual void endVisit(ReturnStatement *) {}
+
+ virtual bool visit(WithStatement *) { return true; }
+ virtual void endVisit(WithStatement *) {}
+
+ virtual bool visit(SwitchStatement *) { return true; }
+ virtual void endVisit(SwitchStatement *) {}
+
+ virtual bool visit(CaseBlock *) { return true; }
+ virtual void endVisit(CaseBlock *) {}
+
+ virtual bool visit(CaseClauses *) { return true; }
+ virtual void endVisit(CaseClauses *) {}
+
+ virtual bool visit(CaseClause *) { return true; }
+ virtual void endVisit(CaseClause *) {}
+
+ virtual bool visit(DefaultClause *) { return true; }
+ virtual void endVisit(DefaultClause *) {}
+
+ virtual bool visit(LabelledStatement *) { return true; }
+ virtual void endVisit(LabelledStatement *) {}
+
+ virtual bool visit(ThrowStatement *) { return true; }
+ virtual void endVisit(ThrowStatement *) {}
+
+ virtual bool visit(TryStatement *) { return true; }
+ virtual void endVisit(TryStatement *) {}
+
+ virtual bool visit(Catch *) { return true; }
+ virtual void endVisit(Catch *) {}
+
+ virtual bool visit(Finally *) { return true; }
+ virtual void endVisit(Finally *) {}
+
+ virtual bool visit(FunctionDeclaration *) { return true; }
+ virtual void endVisit(FunctionDeclaration *) {}
+
+ virtual bool visit(FunctionExpression *) { return true; }
+ virtual void endVisit(FunctionExpression *) {}
+
+ virtual bool visit(FormalParameterList *) { return true; }
+ virtual void endVisit(FormalParameterList *) {}
+
+ virtual bool visit(FunctionBody *) { return true; }
+ virtual void endVisit(FunctionBody *) {}
+
+ virtual bool visit(Program *) { return true; }
+ virtual void endVisit(Program *) {}
+
+ virtual bool visit(SourceElements *) { return true; }
+ virtual void endVisit(SourceElements *) {}
+
+ virtual bool visit(FunctionSourceElement *) { return true; }
+ virtual void endVisit(FunctionSourceElement *) {}
+
+ virtual bool visit(StatementSourceElement *) { return true; }
+ virtual void endVisit(StatementSourceElement *) {}
+
+ virtual bool visit(DebuggerStatement *) { return true; }
+ virtual void endVisit(DebuggerStatement *) {}
+};
+
+} } // namespace AST
+
+QT_QML_END_NAMESPACE
+
+#endif // QMLJSASTVISITOR_P_H
diff --git a/src/declarative/qml/parser/qmljsengine_p.cpp b/src/declarative/qml/parser/qmljsengine_p.cpp
new file mode 100644
index 0000000..b8ecd18
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsengine_p.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmljsengine_p.h"
+
+#include "qmljsglobal_p.h"
+#include "qmljsnodepool_p.h"
+
+#include <qnumeric.h>
+#include <QHash>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+uint qHash(const QmlJS::NameId &id)
+{ return qHash(id.asString()); }
+
+QString numberToString(double value)
+{ return QString::number(value); }
+
+int Ecma::RegExp::flagFromChar(const QChar &ch)
+{
+ static QHash<QChar, int> flagsHash;
+ if (flagsHash.isEmpty()) {
+ flagsHash[QLatin1Char('g')] = Global;
+ flagsHash[QLatin1Char('i')] = IgnoreCase;
+ flagsHash[QLatin1Char('m')] = Multiline;
+ }
+ QHash<QChar, int>::const_iterator it;
+ it = flagsHash.constFind(ch);
+ if (it == flagsHash.constEnd())
+ return 0;
+ return it.value();
+}
+
+QString Ecma::RegExp::flagsToString(int flags)
+{
+ QString result;
+ if (flags & Global)
+ result += QLatin1Char('g');
+ if (flags & IgnoreCase)
+ result += QLatin1Char('i');
+ if (flags & Multiline)
+ result += QLatin1Char('m');
+ return result;
+}
+
+NodePool::NodePool(const QString &fileName, Engine *engine)
+ : m_fileName(fileName), m_engine(engine)
+{
+ m_engine->setNodePool(this);
+}
+
+NodePool::~NodePool()
+{
+}
+
+Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &)
+{
+ Q_ASSERT(0);
+ return 0;
+}
+
+static int toDigit(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'a') && (c <= 'z'))
+ return 10 + c - 'a';
+ else if ((c >= 'A') && (c <= 'Z'))
+ return 10 + c - 'A';
+ return -1;
+}
+
+double integerFromString(const char *buf, int size, int radix)
+{
+ if (size == 0)
+ return qSNaN();
+
+ double sign = 1.0;
+ int i = 0;
+ if (buf[0] == '+') {
+ ++i;
+ } else if (buf[0] == '-') {
+ sign = -1.0;
+ ++i;
+ }
+
+ if (((size-i) >= 2) && (buf[i] == '0')) {
+ if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ && (radix < 34)) {
+ if ((radix != 0) && (radix != 16))
+ return 0;
+ radix = 16;
+ i += 2;
+ } else {
+ if (radix == 0) {
+ radix = 8;
+ ++i;
+ }
+ }
+ } else if (radix == 0) {
+ radix = 10;
+ }
+
+ int j = i;
+ for ( ; i < size; ++i) {
+ int d = toDigit(buf[i]);
+ if ((d == -1) || (d >= radix))
+ break;
+ }
+ double result;
+ if (j == i) {
+ if (!qstrcmp(buf, "Infinity"))
+ result = qInf();
+ else
+ result = qSNaN();
+ } else {
+ result = 0;
+ double multiplier = 1;
+ for (--i ; i >= j; --i, multiplier *= radix)
+ result += toDigit(buf[i]) * multiplier;
+ }
+ result *= sign;
+ return result;
+}
+
+double integerFromString(const QString &str, int radix)
+{
+ QByteArray ba = str.trimmed().toLatin1();
+ return integerFromString(ba.constData(), ba.size(), radix);
+}
+
+
+Engine::Engine()
+ : _lexer(0), _nodePool(0)
+{ }
+
+Engine::~Engine()
+{ }
+
+QSet<NameId> Engine::literals() const
+{ return _literals; }
+
+void Engine::addComment(int pos, int len, int line, int col)
+{ if (len > 0) _comments.append(QmlJS::AST::SourceLocation(pos, len, line, col)); }
+
+QList<QmlJS::AST::SourceLocation> Engine::comments() const
+{ return _comments; }
+
+NameId *Engine::intern(const QChar *u, int s)
+{ return const_cast<NameId *>(&*_literals.insert(NameId(u, s))); }
+
+QString Engine::toString(NameId *id)
+{ return id->asString(); }
+
+Lexer *Engine::lexer() const
+{ return _lexer; }
+
+void Engine::setLexer(Lexer *lexer)
+{ _lexer = lexer; }
+
+NodePool *Engine::nodePool() const
+{ return _nodePool; }
+
+void Engine::setNodePool(NodePool *nodePool)
+{ _nodePool = nodePool; }
+
+
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
diff --git a/src/declarative/qml/parser/qmljsengine_p.h b/src/declarative/qml/parser/qmljsengine_p.h
new file mode 100644
index 0000000..2c15af3
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsengine_p.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLJSENGINE_P_H
+#define QMLJSENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmljsglobal_p.h"
+#include "qmljsastfwd_p.h"
+
+#include <QString>
+#include <QSet>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+class QML_PARSER_EXPORT NameId
+{
+ QString _text;
+
+public:
+ NameId(const QChar *u, int s)
+ : _text(u, s)
+ { }
+
+ const QString asString() const
+ { return _text; }
+
+ bool operator == (const NameId &other) const
+ { return _text == other._text; }
+
+ bool operator != (const NameId &other) const
+ { return _text != other._text; }
+
+ bool operator < (const NameId &other) const
+ { return _text < other._text; }
+};
+
+uint qHash(const QmlJS::NameId &id);
+
+} // end of namespace QmlJS
+
+#if defined(Q_CC_MSVC) && _MSC_VER <= 1300
+//this ensures that code outside QmlJS can use the hash function
+//it also a workaround for some compilers
+inline uint qHash(const QmlJS::NameId &nameId) { return QmlJS::qHash(nameId); }
+#endif
+
+namespace QmlJS {
+
+class Lexer;
+class NodePool;
+
+namespace Ecma {
+
+class QML_PARSER_EXPORT RegExp
+{
+public:
+ enum RegExpFlag {
+ Global = 0x01,
+ IgnoreCase = 0x02,
+ Multiline = 0x04
+ };
+
+public:
+ static int flagFromChar(const QChar &);
+ static QString flagsToString(int flags);
+};
+
+} // end of namespace Ecma
+
+class QML_PARSER_EXPORT DiagnosticMessage
+{
+public:
+ enum Kind { Warning, Error };
+
+ DiagnosticMessage()
+ : kind(Error) {}
+
+ DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message)
+ : kind(kind), loc(loc), message(message) {}
+
+ bool isWarning() const
+ { return kind == Warning; }
+
+ bool isError() const
+ { return kind == Error; }
+
+ Kind kind;
+ AST::SourceLocation loc;
+ QString message;
+};
+
+class QML_PARSER_EXPORT Engine
+{
+ Lexer *_lexer;
+ NodePool *_nodePool;
+ QSet<NameId> _literals;
+ QList<QmlJS::AST::SourceLocation> _comments;
+
+public:
+ Engine();
+ ~Engine();
+
+ QSet<NameId> literals() const;
+
+ void addComment(int pos, int len, int line, int col);
+ QList<QmlJS::AST::SourceLocation> comments() const;
+
+ NameId *intern(const QChar *u, int s);
+
+ static QString toString(NameId *id);
+
+ Lexer *lexer() const;
+ void setLexer(Lexer *lexer);
+
+ NodePool *nodePool() const;
+ void setNodePool(NodePool *nodePool);
+};
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif // QMLJSENGINE_P_H
diff --git a/src/declarative/qml/parser/qmljsglobal_p.h b/src/declarative/qml/parser/qmljsglobal_p.h
new file mode 100644
index 0000000..49e50cf
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsglobal_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QMLJSGLOBAL_P_H
+#define QMLJSGLOBAL_P_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef QT_CREATOR
+# define QT_QML_BEGIN_NAMESPACE
+# define QT_QML_END_NAMESPACE
+
+# ifdef QMLJS_BUILD_DIR
+# define QML_PARSER_EXPORT Q_DECL_EXPORT
+# elif QML_BUILD_STATIC_LIB
+# define QML_PARSER_EXPORT
+# else
+# define QML_PARSER_EXPORT Q_DECL_IMPORT
+# endif // QMLJS_BUILD_DIR
+
+#else // !QT_CREATOR
+# define QT_QML_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
+# define QT_QML_END_NAMESPACE QT_END_NAMESPACE
+# define QML_PARSER_EXPORT
+#endif // QT_CREATOR
+
+#endif // QMLJSGLOBAL_P_H
diff --git a/src/declarative/qml/parser/qmljsgrammar.cpp b/src/declarative/qml/parser/qmljsgrammar.cpp
new file mode 100644
index 0000000..b416959
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsgrammar.cpp
@@ -0,0 +1,939 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file was generated by qlalr - DO NOT EDIT!
+#include "qmljsgrammar_p.h"
+
+QT_BEGIN_NAMESPACE
+
+const char *const QmlJSGrammar::spell [] = {
+ "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue",
+ "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
+ "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
+ "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
+ "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
+ "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
+ ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch",
+ "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^",
+ "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public",
+ "import", "as", 0, 0, 0, 0, 0, 0, 0, 0};
+
+const short QmlJSGrammar::lhs [] = {
+ 100, 100, 100, 100, 100, 100, 101, 107, 107, 110,
+ 110, 112, 111, 111, 111, 111, 111, 111, 111, 111,
+ 114, 109, 108, 117, 117, 118, 118, 119, 119, 116,
+ 105, 105, 105, 105, 105, 105, 105, 125, 125, 125,
+ 126, 126, 127, 127, 105, 105, 105, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 105, 105, 115, 115, 115, 115, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 120, 132, 132, 132, 132, 131,
+ 131, 134, 134, 136, 136, 136, 136, 136, 136, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ 138, 138, 113, 113, 113, 113, 113, 141, 141, 142,
+ 142, 142, 142, 140, 140, 143, 143, 144, 144, 145,
+ 145, 145, 146, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 147, 147, 147, 147, 148, 148, 148, 149,
+ 149, 149, 149, 150, 150, 150, 150, 150, 150, 150,
+ 151, 151, 151, 151, 151, 151, 152, 152, 152, 152,
+ 152, 153, 153, 153, 153, 153, 154, 154, 155, 155,
+ 156, 156, 157, 157, 158, 158, 159, 159, 160, 160,
+ 161, 161, 162, 162, 163, 163, 164, 164, 165, 165,
+ 135, 135, 166, 166, 167, 167, 167, 167, 167, 167,
+ 167, 167, 167, 167, 167, 167, 103, 103, 168, 168,
+ 169, 169, 170, 170, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 121,
+ 182, 182, 181, 181, 129, 129, 183, 183, 184, 184,
+ 186, 186, 185, 187, 190, 188, 188, 191, 189, 189,
+ 122, 123, 123, 124, 124, 171, 171, 171, 171, 171,
+ 171, 171, 172, 172, 172, 172, 173, 173, 173, 173,
+ 174, 174, 175, 177, 192, 192, 195, 195, 193, 193,
+ 196, 194, 176, 176, 176, 178, 178, 179, 179, 179,
+ 197, 198, 180, 180, 128, 139, 202, 202, 199, 199,
+ 200, 200, 203, 106, 204, 204, 104, 104, 201, 201,
+ 133, 133, 205};
+
+const short QmlJSGrammar::rhs [] = {
+ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
+ 2, 1, 2, 2, 3, 3, 5, 5, 4, 4,
+ 2, 0, 1, 1, 2, 1, 3, 2, 3, 2,
+ 1, 5, 4, 3, 3, 3, 3, 1, 1, 1,
+ 0, 1, 2, 4, 6, 6, 3, 3, 7, 7,
+ 4, 4, 5, 5, 6, 6, 7, 7, 7, 7,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 3, 3, 4,
+ 5, 3, 4, 3, 1, 1, 2, 3, 4, 1,
+ 2, 3, 5, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 4, 3, 5, 1, 2, 4,
+ 4, 4, 3, 0, 1, 1, 3, 1, 1, 1,
+ 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 1, 3, 3, 3, 1, 3, 3, 1,
+ 3, 3, 3, 1, 3, 3, 3, 3, 3, 3,
+ 1, 3, 3, 3, 3, 3, 1, 3, 3, 3,
+ 3, 1, 3, 3, 3, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 3, 1, 5, 1, 5,
+ 1, 3, 1, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3, 0, 1,
+ 1, 3, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 1, 2, 0, 1, 3, 3, 1, 1, 1, 3,
+ 1, 3, 2, 2, 2, 0, 1, 2, 0, 1,
+ 1, 2, 2, 7, 5, 7, 7, 5, 9, 10,
+ 7, 8, 2, 2, 3, 3, 2, 2, 3, 3,
+ 3, 3, 5, 5, 3, 5, 1, 2, 0, 1,
+ 4, 3, 3, 3, 3, 3, 3, 3, 3, 4,
+ 5, 2, 2, 2, 8, 8, 1, 3, 0, 1,
+ 0, 1, 1, 1, 1, 2, 1, 1, 0, 1,
+ 0, 1, 2};
+
+const short QmlJSGrammar::action_default [] = {
+ 0, 0, 0, 0, 0, 0, 22, 0, 170, 237,
+ 201, 209, 205, 149, 221, 197, 3, 134, 68, 150,
+ 213, 217, 138, 167, 148, 153, 133, 187, 174, 0,
+ 75, 76, 71, 339, 63, 341, 0, 0, 0, 0,
+ 73, 0, 0, 69, 72, 0, 0, 64, 66, 65,
+ 74, 67, 0, 70, 0, 0, 163, 0, 0, 150,
+ 169, 152, 151, 0, 0, 0, 165, 166, 164, 168,
+ 0, 198, 0, 0, 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 178, 0, 0, 0, 172, 173, 171,
+ 176, 180, 179, 177, 175, 190, 189, 191, 0, 206,
+ 0, 202, 0, 0, 144, 131, 143, 132, 100, 101,
+ 102, 127, 103, 128, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 129, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 130, 0,
+ 0, 142, 238, 145, 0, 146, 0, 147, 141, 0,
+ 234, 227, 225, 232, 233, 231, 230, 236, 229, 228,
+ 226, 235, 222, 0, 210, 0, 0, 214, 0, 0,
+ 218, 0, 0, 144, 136, 0, 135, 0, 140, 154,
+ 0, 340, 329, 330, 0, 327, 0, 328, 0, 331,
+ 245, 252, 251, 259, 247, 0, 248, 332, 0, 338,
+ 249, 250, 255, 253, 335, 333, 337, 256, 0, 267,
+ 0, 0, 0, 0, 339, 63, 0, 341, 64, 239,
+ 281, 65, 0, 0, 0, 268, 0, 0, 257, 258,
+ 0, 246, 254, 282, 283, 326, 336, 0, 297, 298,
+ 299, 300, 0, 293, 294, 295, 296, 323, 324, 0,
+ 0, 0, 0, 0, 286, 287, 243, 241, 203, 211,
+ 207, 223, 199, 244, 0, 150, 215, 219, 192, 181,
+ 0, 0, 200, 0, 0, 0, 0, 193, 0, 0,
+ 0, 0, 0, 185, 183, 186, 184, 182, 195, 194,
+ 196, 0, 208, 0, 204, 0, 242, 150, 0, 224,
+ 239, 240, 0, 239, 0, 0, 289, 0, 0, 0,
+ 291, 0, 212, 0, 0, 216, 0, 0, 220, 279,
+ 0, 271, 280, 274, 0, 278, 0, 239, 272, 0,
+ 239, 0, 0, 290, 0, 0, 0, 292, 340, 329,
+ 0, 0, 331, 0, 325, 0, 315, 0, 0, 0,
+ 285, 0, 284, 0, 342, 0, 99, 261, 264, 0,
+ 100, 267, 103, 128, 105, 106, 71, 110, 111, 63,
+ 112, 115, 69, 72, 64, 239, 65, 74, 118, 67,
+ 120, 70, 122, 123, 268, 125, 126, 130, 0, 92,
+ 0, 0, 94, 98, 96, 83, 95, 97, 0, 93,
+ 82, 262, 260, 138, 139, 144, 0, 137, 0, 314,
+ 0, 301, 302, 0, 313, 0, 0, 0, 304, 309,
+ 307, 310, 0, 0, 308, 309, 0, 305, 0, 306,
+ 263, 312, 0, 263, 311, 0, 316, 317, 0, 263,
+ 318, 319, 0, 0, 320, 0, 0, 0, 321, 322,
+ 156, 155, 0, 0, 0, 288, 0, 0, 0, 303,
+ 276, 269, 0, 277, 273, 0, 275, 265, 0, 266,
+ 270, 86, 0, 0, 90, 77, 0, 79, 88, 0,
+ 80, 89, 91, 81, 87, 78, 0, 84, 160, 158,
+ 162, 159, 157, 161, 6, 334, 4, 2, 61, 85,
+ 0, 0, 64, 66, 65, 31, 5, 0, 62, 0,
+ 40, 39, 38, 0, 0, 53, 0, 54, 0, 59,
+ 60, 0, 40, 0, 0, 0, 0, 0, 49, 50,
+ 0, 51, 0, 52, 0, 55, 56, 0, 0, 0,
+ 0, 0, 57, 58, 0, 47, 41, 48, 42, 0,
+ 0, 0, 0, 44, 0, 45, 46, 43, 0, 0,
+ 30, 34, 35, 36, 37, 138, 263, 0, 0, 100,
+ 267, 103, 128, 105, 106, 71, 110, 111, 63, 112,
+ 115, 69, 72, 64, 239, 65, 74, 118, 67, 120,
+ 70, 122, 123, 268, 125, 126, 130, 138, 0, 26,
+ 0, 0, 32, 27, 33, 28, 24, 0, 29, 25,
+ 8, 0, 10, 0, 9, 0, 1, 21, 12, 0,
+ 13, 0, 14, 0, 19, 20, 0, 15, 16, 0,
+ 17, 18, 11, 23, 7, 343};
+
+const short QmlJSGrammar::goto_default [] = {
+ 7, 616, 206, 195, 204, 506, 494, 615, 634, 610,
+ 614, 612, 617, 22, 613, 18, 505, 607, 598, 560,
+ 507, 190, 194, 196, 200, 523, 549, 548, 199, 231,
+ 26, 473, 472, 355, 354, 9, 353, 356, 106, 17,
+ 144, 24, 13, 143, 19, 25, 56, 23, 8, 28,
+ 27, 268, 15, 262, 10, 258, 12, 260, 11, 259,
+ 20, 266, 21, 267, 14, 261, 257, 298, 410, 263,
+ 264, 201, 192, 191, 203, 232, 202, 207, 228, 229,
+ 193, 359, 358, 230, 462, 461, 320, 321, 464, 323,
+ 463, 322, 418, 422, 425, 421, 420, 440, 441, 184,
+ 198, 180, 183, 197, 205, 0};
+
+const short QmlJSGrammar::action_index [] = {
+ 439, 1109, 2228, 2228, 2132, 814, -74, 18, 147, -100,
+ 31, -17, -49, 232, -100, 318, 85, -100, -100, 554,
+ 33, 94, 331, 215, -100, -100, -100, 448, 231, 1109,
+ -100, -100, -100, 320, -100, 1940, 1472, 1109, 1109, 1109,
+ -100, 724, 1109, -100, -100, 1109, 1109, -100, -100, -100,
+ -100, -100, 1109, -100, 1109, 1109, -100, 1109, 1109, 129,
+ 157, -100, -100, 1109, 1109, 1109, -100, -100, -100, 200,
+ 1109, 293, 1109, 1109, 1109, 1109, 466, 1109, 1109, 1109,
+ 1109, 1109, 1109, 179, 1109, 1109, 1109, 119, 125, 95,
+ 188, 198, 184, 203, 178, 567, 567, 484, 1109, -5,
+ 1109, 67, 1844, 1109, 1109, -100, -100, -100, -100, -100,
+ -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, -100, -100, -100, -100, -100, -100, 110,
+ 1109, -100, -100, 70, 61, -100, 1109, -100, -100, 1109,
+ -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, 1109, 55, 1109, 1109, 73, 63, 1109,
+ -100, 1844, 1109, 1109, -100, 141, -100, 41, -100, -100,
+ 87, -100, 255, 80, 78, -100, 287, -100, 83, 2228,
+ -100, -100, -100, -100, -100, 225, -100, -100, 52, -100,
+ -100, -100, -100, -100, -100, 2228, -100, -100, 420, -100,
+ 408, 113, 2132, 50, 330, 65, 46, 2420, 72, 1109,
+ -100, 74, 75, 1109, 77, -100, 53, 56, -100, -100,
+ 323, -100, -100, -100, -100, -100, -100, 96, -100, -100,
+ -100, -100, 99, -100, -100, -100, -100, -100, -100, 60,
+ 47, 1109, 118, 93, -100, -100, 1291, -100, 79, 66,
+ 64, -100, 413, 76, 51, 664, 89, 97, 393, 183,
+ 337, 1109, 413, 1109, 1109, 1109, 1109, 411, 1109, 1109,
+ 1109, 1109, 1109, 252, 272, 212, 217, 221, 490, 490,
+ 383, 1109, 64, 1109, 84, 1109, -100, 536, 1109, -100,
+ 1109, 69, 68, 1109, 44, 2132, -100, 1109, 124, 2132,
+ -100, 1109, 54, 1109, 1109, 71, 88, 1109, -100, 82,
+ 122, 154, -100, -100, 1109, -100, 343, 1109, -100, 81,
+ 1109, 90, 2132, -100, 1109, 112, 2132, -100, 86, 333,
+ -39, -10, 2228, -33, -100, 2132, -100, 1109, 246, 2132,
+ 4, 2132, -100, 10, 16, -21, -100, -100, 2132, -26,
+ 480, 19, 462, 128, 1109, 2132, 6, -9, 400, 8,
+ -22, 840, -3, -6, -100, 1202, -100, -7, -28, 5,
+ 1109, 2, -23, 1109, 0, 1109, -34, -30, 1109, -100,
+ 2036, 21, -100, -100, -100, -100, -100, -100, 1109, -100,
+ -100, -100, -100, 209, -100, 1109, 40, -100, 2132, -100,
+ 101, -100, -100, 2132, -100, 1109, 120, 43, -100, 62,
+ -100, 59, 109, 1109, -100, 57, 58, -100, 39, -100,
+ 2132, -100, 117, 2132, -100, 199, -100, -100, 107, 2132,
+ 34, -100, 24, 11, -100, 346, -19, 14, -100, -100,
+ -100, -100, 1109, 133, 2132, -100, 1109, 126, 2132, -100,
+ 20, -100, 173, -100, -100, 1109, -100, -100, 303, -100,
+ -100, -100, 100, 1656, -100, -100, 1564, -100, -100, 1748,
+ -100, -100, -100, -100, -100, -100, 131, -100, -100, -100,
+ -100, -100, -100, -100, -100, 2228, -100, -100, -100, 158,
+ -20, 752, 165, -16, 22, -100, -100, 98, -100, 189,
+ -100, -100, -100, 28, 170, -100, 1109, -100, 230, -100,
+ -100, 247, 1, 13, 238, 37, -24, 106, -100, -100,
+ 273, -100, 1109, -100, 265, -100, -100, 242, -4, 12,
+ 1109, 241, -100, -100, 234, -100, 245, -100, 3, 9,
+ 311, 190, 316, -100, 134, -100, -100, -100, 1380, 1020,
+ -100, -100, -100, -100, -100, 359, 2324, 1472, 15, 444,
+ 38, 394, 138, 1109, 2132, 36, 17, 397, 42, 23,
+ 840, 32, 29, -100, 1202, -100, 26, 35, 48, 1109,
+ 45, 25, 1109, 49, 1109, 27, 30, 314, 132, -100,
+ 7, 752, -100, -100, -100, -100, -100, 930, -100, -100,
+ -100, 752, -100, 253, -87, 617, -100, -100, 102, 290,
+ -100, 191, -100, 140, -100, -100, 275, -100, -100, 91,
+ -100, -100, -100, -100, -100, -100,
+
+ -106, 12, -87, 18, 17, 212, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -53,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, 162,
+ -106, -106, -106, -4, -106, -106, -11, 24, 75, 76,
+ -106, 83, 55, -106, -106, 157, 158, -106, -106, -106,
+ -106, -106, 150, -106, 172, 176, -106, 168, 167, -106,
+ -106, -106, -106, 173, 154, 115, -106, -106, -106, -106,
+ 147, -106, 121, 113, 112, 125, -106, 128, 143, 146,
+ 140, 139, 136, -106, 122, 138, 130, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, 149, -106,
+ 153, -106, 110, 82, 46, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ 35, -106, -106, -106, -106, -106, 37, -106, -106, 45,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, 92, -106, 88, 58, -106, -106, 51,
+ -106, 209, 72, 78, -106, -106, -106, -106, -106, -106,
+ -106, -106, 27, -106, -106, -106, 63, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, 50, -106, -106, 28, -106,
+ 29, -106, 47, -106, 33, -106, -106, 66, -106, 73,
+ -106, -106, -106, 81, 53, -106, -106, -106, -106, -106,
+ -13, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, 9, -106, -106, -106, -106, 111, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ 3, 186, -106, 220, 228, 234, 204, -106, 90, 91,
+ 94, 97, 93, -106, -106, -106, -106, -106, -106, -106,
+ -106, 210, -106, 187, -106, 214, -106, -106, 208, -106,
+ 207, -106, -106, 155, -106, 8, -106, 4, -106, -1,
+ -106, 217, -106, 177, 185, -106, -106, 184, -106, -106,
+ -106, -106, -106, -106, 183, -106, 194, 105, -106, -106,
+ 99, -106, 71, -106, 74, -106, 65, -106, -106, 114,
+ -106, -106, -55, -106, -106, 64, -106, 44, -106, 30,
+ -106, 31, -106, -106, -106, -106, -106, -106, 57, -106,
+ 36, -106, 40, -106, 70, 59, -106, -106, 42, -106,
+ -106, 104, -106, -106, -106, 38, -106, -106, -106, -106,
+ 79, -106, 69, 108, -106, 84, -106, -106, 56, -106,
+ 68, -106, -106, -106, -106, -106, -106, -106, 52, -106,
+ -106, -106, -106, -106, -106, 109, -106, -106, 77, -106,
+ -106, -106, -106, 86, -106, 80, -106, -106, -106, -106,
+ -106, -59, -106, 43, -106, -63, -106, -106, -106, -106,
+ 98, -106, -106, 95, -106, -106, -106, -106, -106, 60,
+ -34, -106, -106, 32, -106, 41, -106, 39, -106, -106,
+ -106, -106, 49, -106, 61, -106, 62, -106, 48, -106,
+ -106, -106, -106, -106, -106, 23, -106, -106, 96, -106,
+ -106, -106, -106, 34, -106, -106, 133, -106, -106, 54,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, 67, -106, -106, -106, -106,
+ -106, 22, -106, -106, -106, -106, -106, -106, -106, -22,
+ -106, -106, -106, -106, -106, -106, 2, -106, -106, -106,
+ -106, -106, -106, -106, -19, -106, -106, -106, -106, -106,
+ -106, -106, 100, -106, -106, -106, -106, -21, -106, -106,
+ -3, -106, -106, -106, -106, -106, 13, -106, -106, -106,
+ 11, 14, 10, -106, -106, -106, -106, -106, 279, 283,
+ -106, -106, -106, -106, -106, -106, 19, 273, 15, 16,
+ -106, 21, -106, 224, 6, -106, -106, 25, -106, -106,
+ 85, -106, -106, -106, 26, -106, -106, -106, -106, 20,
+ -106, 7, 87, -106, 107, -106, -106, -106, -106, -106,
+ -106, 317, -106, -106, -106, -106, -106, 277, -106, -106,
+ -106, 0, -106, -106, -2, 271, -106, -106, -106, 1,
+ -106, -106, -106, -106, -106, -106, 5, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106};
+
+const short QmlJSGrammar::action_info [] = {
+ -97, -98, 452, 611, -116, 527, 456, -124, 415, -121,
+ 439, 551, -119, -108, 347, -94, 611, 388, 635, 540,
+ 351, 341, 344, 342, 390, 539, -127, 256, 398, 402,
+ 100, 98, 70, -97, 400, 163, -98, 465, 524, -116,
+ 559, 447, 530, -108, 439, -127, 509, 439, 559, -94,
+ 537, 544, -121, 256, 443, -119, -124, 514, 439, 347,
+ 445, 526, 423, 452, 423, 430, 456, 423, 70, 554,
+ 169, 415, 345, 311, 100, 163, 419, 140, 146, 408,
+ 271, 413, 347, 251, 295, 271, 256, 0, 186, 452,
+ 0, 311, 456, 140, 429, 317, 0, 0, 0, 324,
+ 407, 178, 291, 98, 305, 558, 0, 235, 476, 0,
+ 439, 415, 300, 442, 291, 0, 189, 171, 140, 426,
+ 140, 148, 339, 182, 433, 140, 140, 443, 140, 303,
+ 326, 559, 140, 0, 140, 57, 172, 250, 188, 140,
+ 601, 140, 330, 293, 165, 0, 58, 313, 166, 140,
+ 332, 314, 631, 630, 255, 254, 477, 241, 240, 57,
+ 246, 245, 412, 411, 427, 57, 141, 529, 528, 63,
+ 58, 61, 336, 171, 248, 247, 58, 516, 253, 0,
+ 417, 468, 62, 327, 309, 334, 458, 57, 602, 248,
+ 247, 487, 172, 454, 522, 556, 555, 176, 58, 248,
+ 247, 625, 624, 84, 84, 85, 85, 140, 84, 84,
+ 85, 85, 63, 84, 64, 85, 86, 86, 510, 510,
+ 65, 86, 86, 84, 171, 85, 86, 63, 84, 0,
+ 85, 517, 515, 140, 469, 467, 86, 84, 140, 85,
+ 512, 86, 84, 172, 85, 405, 84, 102, 85, 140,
+ 86, 511, 628, 627, 140, 86, 84, 64, 85, 86,
+ 437, 436, 171, 65, 512, 512, 103, 510, 104, 86,
+ 546, 510, 64, 140, 510, 511, 511, 84, 65, 85,
+ 532, 172, 626, 405, 34, 0, 234, 233, 0, 0,
+ 86, 520, 519, 0, 0, 547, 545, 84, 0, 85,
+ 621, 0, 543, 542, 34, 0, 349, 0, 0, 0,
+ 86, 72, 73, 512, 622, 620, 34, 512, 0, 34,
+ 512, 47, 49, 48, 511, 0, 536, 535, 511, 171,
+ 0, 511, 34, 0, 533, 531, 72, 73, 74, 75,
+ 34, 47, 49, 48, 619, 34, 171, -85, 172, 34,
+ 173, 0, 34, 47, 49, 48, 47, 49, 48, 34,
+ 0, 0, 34, 74, 75, 172, 34, 173, 0, 47,
+ 49, 48, 34, 0, 171, 34, 0, 47, 49, 48,
+ 0, 0, 47, 49, 48, 0, 47, 49, 48, 47,
+ 49, 48, -85, 172, 0, 173, 47, 49, 48, 47,
+ 49, 48, 0, 47, 49, 48, 278, 279, 0, 47,
+ 49, 48, 47, 49, 48, 280, 278, 279, 281, 0,
+ 282, 0, 0, 34, 0, 280, 34, 0, 281, 34,
+ 282, 273, 274, -339, 278, 279, -339, 34, 0, 0,
+ 0, 0, 0, 280, 0, 0, 281, 0, 282, 34,
+ 0, 0, 0, 0, 0, 244, 243, 0, 275, 276,
+ 47, 49, 48, 47, 49, 48, 47, 49, 48, 244,
+ 243, 77, 78, 34, 47, 49, 48, 0, 0, 79,
+ 80, 239, 238, 81, 0, 82, 47, 49, 48, 77,
+ 78, 34, 0, 0, 0, 0, 0, 79, 80, 0,
+ 0, 81, 0, 82, 0, 239, 238, 77, 78, 34,
+ 47, 49, 48, 278, 279, 79, 80, 0, 0, 81,
+ 0, 82, 280, 244, 243, 281, 0, 282, 47, 49,
+ 48, 6, 5, 4, 1, 3, 2, 0, 0, 150,
+ 0, 239, 238, 0, 0, 0, 47, 49, 48, 151,
+ 0, 0, 0, 152, 0, 0, 0, 150, 0, 0,
+ 0, 0, 153, 0, 154, 0, 0, 151, 0, 0,
+ 0, 152, 0, 0, 0, 155, 0, 156, 61, 0,
+ 153, 0, 154, 0, 0, 157, 0, 0, 158, 62,
+ 77, 78, 0, 155, 159, 156, 61, 0, 79, 80,
+ 160, 0, 81, 157, 82, 0, 158, 62, 0, 0,
+ 0, 0, 159, 0, 0, 0, 161, 0, 160, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,
+ 31, 0, 0, 0, 161, 0, 0, 0, 0, 33,
+ 0, 0, 0, 0, 0, 0, 34, 0, 0, 0,
+ 35, 36, 0, 37, 0, 0, 0, 0, 0, 0,
+ 501, 0, 0, 0, 44, 0, 0, 150, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 151, 0, 0,
+ 0, 152, 50, 47, 49, 48, 0, 51, 0, 0,
+ 153, 0, 154, 0, 0, 307, 0, 0, 43, 53,
+ 32, 0, 0, 155, 40, 156, 61, 0, 0, 0,
+ 0, 0, 0, 157, 0, 0, 158, 62, 0, 0,
+ 0, 0, 159, 0, 0, 0, 0, 0, 160, 0,
+ 0, 0, 0, 0, 0, 0, 30, 31, 0, 0,
+ 0, 0, 0, 0, 161, 0, 33, 0, 0, 0,
+ 0, 0, 0, 34, 0, 0, 0, 35, 36, 0,
+ 37, 0, 0, 0, 30, 31, 0, 41, 0, 0,
+ 0, 44, 0, 0, 33, 0, 0, 0, 0, 0,
+ 0, 34, 0, 0, 0, 35, 36, 0, 37, 50,
+ 47, 49, 48, 0, 51, 501, 0, 0, 0, 44,
+ 0, 0, 0, 0, 0, 43, 53, 32, 0, 0,
+ 0, 40, 0, 0, 0, 0, 0, 50, 47, 49,
+ 48, 0, 51, 0, 500, 0, 30, 31, 0, 0,
+ 0, 0, 0, 43, 53, 32, 214, 0, 0, 40,
+ 0, 0, 0, 34, 0, 0, 0, 35, 36, 0,
+ 37, 0, 30, 31, 0, 0, 0, 501, 0, 0,
+ 0, 44, 33, 0, 0, 0, 0, 0, 0, 34,
+ 0, 0, 0, 35, 36, 0, 37, 0, 0, 50,
+ 502, 504, 503, 41, 51, 0, 0, 44, 0, 225,
+ 0, 0, 0, 0, 0, 43, 53, 32, 209, 0,
+ 0, 40, 0, 0, 0, 50, 47, 49, 48, 0,
+ 51, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 43, 53, 32, 0, 0, 0, 40, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 500, 0, 30, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 214, 0, 0, 0, 0, 0, 0, 34,
+ 0, 0, 0, 35, 36, 0, 37, 0, 0, 0,
+ 0, 0, 0, 501, 0, 0, 0, 44, 0, 0,
+ 0, 0, 0, 0, 0, 608, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 50, 502, 504, 503, 0,
+ 51, 0, 0, 0, 0, 225, 0, 0, 0, 0,
+ 0, 43, 53, 32, 209, 0, 0, 40, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 500, 0, 30, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 214, 0, 0, 0, 0, 0, 0, 34,
+ 0, 0, 0, 35, 36, 0, 37, 0, 0, 0,
+ 0, 0, 0, 501, 0, 0, 0, 44, 0, 0,
+ 0, 0, 0, 0, 0, 605, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 50, 502, 504, 503, 0,
+ 51, 0, 0, 0, 0, 225, 0, 0, 0, 0,
+ 0, 43, 53, 32, 209, 0, 0, 40, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 29, 30, 31, 0, 0, 0, 0, 0, 0, 0,
+ 0, 33, 0, 0, 0, 0, 0, 0, 34, 0,
+ 0, 0, 35, 36, 0, 37, 0, 0, 0, 38,
+ 0, 39, 41, 42, 0, 0, 44, 0, 0, 0,
+ 45, 0, 46, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 50, 47, 49, 48, 0, 51,
+ 0, 52, 0, 54, 0, 55, 0, 0, 0, 0,
+ 43, 53, 32, 0, 0, 0, 40, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -117,
+ 0, 0, 0, 29, 30, 31, 0, 0, 0, 0,
+ 0, 0, 0, 0, 33, 0, 0, 0, 0, 0,
+ 0, 34, 0, 0, 0, 35, 36, 0, 37, 0,
+ 0, 0, 38, 0, 39, 41, 42, 0, 0, 44,
+ 0, 0, 0, 45, 0, 46, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 50, 47, 49,
+ 48, 0, 51, 0, 52, 0, 54, 0, 55, 0,
+ 0, 0, 0, 43, 53, 32, 0, 0, 0, 40,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 29, 30, 31, 0, 0, 0, 0, 0,
+ 0, 0, 0, 33, 0, 0, 0, 0, 0, 0,
+ 34, 0, 0, 0, 35, 36, 0, 37, 0, 0,
+ 0, 38, 0, 39, 41, 42, 0, 0, 44, 0,
+ 0, 0, 45, 0, 46, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 50, 47, 49, 48,
+ 0, 51, 0, 52, 0, 54, 270, 55, 0, 0,
+ 0, 0, 43, 53, 32, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 29, 30, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 33, 0, 0, 0, 0, 0, 0, 34,
+ 216, 0, 0, 566, 567, 0, 37, 0, 0, 0,
+ 38, 0, 39, 41, 42, 0, 0, 44, 0, 0,
+ 0, 45, 0, 46, 0, 0, 0, 0, 0, 0,
+ 0, 220, 0, 0, 0, 50, 47, 49, 48, 0,
+ 51, 0, 52, 0, 54, 0, 55, 0, 0, 0,
+ 0, 43, 53, 32, 0, 0, 0, 40, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 474, 0, 0, 29, 30, 31, 0, 0, 0, 0,
+ 0, 0, 0, 0, 33, 0, 0, 0, 0, 0,
+ 0, 34, 0, 0, 0, 35, 36, 0, 37, 0,
+ 0, 0, 38, 0, 39, 41, 42, 0, 0, 44,
+ 0, 0, 0, 45, 0, 46, 0, 0, 475, 0,
+ 0, 0, 0, 0, 0, 0, 0, 50, 47, 49,
+ 48, 0, 51, 0, 52, 0, 54, 0, 55, 0,
+ 0, 0, 0, 43, 53, 32, 0, 0, 0, 40,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 474, 0, 0, 29, 30, 31, 0, 0,
+ 0, 0, 0, 0, 0, 0, 33, 0, 0, 0,
+ 0, 0, 0, 34, 0, 0, 0, 35, 36, 0,
+ 37, 0, 0, 0, 38, 0, 39, 41, 42, 0,
+ 0, 44, 0, 0, 0, 45, 0, 46, 0, 0,
+ 480, 0, 0, 0, 0, 0, 0, 0, 0, 50,
+ 47, 49, 48, 0, 51, 0, 52, 0, 54, 0,
+ 55, 0, 0, 0, 0, 43, 53, 32, 0, 0,
+ 0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 482, 0, 0, 29, 30, 31,
+ 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
+ 0, 0, 0, 0, 0, 34, 0, 0, 0, 35,
+ 36, 0, 37, 0, 0, 0, 38, 0, 39, 41,
+ 42, 0, 0, 44, 0, 0, 0, 45, 0, 46,
+ 0, 0, 485, 0, 0, 0, 0, 0, 0, 0,
+ 0, 50, 47, 49, 48, 0, 51, 0, 52, 0,
+ 54, 0, 55, 0, 0, 0, 0, 43, 53, 32,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 482, 0, 0, 29,
+ 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
+ 33, 0, 0, 0, 0, 0, 0, 34, 0, 0,
+ 0, 35, 36, 0, 37, 0, 0, 0, 38, 0,
+ 39, 41, 42, 0, 0, 44, 0, 0, 0, 45,
+ 0, 46, 0, 0, 483, 0, 0, 0, 0, 0,
+ 0, 0, 0, 50, 47, 49, 48, 0, 51, 0,
+ 52, 0, 54, 0, 55, 0, 0, 0, 0, 43,
+ 53, 32, 0, 0, 0, 40, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 108, 109,
+ 110, 0, 0, 112, 114, 115, 0, 0, 116, 0,
+ 117, 0, 0, 0, 119, 120, 121, 0, 0, 0,
+ 0, 0, 0, 34, 122, 123, 124, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 125, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 128, 0, 0, 0, 0, 0, 0,
+ 47, 49, 48, 129, 130, 131, 0, 133, 134, 135,
+ 136, 137, 138, 0, 0, 126, 132, 118, 111, 113,
+ 127, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 108, 109, 110, 0, 0, 112,
+ 114, 115, 0, 0, 116, 0, 117, 0, 0, 0,
+ 119, 120, 121, 0, 0, 0, 0, 0, 0, 392,
+ 122, 123, 124, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 125, 0, 0, 0, 393, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,
+ 0, 0, 0, 0, 0, 397, 394, 396, 0, 129,
+ 130, 131, 0, 133, 134, 135, 136, 137, 138, 0,
+ 0, 126, 132, 118, 111, 113, 127, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 109, 110, 0, 0, 112, 114, 115, 0, 0,
+ 116, 0, 117, 0, 0, 0, 119, 120, 121, 0,
+ 0, 0, 0, 0, 0, 392, 122, 123, 124, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 125,
+ 0, 0, 0, 393, 0, 0, 0, 0, 0, 0,
+ 0, 395, 0, 0, 0, 128, 0, 0, 0, 0,
+ 0, 397, 394, 396, 0, 129, 130, 131, 0, 133,
+ 134, 135, 136, 137, 138, 0, 0, 126, 132, 118,
+ 111, 113, 127, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 208, 0, 0, 0,
+ 0, 210, 0, 29, 30, 31, 212, 0, 0, 0,
+ 0, 0, 0, 213, 33, 0, 0, 0, 0, 0,
+ 0, 215, 216, 0, 0, 217, 36, 0, 37, 0,
+ 0, 0, 38, 0, 39, 41, 42, 0, 0, 44,
+ 0, 0, 0, 45, 0, 46, 0, 0, 0, 0,
+ 0, 219, 0, 220, 0, 0, 0, 50, 218, 221,
+ 48, 222, 51, 223, 52, 224, 54, 225, 55, 226,
+ 227, 0, 0, 43, 53, 32, 209, 211, 0, 40,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 208, 0, 0, 0, 0, 210, 0, 29,
+ 30, 31, 212, 0, 0, 0, 0, 0, 0, 213,
+ 214, 0, 0, 0, 0, 0, 0, 215, 216, 0,
+ 0, 217, 36, 0, 37, 0, 0, 0, 38, 0,
+ 39, 41, 42, 0, 0, 44, 0, 0, 0, 45,
+ 0, 46, 0, 0, 0, 0, 0, 219, 0, 220,
+ 0, 0, 0, 50, 218, 221, 48, 222, 51, 223,
+ 52, 224, 54, 225, 55, 226, 227, 0, 0, 43,
+ 53, 32, 209, 211, 0, 40, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 569, 109,
+ 110, 0, 0, 571, 114, 573, 30, 31, 574, 0,
+ 117, 0, 0, 0, 119, 576, 577, 0, 0, 0,
+ 0, 0, 0, 578, 579, 123, 124, 217, 36, 0,
+ 37, 0, 0, 0, 38, 0, 39, 580, 42, 0,
+ 0, 582, 0, 0, 0, 45, 0, 46, 0, 0,
+ 0, 0, 0, 584, 0, 220, 0, 0, 0, 586,
+ 583, 585, 48, 587, 588, 589, 52, 591, 592, 593,
+ 594, 595, 596, 0, 0, 581, 590, 575, 570, 572,
+ 127, 40, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 360, 109, 110, 0, 0, 362,
+ 114, 364, 30, 31, 365, 0, 117, 0, 0, 0,
+ 119, 367, 368, 0, 0, 0, 0, 0, 0, 369,
+ 370, 123, 124, 217, 36, 0, 37, 0, 0, 0,
+ 38, 0, 39, 371, 42, 0, 0, 373, 0, 0,
+ 0, 45, 0, 46, 0, -263, 0, 0, 0, 375,
+ 0, 220, 0, 0, 0, 377, 374, 376, 48, 378,
+ 379, 380, 52, 382, 383, 384, 385, 386, 387, 0,
+ 0, 372, 381, 366, 361, 363, 127, 40, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 541, 310, 460, 513, 538, 518, 525, 308, 249, 632,
+ 306, 181, 252, 618, 149, 16, 623, 495, 319, 497,
+ 629, 357, 496, 435, 471, 553, 557, 486, 438, 301,
+ 428, 237, 350, 352, 604, 521, 242, 424, 550, 552,
+ 181, 301, 185, 237, 242, 343, 432, 348, 338, 249,
+ 459, 237, 453, 449, 236, 242, 446, 181, 466, 401,
+ 448, 249, 357, 455, 444, 457, 346, 337, 357, 484,
+ 142, 236, 147, 333, 438, 175, 301, 335, 187, 409,
+ 162, 145, 435, 416, 435, 139, 170, 399, 414, 481,
+ 438, 389, 0, 168, 0, 0, 403, 357, 403, 59,
+ 357, 490, 301, 534, 391, 0, 0, 0, 301, 0,
+ 0, 460, 0, 145, 59, 0, 179, 403, 177, 59,
+ 59, 488, 489, 0, 404, 105, 404, 0, 59, 185,
+ 451, 59, 59, 450, 59, 59, 59, 59, 59, 283,
+ 284, 59, 287, 285, 145, 404, 286, 107, 167, 406,
+ 164, 59, 59, 451, 450, 265, 59, 59, 301, 59,
+ 269, 68, 96, 95, 479, 59, 59, 331, 478, 59,
+ 87, 76, 59, 329, 59, 97, 434, 83, 89, 431,
+ 59, 470, 59, 59, 59, 94, 88, 59, 93, 92,
+ 59, 59, 90, 59, 59, 91, 493, 59, 59, 71,
+ 67, 59, 59, 491, 492, 99, 59, 101, 179, 319,
+ 301, 59, 59, 340, 69, 60, 59, 59, 450, 66,
+ 59, 59, 451, 304, 105, 499, 269, 297, 297, 297,
+ 59, 59, 269, 269, 269, 269, 269, 0, 315, 272,
+ 498, 508, 294, 0, 0, 0, 107, 174, 59, 325,
+ 318, 316, 297, 269, 59, 290, 0, 269, 297, 269,
+ 0, 59, 0, 269, 59, 0, 269, 292, 59, 269,
+ 179, 277, 59, 0, 299, 302, 312, 269, 59, 288,
+ 296, 328, 609, 269, 499, 289, 597, 633, 606, 599,
+ 499, 600, 565, 600, 0, 0, 499, 0, 0, 568,
+ 561, 562, 563, 564, 0, 498, 508, 0, 471, 0,
+ 0, 498, 508, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 499, 0, 0, 603, 0, 0, 0, 600, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
+
+const short QmlJSGrammar::action_check [] = {
+ 7, 7, 36, 90, 7, 29, 36, 7, 36, 7,
+ 33, 8, 7, 7, 36, 7, 90, 7, 0, 7,
+ 16, 60, 55, 33, 8, 29, 7, 36, 7, 55,
+ 79, 48, 1, 7, 55, 2, 7, 17, 37, 7,
+ 33, 60, 29, 7, 33, 7, 66, 33, 33, 7,
+ 66, 29, 7, 36, 20, 7, 7, 29, 33, 36,
+ 36, 24, 5, 36, 5, 7, 36, 5, 1, 60,
+ 7, 36, 7, 2, 79, 2, 33, 8, 8, 7,
+ 1, 7, 36, 36, 8, 1, 36, -1, 8, 36,
+ -1, 2, 36, 8, 55, 7, -1, -1, -1, 17,
+ 60, 60, 48, 48, 60, 7, -1, 55, 8, -1,
+ 33, 36, 61, 6, 48, -1, 33, 15, 8, 10,
+ 8, 60, 36, 36, 7, 8, 8, 20, 8, 61,
+ 8, 33, 8, -1, 8, 40, 34, 77, 60, 8,
+ 8, 8, 61, 79, 50, -1, 51, 50, 54, 8,
+ 60, 54, 61, 62, 61, 62, 56, 61, 62, 40,
+ 61, 62, 61, 62, 55, 40, 56, 61, 62, 12,
+ 51, 42, 60, 15, 61, 62, 51, 7, 60, -1,
+ 60, 8, 53, 61, 60, 31, 60, 40, 56, 61,
+ 62, 60, 34, 60, 29, 61, 62, 56, 51, 61,
+ 62, 61, 62, 25, 25, 27, 27, 8, 25, 25,
+ 27, 27, 12, 25, 57, 27, 38, 38, 29, 29,
+ 63, 38, 38, 25, 15, 27, 38, 12, 25, -1,
+ 27, 61, 62, 8, 61, 62, 38, 25, 8, 27,
+ 75, 38, 25, 34, 27, 36, 25, 15, 27, 8,
+ 38, 86, 61, 62, 8, 38, 25, 57, 27, 38,
+ 61, 62, 15, 63, 75, 75, 34, 29, 36, 38,
+ 36, 29, 57, 8, 29, 86, 86, 25, 63, 27,
+ 7, 34, 91, 36, 29, -1, 61, 62, -1, -1,
+ 38, 61, 62, -1, -1, 61, 62, 25, -1, 27,
+ 47, -1, 61, 62, 29, -1, 60, -1, -1, -1,
+ 38, 18, 19, 75, 61, 62, 29, 75, -1, 29,
+ 75, 66, 67, 68, 86, -1, 61, 62, 86, 15,
+ -1, 86, 29, -1, 61, 62, 18, 19, 45, 46,
+ 29, 66, 67, 68, 91, 29, 15, 33, 34, 29,
+ 36, -1, 29, 66, 67, 68, 66, 67, 68, 29,
+ -1, -1, 29, 45, 46, 34, 29, 36, -1, 66,
+ 67, 68, 29, -1, 15, 29, -1, 66, 67, 68,
+ -1, -1, 66, 67, 68, -1, 66, 67, 68, 66,
+ 67, 68, 33, 34, -1, 36, 66, 67, 68, 66,
+ 67, 68, -1, 66, 67, 68, 23, 24, -1, 66,
+ 67, 68, 66, 67, 68, 32, 23, 24, 35, -1,
+ 37, -1, -1, 29, -1, 32, 29, -1, 35, 29,
+ 37, 18, 19, 36, 23, 24, 36, 29, -1, -1,
+ -1, -1, -1, 32, -1, -1, 35, -1, 37, 29,
+ -1, -1, -1, -1, -1, 61, 62, -1, 45, 46,
+ 66, 67, 68, 66, 67, 68, 66, 67, 68, 61,
+ 62, 23, 24, 29, 66, 67, 68, -1, -1, 31,
+ 32, 61, 62, 35, -1, 37, 66, 67, 68, 23,
+ 24, 29, -1, -1, -1, -1, -1, 31, 32, -1,
+ -1, 35, -1, 37, -1, 61, 62, 23, 24, 29,
+ 66, 67, 68, 23, 24, 31, 32, -1, -1, 35,
+ -1, 37, 32, 61, 62, 35, -1, 37, 66, 67,
+ 68, 92, 93, 94, 95, 96, 97, -1, -1, 3,
+ -1, 61, 62, -1, -1, -1, 66, 67, 68, 13,
+ -1, -1, -1, 17, -1, -1, -1, 3, -1, -1,
+ -1, -1, 26, -1, 28, -1, -1, 13, -1, -1,
+ -1, 17, -1, -1, -1, 39, -1, 41, 42, -1,
+ 26, -1, 28, -1, -1, 49, -1, -1, 52, 53,
+ 23, 24, -1, 39, 58, 41, 42, -1, 31, 32,
+ 64, -1, 35, 49, 37, -1, 52, 53, -1, -1,
+ -1, -1, 58, -1, -1, -1, 80, -1, 64, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 12,
+ 13, -1, -1, -1, 80, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, -1, -1, -1,
+ 43, -1, -1, -1, 47, -1, -1, 3, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 13, -1, -1,
+ -1, 17, 65, 66, 67, 68, -1, 70, -1, -1,
+ 26, -1, 28, -1, -1, 31, -1, -1, 81, 82,
+ 83, -1, -1, 39, 87, 41, 42, -1, -1, -1,
+ -1, -1, -1, 49, -1, -1, 52, 53, -1, -1,
+ -1, -1, 58, -1, -1, -1, -1, -1, 64, -1,
+ -1, -1, -1, -1, -1, -1, 12, 13, -1, -1,
+ -1, -1, -1, -1, 80, -1, 22, -1, -1, -1,
+ -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
+ 36, -1, -1, -1, 12, 13, -1, 43, -1, -1,
+ -1, 47, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, 65,
+ 66, 67, 68, -1, 70, 43, -1, -1, -1, 47,
+ -1, -1, -1, -1, -1, 81, 82, 83, -1, -1,
+ -1, 87, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, 10, -1, 12, 13, -1, -1,
+ -1, -1, -1, 81, 82, 83, 22, -1, -1, 87,
+ -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
+ 36, -1, 12, 13, -1, -1, -1, 43, -1, -1,
+ -1, 47, 22, -1, -1, -1, -1, -1, -1, 29,
+ -1, -1, -1, 33, 34, -1, 36, -1, -1, 65,
+ 66, 67, 68, 43, 70, -1, -1, 47, -1, 75,
+ -1, -1, -1, -1, -1, 81, 82, 83, 84, -1,
+ -1, 87, -1, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 81, 82, 83, -1, -1, -1, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, -1, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
+ -1, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, 55, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, -1, -1, -1, 75, -1, -1, -1, -1,
+ -1, 81, 82, 83, 84, -1, -1, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, -1, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
+ -1, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, 55, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, -1, -1, -1, 75, -1, -1, -1, -1,
+ -1, 81, 82, 83, 84, -1, -1, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 11, 12, 13, -1, -1, -1, -1, -1, -1, -1,
+ -1, 22, -1, -1, -1, -1, -1, -1, 29, -1,
+ -1, -1, 33, 34, -1, 36, -1, -1, -1, 40,
+ -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
+ 51, -1, 53, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 65, 66, 67, 68, -1, 70,
+ -1, 72, -1, 74, -1, 76, -1, -1, -1, -1,
+ 81, 82, 83, -1, -1, -1, 87, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 7,
+ -1, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 11, 12, 13, -1, -1, -1, -1, -1,
+ -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
+ 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
+ -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
+ -1, -1, 51, -1, 53, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 65, 66, 67, 68,
+ -1, 70, -1, 72, -1, 74, 75, 76, -1, -1,
+ -1, -1, 81, 82, 83, -1, -1, -1, 87, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 11, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, -1, -1, -1, -1, -1,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, 72, -1, 74, -1, 76, -1, -1, -1,
+ -1, 81, 82, 83, -1, -1, -1, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 8, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, 56, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 8, -1, -1, 11, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
+ -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
+ 36, -1, -1, -1, 40, -1, 42, 43, 44, -1,
+ -1, 47, -1, -1, -1, 51, -1, 53, -1, -1,
+ 56, -1, -1, -1, -1, -1, -1, -1, -1, 65,
+ 66, 67, 68, -1, 70, -1, 72, -1, 74, -1,
+ 76, -1, -1, -1, -1, 81, 82, 83, -1, -1,
+ -1, 87, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
+ 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, 87, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 8, -1, -1, 11,
+ 12, 13, -1, -1, -1, -1, -1, -1, -1, -1,
+ 22, -1, -1, -1, -1, -1, -1, 29, -1, -1,
+ -1, 33, 34, -1, 36, -1, -1, -1, 40, -1,
+ 42, 43, 44, -1, -1, 47, -1, -1, -1, 51,
+ -1, 53, -1, -1, 56, -1, -1, -1, -1, -1,
+ -1, -1, -1, 65, 66, 67, 68, -1, 70, -1,
+ 72, -1, 74, -1, 76, -1, -1, -1, -1, 81,
+ 82, 83, -1, -1, -1, 87, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 4, 5,
+ 6, -1, -1, 9, 10, 11, -1, -1, 14, -1,
+ 16, -1, -1, -1, 20, 21, 22, -1, -1, -1,
+ -1, -1, -1, 29, 30, 31, 32, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 43, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 59, -1, -1, -1, -1, -1, -1,
+ 66, 67, 68, 69, 70, 71, -1, 73, 74, 75,
+ 76, 77, 78, -1, -1, 81, 82, 83, 84, 85,
+ 86, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4, 5, 6, -1, -1, 9,
+ 10, 11, -1, -1, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -1, -1, -1, -1, -1, 65, 66, 67, -1, 69,
+ 70, 71, -1, 73, 74, 75, 76, 77, 78, -1,
+ -1, 81, 82, 83, 84, 85, 86, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 4, 5, 6, -1, -1, 9, 10, 11, -1, -1,
+ 14, -1, 16, -1, -1, -1, 20, 21, 22, -1,
+ -1, -1, -1, -1, -1, 29, 30, 31, 32, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 43,
+ -1, -1, -1, 47, -1, -1, -1, -1, -1, -1,
+ -1, 55, -1, -1, -1, 59, -1, -1, -1, -1,
+ -1, 65, 66, 67, -1, 69, 70, 71, -1, 73,
+ 74, 75, 76, 77, 78, -1, -1, 81, 82, 83,
+ 84, 85, 86, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4, -1, -1, -1,
+ -1, 9, -1, 11, 12, 13, 14, -1, -1, -1,
+ -1, -1, -1, 21, 22, -1, -1, -1, -1, -1,
+ -1, 29, 30, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, -1, -1,
+ -1, 59, -1, 61, -1, -1, -1, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, -1, -1, 81, 82, 83, 84, 85, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4, -1, -1, -1, -1, 9, -1, 11,
+ 12, 13, 14, -1, -1, -1, -1, -1, -1, 21,
+ 22, -1, -1, -1, -1, -1, -1, 29, 30, -1,
+ -1, 33, 34, -1, 36, -1, -1, -1, 40, -1,
+ 42, 43, 44, -1, -1, 47, -1, -1, -1, 51,
+ -1, 53, -1, -1, -1, -1, -1, 59, -1, 61,
+ -1, -1, -1, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, -1, -1, 81,
+ 82, 83, 84, 85, -1, 87, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 4, 5,
+ 6, -1, -1, 9, 10, 11, 12, 13, 14, -1,
+ 16, -1, -1, -1, 20, 21, 22, -1, -1, -1,
+ -1, -1, -1, 29, 30, 31, 32, 33, 34, -1,
+ 36, -1, -1, -1, 40, -1, 42, 43, 44, -1,
+ -1, 47, -1, -1, -1, 51, -1, 53, -1, -1,
+ -1, -1, -1, 59, -1, 61, -1, -1, -1, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, -1, -1, 81, 82, 83, 84, 85,
+ 86, 87, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4, 5, 6, -1, -1, 9,
+ 10, 11, 12, 13, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, 55, -1, -1, -1, 59,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, -1,
+ -1, 81, 82, 83, 84, 85, 86, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ 3, 2, 15, 25, 25, 3, 25, 3, 2, 11,
+ 2, 15, 3, 13, 67, 3, 15, 104, 15, 2,
+ 15, 2, 4, 3, 35, 15, 15, 3, 21, 3,
+ 93, 15, 2, 2, 19, 13, 15, 96, 25, 25,
+ 15, 3, 15, 15, 15, 100, 3, 3, 15, 2,
+ 2, 15, 3, 21, 4, 15, 15, 15, 35, 2,
+ 21, 2, 2, 2, 98, 3, 2, 2, 2, 35,
+ 35, 4, 35, 2, 21, 3, 3, 3, 15, 2,
+ 35, 35, 3, 3, 3, 3, 35, 35, 2, 35,
+ 21, 35, -1, 35, -1, -1, 13, 2, 13, 44,
+ 2, 46, 3, 3, 36, -1, -1, -1, 3, -1,
+ -1, 15, -1, 35, 44, -1, 46, 13, 40, 44,
+ 44, 46, 46, -1, 41, 15, 41, -1, 44, 15,
+ 46, 44, 44, 46, 44, 44, 44, 44, 44, 49,
+ 49, 44, 49, 49, 35, 41, 49, 37, 60, 40,
+ 58, 44, 44, 46, 46, 44, 44, 44, 3, 44,
+ 49, 46, 50, 50, 31, 44, 44, 68, 35, 44,
+ 48, 50, 44, 68, 44, 50, 81, 49, 48, 81,
+ 44, 85, 44, 44, 44, 49, 48, 44, 49, 49,
+ 44, 44, 49, 44, 44, 49, 46, 44, 44, 52,
+ 46, 44, 44, 46, 46, 56, 44, 54, 46, 15,
+ 3, 44, 44, 99, 47, 47, 44, 44, 46, 46,
+ 44, 44, 46, 68, 15, 13, 49, 44, 44, 44,
+ 44, 44, 49, 49, 49, 49, 49, -1, 61, 53,
+ 28, 29, 55, -1, -1, -1, 37, 38, 44, 66,
+ 66, 66, 44, 49, 44, 51, -1, 49, 44, 49,
+ -1, 44, -1, 49, 44, -1, 49, 57, 44, 49,
+ 46, 51, 44, -1, 66, 68, 59, 49, 44, 51,
+ 66, 87, 5, 49, 13, 51, 13, 16, 5, 16,
+ 13, 20, 13, 20, -1, -1, 13, -1, -1, 20,
+ 21, 22, 23, 24, -1, 28, 29, -1, 35, -1,
+ -1, 28, 29, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 13, -1, -1, 16, -1, -1, -1, 20, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1};
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/parser/qmljsgrammar_p.h b/src/declarative/qml/parser/qmljsgrammar_p.h
new file mode 100644
index 0000000..c2e2693
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsgrammar_p.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+// This file was generated by qlalr - DO NOT EDIT!
+#ifndef QMLJSGRAMMAR_P_H
+#define QMLJSGRAMMAR_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlJSGrammar
+{
+public:
+ enum VariousConstants {
+ EOF_SYMBOL = 0,
+ REDUCE_HERE = 99,
+ SHIFT_THERE = 98,
+ T_AND = 1,
+ T_AND_AND = 2,
+ T_AND_EQ = 3,
+ T_AS = 91,
+ T_AUTOMATIC_SEMICOLON = 62,
+ T_BREAK = 4,
+ T_CASE = 5,
+ T_CATCH = 6,
+ T_COLON = 7,
+ T_COMMA = 8,
+ T_COMMENT = 88,
+ T_CONST = 84,
+ T_CONTINUE = 9,
+ T_DEBUGGER = 85,
+ T_DEFAULT = 10,
+ T_DELETE = 11,
+ T_DIVIDE_ = 12,
+ T_DIVIDE_EQ = 13,
+ T_DO = 14,
+ T_DOT = 15,
+ T_ELSE = 16,
+ T_EQ = 17,
+ T_EQ_EQ = 18,
+ T_EQ_EQ_EQ = 19,
+ T_FALSE = 83,
+ T_FEED_JS_EXPRESSION = 95,
+ T_FEED_JS_PROGRAM = 97,
+ T_FEED_JS_SOURCE_ELEMENT = 96,
+ T_FEED_JS_STATEMENT = 94,
+ T_FEED_UI_OBJECT_MEMBER = 93,
+ T_FEED_UI_PROGRAM = 92,
+ T_FINALLY = 20,
+ T_FOR = 21,
+ T_FUNCTION = 22,
+ T_GE = 23,
+ T_GT = 24,
+ T_GT_GT = 25,
+ T_GT_GT_EQ = 26,
+ T_GT_GT_GT = 27,
+ T_GT_GT_GT_EQ = 28,
+ T_IDENTIFIER = 29,
+ T_IF = 30,
+ T_IMPORT = 90,
+ T_IN = 31,
+ T_INSTANCEOF = 32,
+ T_LBRACE = 33,
+ T_LBRACKET = 34,
+ T_LE = 35,
+ T_LPAREN = 36,
+ T_LT = 37,
+ T_LT_LT = 38,
+ T_LT_LT_EQ = 39,
+ T_MINUS = 40,
+ T_MINUS_EQ = 41,
+ T_MINUS_MINUS = 42,
+ T_MULTILINE_STRING_LITERAL = 87,
+ T_NEW = 43,
+ T_NOT = 44,
+ T_NOT_EQ = 45,
+ T_NOT_EQ_EQ = 46,
+ T_NULL = 81,
+ T_NUMERIC_LITERAL = 47,
+ T_OR = 48,
+ T_OR_EQ = 49,
+ T_OR_OR = 50,
+ T_PLUS = 51,
+ T_PLUS_EQ = 52,
+ T_PLUS_PLUS = 53,
+ T_PROPERTY = 66,
+ T_PUBLIC = 89,
+ T_QUESTION = 54,
+ T_RBRACE = 55,
+ T_RBRACKET = 56,
+ T_READONLY = 68,
+ T_REMAINDER = 57,
+ T_REMAINDER_EQ = 58,
+ T_RESERVED_WORD = 86,
+ T_RETURN = 59,
+ T_RPAREN = 60,
+ T_SEMICOLON = 61,
+ T_SIGNAL = 67,
+ T_STAR = 63,
+ T_STAR_EQ = 64,
+ T_STRING_LITERAL = 65,
+ T_SWITCH = 69,
+ T_THIS = 70,
+ T_THROW = 71,
+ T_TILDE = 72,
+ T_TRUE = 82,
+ T_TRY = 73,
+ T_TYPEOF = 74,
+ T_VAR = 75,
+ T_VOID = 76,
+ T_WHILE = 77,
+ T_WITH = 78,
+ T_XOR = 79,
+ T_XOR_EQ = 80,
+
+ ACCEPT_STATE = 635,
+ RULE_COUNT = 343,
+ STATE_COUNT = 636,
+ TERMINAL_COUNT = 100,
+ NON_TERMINAL_COUNT = 106,
+
+ GOTO_INDEX_OFFSET = 636,
+ GOTO_INFO_OFFSET = 2520,
+ GOTO_CHECK_OFFSET = 2520
+ };
+
+ static const char *const spell [];
+ static const short lhs [];
+ static const short rhs [];
+ static const short goto_default [];
+ static const short action_default [];
+ static const short action_index [];
+ static const short action_info [];
+ static const short action_check [];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
+ if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
+ return goto_default [nt];
+
+ return action_info [GOTO_INFO_OFFSET + yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
+};
+
+
+QT_END_NAMESPACE
+#endif // QMLJSGRAMMAR_P_H
+
diff --git a/src/declarative/qml/parser/qmljslexer.cpp b/src/declarative/qml/parser/qmljslexer.cpp
new file mode 100644
index 0000000..cf3ed34
--- /dev/null
+++ b/src/declarative/qml/parser/qmljslexer.cpp
@@ -0,0 +1,1161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "qmljslexer_p.h"
+
+#include "qmljsglobal_p.h"
+#include "qmljsengine_p.h"
+#include "qmljsgrammar_p.h"
+
+#include <QtCore/qcoreapplication.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+QT_QML_BEGIN_NAMESPACE
+
+extern double qstrtod(const char *s00, char const **se, bool *ok);
+
+#define shiftWindowsLineBreak() \
+ do { \
+ if (((current == '\r') && (next1 == '\n')) \
+ || ((current == '\n') && (next1 == '\r'))) { \
+ shift(1); \
+ } \
+ } \
+ while (0)
+
+namespace QmlJS {
+extern double integerFromString(const char *buf, int size, int radix);
+}
+
+using namespace QmlJS;
+
+Lexer::Lexer(Engine *eng, bool tokenizeComments)
+ : driver(eng),
+ yylineno(0),
+ done(false),
+ size8(128), size16(128),
+ pos8(0), pos16(0),
+ terminator(false),
+ restrKeyword(false),
+ delimited(false),
+ stackToken(-1),
+ state(Start),
+ pos(0),
+ code(0), length(0),
+ yycolumn(0),
+ startpos(0),
+ startlineno(0), startcolumn(0),
+ bol(true),
+ current(0), next1(0), next2(0), next3(0),
+ err(NoError),
+ wantRx(false),
+ check_reserved(true),
+ parenthesesState(IgnoreParentheses),
+ parenthesesCount(0),
+ prohibitAutomaticSemicolon(false),
+ tokenizeComments(tokenizeComments)
+{
+ driver->setLexer(this);
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new QChar[size16];
+ pattern = 0;
+ flags = 0;
+
+}
+
+Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+void Lexer::setCode(const QString &c, int lineno)
+{
+ errmsg = QString();
+ yylineno = lineno;
+ yycolumn = 1;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c.unicode();
+ length = c.length();
+ bol = true;
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void Lexer::shift(uint p)
+{
+ while (p--) {
+ ++pos;
+ ++yycolumn;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int Lexer::findReservedWord(const QChar *c, int size) const
+{
+ switch (size) {
+ case 2: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
+ return QmlJSGrammar::T_DO;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
+ return QmlJSGrammar::T_IF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
+ return QmlJSGrammar::T_IN;
+ else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s'))
+ return QmlJSGrammar::T_AS;
+ } break;
+
+ case 3: {
+ if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
+ return QmlJSGrammar::T_FOR;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
+ return QmlJSGrammar::T_NEW;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
+ return QmlJSGrammar::T_TRY;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
+ return QmlJSGrammar::T_VAR;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 4: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_CASE;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_ELSE;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
+ return QmlJSGrammar::T_THIS;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
+ return QmlJSGrammar::T_VOID;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
+ return QmlJSGrammar::T_WITH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_TRUE;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
+ return QmlJSGrammar::T_NULL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 5: {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('k'))
+ return QmlJSGrammar::T_BREAK;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h'))
+ return QmlJSGrammar::T_CATCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w'))
+ return QmlJSGrammar::T_THROW;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e'))
+ return QmlJSGrammar::T_WHILE;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('t'))
+ return QmlJSGrammar::T_CONST;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('e'))
+ return QmlJSGrammar::T_FALSE;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
+ && c[4] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 6: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
+ return QmlJSGrammar::T_DELETE;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
+ return QmlJSGrammar::T_RETURN;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
+ return QmlJSGrammar::T_SWITCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
+ return QmlJSGrammar::T_TYPEOF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QmlJSGrammar::T_IMPORT;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l'))
+ return QmlJSGrammar::T_SIGNAL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QmlJSGrammar::T_PUBLIC;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
+ && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 7: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('t'))
+ return QmlJSGrammar::T_DEFAULT;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('y'))
+ return QmlJSGrammar::T_FINALLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('n'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
+ && c[6] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
+ && c[6] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 8: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
+ return QmlJSGrammar::T_CONTINUE;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
+ return QmlJSGrammar::T_FUNCTION;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
+ return QmlJSGrammar::T_DEBUGGER;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y'))
+ return QmlJSGrammar::T_PROPERTY;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('d')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('y'))
+ return QmlJSGrammar::T_READONLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 9: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
+ && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
+ && c[8] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('d'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 10: {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
+ return QmlJSGrammar::T_INSTANCEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 12: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
+ && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ } // switch
+
+ return -1;
+}
+
+int Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ ushort stringType = 0; // either single or double quotes
+ bool multiLineString = false;
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = -1;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ recordStartPos();
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ recordStartPos();
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ syncProhibitAutomaticSemicolon();
+ if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
+ // automatic semicolon insertion if program incomplete
+ token = QmlJSGrammar::T_SEMICOLON;
+ stackToken = 0;
+ setDone(Other);
+ } else {
+ setDone(Eof);
+ }
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ terminator = true;
+ syncProhibitAutomaticSemicolon();
+ if (restrKeyword) {
+ token = QmlJSGrammar::T_SEMICOLON;
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ recordStartPos();
+ state = InString;
+ multiLineString = false;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ recordStartPos();
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ recordStartPos();
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ recordStartPos();
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ recordStartPos();
+ record8(current);
+ state = InDecimal;
+ } else {
+ recordStartPos();
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ if (terminator && !delimited && !prohibitAutomaticSemicolon
+ && (token == QmlJSGrammar::T_PLUS_PLUS
+ || token == QmlJSGrammar::T_MINUS_MINUS)) {
+ // automatic semicolon insertion
+ stackToken = token;
+ token = QmlJSGrammar::T_SEMICOLON;
+ }
+ setDone(Other);
+ }
+ else {
+ setDone(Bad);
+ err = IllegalCharacter;
+ errmsg = QCoreApplication::translate("QmlParser", "Illegal character");
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (isLineTerminator()) {
+ multiLineString = true;
+ record16(current);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ err = UnclosedStringLiteral;
+ errmsg = QCoreApplication::translate("QmlParser", "Unclosed string at end of line");
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) &&
+ isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ err = IllegalEscapeSequence;
+ errmsg = QCoreApplication::translate("QmlParser", "Illegal escape squence");
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ } else {
+ record16(singleEscape(current));
+ }
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(QLatin1Char(convertHex(current, next1)));
+ shift(1);
+ } else if (current == stringType) {
+ record16(QLatin1Char('x'));
+ shift(1);
+ setDone(String);
+ } else {
+ record16(QLatin1Char('x'));
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16(QLatin1Char('u'));
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ err = IllegalUnicodeEscapeSequence;
+ errmsg = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence");
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ terminator = true;
+ bol = true;
+ if (restrKeyword) {
+ token = QmlJSGrammar::T_SEMICOLON;
+ setDone(Other);
+ } else
+ state = Start;
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ } else if (current == 0) {
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ setDone(Eof);
+ }
+
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ err = UnclosedComment;
+ errmsg = QCoreApplication::translate("QmlParser", "Unclosed comment at end of file");
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ }
+
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current))
+ record8(current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Octal);
+ }
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else {
+ setDone(Bad);
+ err = IllegalExponentIndicator;
+ errmsg = QCoreApplication::translate("QmlParser", "Illegal syntax for exponential number");
+ }
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Number);
+ }
+ break;
+ default:
+ Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current)) {
+ state = Bad;
+ err = IllegalIdentifier;
+ errmsg = QCoreApplication::translate("QmlParser", "Identifier cannot start with numeric literal");
+ }
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+ double dval = 0;
+ if (state == Number) {
+ dval = qstrtod(buffer8, 0, 0);
+ } else if (state == Hex) { // scan hex numbers
+ dval = integerFromString(buffer8, pos8, 16);
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ dval = integerFromString(buffer8, pos8, 8);
+ state = Number;
+ }
+
+ restrKeyword = false;
+ delimited = false;
+
+ switch (parenthesesState) {
+ case IgnoreParentheses:
+ break;
+ case CountParentheses:
+ if (token == QmlJSGrammar::T_RPAREN) {
+ --parenthesesCount;
+ if (parenthesesCount == 0)
+ parenthesesState = BalancedParentheses;
+ } else if (token == QmlJSGrammar::T_LPAREN) {
+ ++parenthesesCount;
+ }
+ break;
+ case BalancedParentheses:
+ parenthesesState = IgnoreParentheses;
+ break;
+ }
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if (token == QmlJSGrammar::T_RBRACE || token == QmlJSGrammar::T_SEMICOLON)
+ delimited = true;
+ return token;
+ case Identifier:
+ if ((token = findReservedWord(buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return QmlJSGrammar::T_IDENTIFIER;
+ }
+ if (token == QmlJSGrammar::T_CONTINUE || token == QmlJSGrammar::T_BREAK
+ || token == QmlJSGrammar::T_RETURN || token == QmlJSGrammar::T_THROW) {
+ restrKeyword = true;
+ } else if (token == QmlJSGrammar::T_IF || token == QmlJSGrammar::T_FOR
+ || token == QmlJSGrammar::T_WHILE || token == QmlJSGrammar::T_WITH) {
+ parenthesesState = CountParentheses;
+ parenthesesCount = 0;
+ } else if (token == QmlJSGrammar::T_DO) {
+ parenthesesState = BalancedParentheses;
+ }
+ return token;
+ case String:
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return multiLineString?QmlJSGrammar::T_MULTILINE_STRING_LITERAL:QmlJSGrammar::T_STRING_LITERAL;
+ case Number:
+ qsyylval.dval = dval;
+ return QmlJSGrammar::T_NUMERIC_LITERAL;
+ case Bad:
+ return -1;
+ default:
+ Q_ASSERT(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool Lexer::isIdentLetter(ushort c)
+{
+ // ASCII-biased, since all reserved words are ASCII, aand hence the
+ // bulk of content to be parsed.
+ if ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c == '$'
+ || c == '_')
+ return true;
+ if (c < 128)
+ return false;
+ return QChar(c).isLetterOrNumber();
+}
+
+bool Lexer::isDecimalDigit(ushort c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool Lexer::isHexDigit(ushort c) const
+{
+ return ((c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F'));
+}
+
+bool Lexer::isOctalDigit(ushort c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int Lexer::matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return QmlJSGrammar::T_GT_GT_GT_EQ;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_EQ_EQ_EQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_NOT_EQ_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return QmlJSGrammar::T_GT_GT_GT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_LT_LT_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_GT_GT_EQ;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_NOT_EQ;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ return QmlJSGrammar::T_PLUS_PLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ return QmlJSGrammar::T_MINUS_MINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_EQ_EQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_PLUS_EQ;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_MINUS_EQ;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_STAR_EQ;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_DIVIDE_EQ;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_AND_EQ;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_XOR_EQ;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_REMAINDER_EQ;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_OR_EQ;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return QmlJSGrammar::T_LT_LT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return QmlJSGrammar::T_GT_GT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return QmlJSGrammar::T_AND_AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return QmlJSGrammar::T_OR_OR;
+ }
+
+ switch(c1) {
+ case '=': shift(1); return QmlJSGrammar::T_EQ;
+ case '>': shift(1); return QmlJSGrammar::T_GT;
+ case '<': shift(1); return QmlJSGrammar::T_LT;
+ case ',': shift(1); return QmlJSGrammar::T_COMMA;
+ case '!': shift(1); return QmlJSGrammar::T_NOT;
+ case '~': shift(1); return QmlJSGrammar::T_TILDE;
+ case '?': shift(1); return QmlJSGrammar::T_QUESTION;
+ case ':': shift(1); return QmlJSGrammar::T_COLON;
+ case '.': shift(1); return QmlJSGrammar::T_DOT;
+ case '+': shift(1); return QmlJSGrammar::T_PLUS;
+ case '-': shift(1); return QmlJSGrammar::T_MINUS;
+ case '*': shift(1); return QmlJSGrammar::T_STAR;
+ case '/': shift(1); return QmlJSGrammar::T_DIVIDE_;
+ case '&': shift(1); return QmlJSGrammar::T_AND;
+ case '|': shift(1); return QmlJSGrammar::T_OR;
+ case '^': shift(1); return QmlJSGrammar::T_XOR;
+ case '%': shift(1); return QmlJSGrammar::T_REMAINDER;
+ case '(': shift(1); return QmlJSGrammar::T_LPAREN;
+ case ')': shift(1); return QmlJSGrammar::T_RPAREN;
+ case '{': shift(1); return QmlJSGrammar::T_LBRACE;
+ case '}': shift(1); return QmlJSGrammar::T_RBRACE;
+ case '[': shift(1); return QmlJSGrammar::T_LBRACKET;
+ case ']': shift(1); return QmlJSGrammar::T_RBRACKET;
+ case ';': shift(1); return QmlJSGrammar::T_SEMICOLON;
+
+ default: return -1;
+ }
+}
+
+ushort Lexer::singleEscape(ushort c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+ushort Lexer::convertOctal(ushort c1, ushort c2,
+ ushort c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char Lexer::convertHex(ushort c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char Lexer::convertHex(ushort c1, ushort c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+QChar Lexer::convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ return QChar((convertHex(c3) << 4) + convertHex(c4),
+ (convertHex(c1) << 4) + convertHex(c2));
+}
+
+void Lexer::record8(ushort c)
+{
+ Q_ASSERT(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void Lexer::record16(QChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ QChar *tmp = new QChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(QChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+void Lexer::recordStartPos()
+{
+ startpos = pos;
+ startlineno = yylineno;
+ startcolumn = yycolumn;
+}
+
+bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ if (prefix == EqualPrefix)
+ record16(QLatin1Char('='));
+
+ while (1) {
+ if (isLineTerminator() || current == 0) {
+ errmsg = QCoreApplication::translate("QmlParser", "Unterminated regular expression literal");
+ return false;
+ }
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape = !lastWasEscape && (current == '\\');
+ }
+ else {
+ if (driver)
+ pattern = driver->intern(buffer16, pos16);
+ else
+ pattern = 0;
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ flags = 0;
+ while (isIdentLetter(current)) {
+ int flag = Ecma::RegExp::flagFromChar(current);
+ if (flag == 0) {
+ errmsg = QCoreApplication::translate("QmlParser", "Invalid regular expression flag '%0'")
+ .arg(QChar(current));
+ return false;
+ }
+ flags |= flag;
+ record16(current);
+ shift(1);
+ }
+
+ return true;
+}
+
+void Lexer::syncProhibitAutomaticSemicolon()
+{
+ if (parenthesesState == BalancedParentheses) {
+ // we have seen something like "if (foo)", which means we should
+ // never insert an automatic semicolon at this point, since it would
+ // then be expanded into an empty statement (ECMA-262 7.9.1)
+ prohibitAutomaticSemicolon = true;
+ parenthesesState = IgnoreParentheses;
+ } else {
+ prohibitAutomaticSemicolon = false;
+ }
+}
+
+QT_QML_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/qmljslexer_p.h b/src/declarative/qml/parser/qmljslexer_p.h
new file mode 100644
index 0000000..b830071
--- /dev/null
+++ b/src/declarative/qml/parser/qmljslexer_p.h
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLJSLEXER_P_H
+#define QMLJSLEXER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmljsglobal_p.h"
+
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class QML_PARSER_EXPORT Lexer
+{
+public:
+ Lexer(Engine *eng, bool tokenizeComments = false);
+ ~Lexer();
+
+ void setCode(const QString &c, int lineno);
+ int lex();
+
+ int currentLineNo() const { return yylineno; }
+ int currentColumnNo() const { return yycolumn; }
+
+ int tokenOffset() const { return startpos; }
+ int tokenLength() const { return pos - startpos; }
+
+ int startLineNo() const { return startlineno; }
+ int startColumnNo() const { return startcolumn; }
+
+ int endLineNo() const { return currentLineNo(); }
+ int endColumnNo() const
+ { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ enum Error {
+ NoError,
+ IllegalCharacter,
+ UnclosedStringLiteral,
+ IllegalEscapeSequence,
+ IllegalUnicodeEscapeSequence,
+ UnclosedComment,
+ IllegalExponentIndicator,
+ IllegalIdentifier
+ };
+
+ enum ParenthesesState {
+ IgnoreParentheses,
+ CountParentheses,
+ BalancedParentheses
+ };
+
+ enum RegExpBodyPrefix {
+ NoPrefix,
+ EqualPrefix
+ };
+
+ bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+
+ NameId *pattern;
+ int flags;
+
+ State lexerState() const
+ { return state; }
+
+ QString errorMessage() const
+ { return errmsg; }
+ void setErrorMessage(const QString &err)
+ { errmsg = err; }
+ void setErrorMessage(const char *err)
+ { setErrorMessage(QString::fromLatin1(err)); }
+
+ Error error() const
+ { return err; }
+ void clearError()
+ { err = NoError; }
+
+private:
+ Engine *driver;
+ int yylineno;
+ bool done;
+ char *buffer8;
+ QChar *buffer16;
+ uint size8, size16;
+ uint pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ uint pos;
+ void shift(uint p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(ushort c) const;
+ bool isOctalDigit(ushort c) const;
+
+ int matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ ushort singleEscape(ushort c) const;
+ ushort convertOctal(ushort c1, ushort c2,
+ ushort c3) const;
+public:
+ static unsigned char convertHex(ushort c1);
+ static unsigned char convertHex(ushort c1, ushort c2);
+ static QChar convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ static bool isIdentLetter(ushort c);
+ static bool isDecimalDigit(ushort c);
+
+ inline int ival() const { return qsyylval.ival; }
+ inline double dval() const { return qsyylval.dval; }
+ inline NameId *ustr() const { return qsyylval.ustr; }
+
+ const QChar *characterBuffer() const { return buffer16; }
+ int characterCount() const { return pos16; }
+
+private:
+ void record8(ushort c);
+ void record16(QChar c);
+ void recordStartPos();
+
+ int findReservedWord(const QChar *buffer, int size) const;
+
+ void syncProhibitAutomaticSemicolon();
+
+ const QChar *code;
+ uint length;
+ int yycolumn;
+ int startpos;
+ int startlineno;
+ int startcolumn;
+ int bol; // begin of line
+
+ union {
+ int ival;
+ double dval;
+ NameId *ustr;
+ } qsyylval;
+
+ // current and following unicode characters
+ ushort current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ QString errmsg;
+ Error err;
+
+ bool wantRx;
+ bool check_reserved;
+
+ ParenthesesState parenthesesState;
+ int parenthesesCount;
+ bool prohibitAutomaticSemicolon;
+ bool tokenizeComments;
+};
+
+} // namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsmemorypool_p.h b/src/declarative/qml/parser/qmljsmemorypool_p.h
new file mode 100644
index 0000000..3da2678
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsmemorypool_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLJSMEMORYPOOL_P_H
+#define QMLJSMEMORYPOOL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmljsglobal_p.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qshareddata.h>
+
+#include <string.h>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class QML_PARSER_EXPORT MemoryPool : public QSharedData
+{
+public:
+ enum { maxBlockCount = -1 };
+ enum { defaultBlockSize = 1 << 12 };
+
+ MemoryPool() {
+ m_blockIndex = maxBlockCount;
+ m_currentIndex = 0;
+ m_storage = 0;
+ m_currentBlock = 0;
+ m_currentBlockSize = 0;
+ }
+
+ virtual ~MemoryPool() {
+ for (int index = 0; index < m_blockIndex + 1; ++index)
+ qFree(m_storage[index]);
+
+ qFree(m_storage);
+ }
+
+ char *allocate(int bytes) {
+ bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment)
+ if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) {
+ ++m_blockIndex;
+ m_currentBlockSize = defaultBlockSize << m_blockIndex;
+
+ m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex)));
+ m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize));
+ ::memset(m_currentBlock, 0, m_currentBlockSize);
+
+ m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned
+ Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize);
+ }
+
+ char *p = reinterpret_cast<char *>
+ (m_currentBlock + m_currentIndex);
+
+ m_currentIndex += bytes;
+
+ return p;
+ }
+
+ int bytesAllocated() const {
+ int bytes = 0;
+ for (int index = 0; index < m_blockIndex; ++index)
+ bytes += (defaultBlockSize << index);
+ bytes += m_currentIndex;
+ return bytes;
+ }
+
+private:
+ int m_blockIndex;
+ int m_currentIndex;
+ char *m_currentBlock;
+ int m_currentBlockSize;
+ char **m_storage;
+
+private:
+ Q_DISABLE_COPY(MemoryPool)
+};
+
+} // namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsnodepool_p.h b/src/declarative/qml/parser/qmljsnodepool_p.h
new file mode 100644
index 0000000..abe4cc8
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsnodepool_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLJSNODEPOOL_P_H
+#define QMLJSNODEPOOL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmljsglobal_p.h"
+#include "qmljsmemorypool_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+namespace AST {
+class Node;
+} // namespace AST
+
+class Code;
+class CompilationUnit;
+class Engine;
+
+template <typename NodeType>
+inline NodeType *makeAstNode(MemoryPool *storage)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType();
+ return node;
+}
+
+template <typename NodeType, typename Arg1>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4);
+ return node;
+}
+
+class QML_PARSER_EXPORT NodePool : public MemoryPool
+{
+public:
+ NodePool(const QString &fileName, Engine *engine);
+ virtual ~NodePool();
+
+ Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation);
+
+ inline QString fileName() const { return m_fileName; }
+ inline Engine *engine() const { return m_engine; }
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ inline qint64 id() const { return m_id; }
+#endif
+
+private:
+ QHash<AST::Node*, Code*> m_codeCache;
+ QString m_fileName;
+ Engine *m_engine;
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ qint64 m_id;
+#endif
+
+private:
+ Q_DISABLE_COPY(NodePool)
+};
+
+} // namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsparser.cpp b/src/declarative/qml/parser/qmljsparser.cpp
new file mode 100644
index 0000000..856d06d
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsparser.cpp
@@ -0,0 +1,1843 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtDebug>
+#include <QtGui/QApplication>
+
+#include <string.h>
+
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsast_p.h"
+#include "qmljsnodepool_p.h"
+
+
+
+#include "qmljsparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+using namespace QmlJS;
+
+QT_QML_BEGIN_NAMESPACE
+
+void Parser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(Engine *driver, int token)
+{
+ return token == QmlJSGrammar::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+Parser::Parser(Engine *engine):
+ driver(engine),
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+Parser::~Parser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
+{
+ QVarLengthArray<NameId *, 4> nameIds;
+ QVarLengthArray<AST::SourceLocation, 4> locations;
+
+ AST::ExpressionNode *it = expr;
+ while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) {
+ nameIds.append(m->name);
+ locations.append(m->identifierToken);
+ it = m->base;
+ }
+
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
+ AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name);
+ q->identifierToken = idExpr->identifierToken;
+
+ AST::UiQualifiedId *currentId = q;
+ for (int i = nameIds.size() - 1; i != -1; --i) {
+ currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]);
+ currentId->identifierToken = locations[i];
+ }
+
+ return currentId->finish();
+ }
+
+ return 0;
+}
+
+bool Parser::parse(int startToken)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ token_buffer[0].token = startToken;
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+
+case 0: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 1: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 2: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 3: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 4: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 5: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 6: {
+ sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+} break;
+
+case 8: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+
+case 9: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+
+case 10: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+
+case 13: {
+ sym(1).UiImport->semicolonToken = loc(2);
+} break;
+
+case 15: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->semicolonToken = loc(3);
+} break;
+
+case 17: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->asToken = loc(3);
+ sym(1).UiImport->importIdToken = loc(4);
+ sym(1).UiImport->importId = sym(4).sval;
+ sym(1).UiImport->semicolonToken = loc(5);
+} break;
+
+case 19: {
+ sym(1).UiImport->asToken = loc(2);
+ sym(1).UiImport->importIdToken = loc(3);
+ sym(1).UiImport->importId = sym(3).sval;
+ sym(1).UiImport->semicolonToken = loc(4);
+} break;
+
+case 20: {
+ AST::UiImport *node = 0;
+
+ if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
+ node->fileNameToken = loc(2);
+ } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
+ QString text;
+ for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
+ text += q->name->asString();
+ if (q->next) text += QLatin1String(".");
+ }
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
+ node->fileNameToken = loc(2);
+ }
+
+ sym(1).Node = node;
+
+ if (! node) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id or a string literal")));
+
+ return false; // ### remove me
+ }
+} break;
+
+case 21: {
+ sym(1).Node = 0;
+} break;
+
+case 22: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 23: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 24: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+
+case 25: {
+ sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 26: {
+ AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(),
+ sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 27: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 28: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 29: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId,
+ sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+} break;
+
+case 31: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 32: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+case 33:case 34:case 35:case 36:
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 37:
+
+case 38: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+
+case 40: {
+ sym(1).Node = 0;
+} break;
+
+case 41: {
+ sym(1).Node = sym(1).UiParameterList->finish ();
+} break;
+
+case 42: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 43: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 45: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->parameters = sym(4).UiParameterList;
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 47: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 49: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval);
+ node->typeModifier = sym(2).sval;
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 51: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 53: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 55: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 57: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 59: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 60: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 61: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 63: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 64: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 65: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 66: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 67: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 68: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 69: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 70: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 71: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 72:
+case 73: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 74: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 75: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 76: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 77: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 78: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 79: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 80: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ sym(4).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 81: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 82: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 83: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 84: {
+ if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
+ QLatin1String("Ignored annotation")));
+
+ sym(1).Expression = mem->base;
+ }
+
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false; // ### recover
+ }
+} break;
+
+case 85: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression);
+} break;
+
+case 86: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression);
+} break;
+
+case 87: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList,
+ (AST::Elision *) 0, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 88: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(),
+ sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 89: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 90: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 91: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 92: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 93: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 94:
+case 95: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 96: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 97: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 98: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 99:
+
+case 100:
+
+case 101:
+
+case 102:
+
+case 103:
+
+case 104:
+
+case 105:
+
+case 106:
+
+case 107:
+
+case 108:
+
+case 109:
+
+case 110:
+
+case 111:
+
+case 112:
+
+case 113:
+
+case 114:
+
+case 115:
+
+case 116:
+
+case 117:
+
+case 118:
+
+case 119:
+
+case 120:
+
+case 121:
+
+case 122:
+
+case 123:
+
+case 124:
+
+case 125:
+
+case 126:
+
+case 127:
+
+case 128:
+
+case 129:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+
+case 134: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 135: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 136: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 138: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 139: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 140: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 141: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 142: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 143: {
+ sym(1).Node = 0;
+} break;
+
+case 144: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+
+case 145: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+
+case 146: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 150: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 151: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 153: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 154: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 155: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 156: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 157: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 158: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 159: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 160: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 161: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 163: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 164: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 165: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 167: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 168: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 170: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 171: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 172: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 174: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 175: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 176: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 177: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 178: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 179: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 181: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 182: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 183: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 184: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 185: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 187: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 188: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 189: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 190: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 192: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 193: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 194: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 195: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 197: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 199: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 201: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 203: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 205: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 207: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 209: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 211: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 213: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 215: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 217: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 219: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 221: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 223: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 224: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+
+case 225: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+
+case 226: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+
+case 227: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+
+case 228: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+
+case 229: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+
+case 230: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+
+case 231: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+
+case 232: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+
+case 233: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+
+case 234: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+
+case 235: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+
+case 237: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 238: {
+ sym(1).Node = 0;
+} break;
+
+case 241: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 242: {
+ sym(1).Node = 0;
+} break;
+
+case 259: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 260: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 261: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+
+case 262: {
+ sym(1).Node = 0;
+} break;
+
+case 263: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+
+case 265: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 266: {
+ sym(1).ival = T_CONST;
+} break;
+
+case 267: {
+ sym(1).ival = T_VAR;
+} break;
+
+case 268: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 269: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 270: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 271: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+
+case 272: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 273: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 274: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 275: {
+ sym(1).Node = 0;
+} break;
+
+case 277: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 278: {
+ sym(1).Node = 0;
+} break;
+
+case 280: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 282: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 283: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 284: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 286: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 287: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 288: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 289: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+
+case 290: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 291: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 293: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 295: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 297: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 299: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 301: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 302: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 303: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 304: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 305: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 306: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+
+case 307: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+
+case 308: {
+ sym(1).Node = 0;
+} break;
+
+case 309: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+
+case 310: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 311: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+case 312:
+case 313: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 314: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 316: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 317: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 318: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 319: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 320: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 321: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 323: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 324: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 325: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 326: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 327: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 328: {
+ sym(1).Node = 0;
+} break;
+
+case 329: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+
+case 330: {
+ sym(1).Node = 0;
+} break;
+
+case 332: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+
+case 333: {
+ sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+
+case 334: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+
+case 335: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+
+case 336: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 337: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+
+case 338: {
+ sym(1).sval = 0;
+} break;
+
+case 340: {
+ sym(1).Node = 0;
+} break;
+
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = qApp->translate("QmlParser", "Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ QString msg;
+ int token = token_buffer[0].token;
+ if (token < 0 || token >= TERMINAL_COUNT)
+ msg = qApp->translate("QmlParser", "Syntax error");
+ else
+ msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM ||
+ tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION ||
+ tk == T_FEED_JS_SOURCE_ELEMENT)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = qApp->translate("QmlParser", "Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_QML_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/qmljsparser_p.h b/src/declarative/qml/parser/qmljsparser_p.h
new file mode 100644
index 0000000..42fb422
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsparser_p.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+//
+// 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.
+//
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+#ifndef QMLJSPARSER_P_H
+#define QMLJSPARSER_P_H
+
+#include "qmljsglobal_p.h"
+#include "qmljsgrammar_p.h"
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class QML_PARSER_EXPORT Parser: protected QmlJSGrammar
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ NameId *sval;
+ AST::ArgumentList *ArgumentList;
+ AST::CaseBlock *CaseBlock;
+ AST::CaseClause *CaseClause;
+ AST::CaseClauses *CaseClauses;
+ AST::Catch *Catch;
+ AST::DefaultClause *DefaultClause;
+ AST::ElementList *ElementList;
+ AST::Elision *Elision;
+ AST::ExpressionNode *Expression;
+ AST::Finally *Finally;
+ AST::FormalParameterList *FormalParameterList;
+ AST::FunctionBody *FunctionBody;
+ AST::FunctionDeclaration *FunctionDeclaration;
+ AST::Node *Node;
+ AST::PropertyName *PropertyName;
+ AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ AST::SourceElement *SourceElement;
+ AST::SourceElements *SourceElements;
+ AST::Statement *Statement;
+ AST::StatementList *StatementList;
+ AST::Block *Block;
+ AST::VariableDeclaration *VariableDeclaration;
+ AST::VariableDeclarationList *VariableDeclarationList;
+
+ AST::UiProgram *UiProgram;
+ AST::UiImportList *UiImportList;
+ AST::UiImport *UiImport;
+ AST::UiParameterList *UiParameterList;
+ AST::UiPublicMember *UiPublicMember;
+ AST::UiObjectDefinition *UiObjectDefinition;
+ AST::UiObjectInitializer *UiObjectInitializer;
+ AST::UiObjectBinding *UiObjectBinding;
+ AST::UiScriptBinding *UiScriptBinding;
+ AST::UiArrayBinding *UiArrayBinding;
+ AST::UiObjectMember *UiObjectMember;
+ AST::UiObjectMemberList *UiObjectMemberList;
+ AST::UiArrayMemberList *UiArrayMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ AST::UiSignature *UiSignature;
+ AST::UiFormalList *UiFormalList;
+ AST::UiFormal *UiFormal;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ // parse a UI program
+ bool parse() { return parse(T_FEED_UI_PROGRAM); }
+ bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
+ bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
+ bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); }
+ bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
+ bool parseProgram() { return parse(T_FEED_JS_PROGRAM); }
+
+ AST::UiProgram *ast() const
+ { return AST::cast<AST::UiProgram *>(program); }
+
+ AST::Statement *statement() const
+ {
+ if (! program)
+ return 0;
+
+ return program->statementCast();
+ }
+
+ AST::ExpressionNode *expression() const
+ {
+ if (! program)
+ return 0;
+
+ return program->expressionCast();
+ }
+
+ AST::UiObjectMember *uiObjectMember() const
+ {
+ if (! program)
+ return 0;
+
+ return program->uiObjectMemberCast();
+ }
+
+ AST::Node *rootNode() const
+ { return program; }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ bool parse(int startToken);
+
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+ AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
+
+protected:
+ Engine *driver;
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ AST::SourceLocation *location_stack;
+
+ AST::Node *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ AST::SourceLocation loc;
+ };
+
+ double yylval;
+ AST::SourceLocation yylloc;
+ AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+} // end of namespace QmlJS
+
+
+
+#define J_SCRIPT_REGEXPLITERAL_RULE1 74
+
+#define J_SCRIPT_REGEXPLITERAL_RULE2 75
+
+QT_QML_END_NAMESPACE
+
+
+
+#endif // QMLJSPARSER_P_H
diff --git a/src/declarative/qml/qbitfield_p.h b/src/declarative/qml/qbitfield_p.h
new file mode 100644
index 0000000..8b3afdb
--- /dev/null
+++ b/src/declarative/qml/qbitfield_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBITFIELD_P_H
+#define QBITFIELD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBitField
+{
+public:
+ inline QBitField();
+ inline QBitField(const quint32 *, int bits);
+ inline QBitField(const QBitField &);
+ inline ~QBitField();
+
+ inline QBitField &operator=(const QBitField &);
+
+ inline quint32 size() const;
+ inline QBitField united(const QBitField &);
+ inline bool testBit(int) const;
+
+private:
+ quint32 bits:31;
+ quint32 *ownData;
+ const quint32 *data;
+};
+
+QBitField::QBitField()
+: bits(0), ownData(0), data(0)
+{
+}
+
+QBitField::QBitField(const quint32 *bitData, int bitCount)
+: bits((quint32)bitCount), ownData(0), data(bitData)
+{
+}
+
+QBitField::QBitField(const QBitField &other)
+: bits(other.bits), ownData(other.ownData), data(other.data)
+{
+ if (ownData)
+ ++(*ownData);
+}
+
+QBitField::~QBitField()
+{
+ if (ownData)
+ if(0 == --(*ownData)) delete [] ownData;
+}
+
+QBitField &QBitField::operator=(const QBitField &other)
+{
+ if (other.data == data)
+ return *this;
+
+ if (ownData)
+ if(0 == --(*ownData)) delete [] ownData;
+
+ bits = other.bits;
+ ownData = other.ownData;
+ data = other.data;
+
+ if (ownData)
+ ++(*ownData);
+
+ return *this;
+}
+
+inline quint32 QBitField::size() const
+{
+ return bits;
+}
+
+QBitField QBitField::united(const QBitField &o)
+{
+ if (o.bits == 0) {
+ return *this;
+ } else if (bits == 0) {
+ return o;
+ } else {
+ int max = (bits > o.bits)?bits:o.bits;
+ int length = (max + 31) / 32;
+ QBitField rv;
+ rv.bits = max;
+ rv.ownData = new quint32[length + 1];
+ *(rv.ownData) = 1;
+ rv.data = rv.ownData + 1;
+ if (bits > o.bits) {
+ ::memcpy((quint32 *)rv.data, data, length * sizeof(quint32));
+ for (quint32 ii = 0; ii < (o.bits + quint32(31)) / 32; ++ii)
+ ((quint32 *)rv.data)[ii] |= o.data[ii];
+ } else {
+ ::memcpy((quint32 *)rv.data, o.data, length * sizeof(quint32));
+ for (quint32 ii = 0; ii < (bits + quint32(31)) / 32; ++ii)
+ ((quint32 *)rv.data)[ii] |= data[ii];
+ }
+ return rv;
+ }
+}
+
+bool QBitField::testBit(int b) const
+{
+ Q_ASSERT(b >= 0);
+ if ((quint32)b < bits) {
+ return data[b / 32] & (1 << (b % 32));
+ } else {
+ return false;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QBITFIELD_P_H
diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..11b9f80
--- /dev/null
+++ b/src/declarative/qml/qmetaobjectbuilder.cpp
@@ -0,0 +1,2575 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetaobjectbuilder_p.h"
+
+#ifndef Q_OS_WIN
+#include <stdint.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMetaObjectBuilder
+ \internal
+ \brief The QMetaObjectBuilder class supports building QMetaObject objects at runtime.
+
+*/
+
+/*!
+ \enum QMetaObjectBuilder::AddMember
+ This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
+
+ \value ClassName Add the class name.
+ \value SuperClass Add the super class.
+ \value Methods Add methods that aren't signals or slots.
+ \value Signals Add signals.
+ \value Slots Add slots.
+ \value Constructors Add constructors.
+ \value Properties Add properties.
+ \value Enumerators Add enumerators.
+ \value ClassInfos Add items of class information.
+ \value RelatedMetaObjects Add related meta objects.
+ \value StaticMetacall Add the static metacall function.
+ \value PublicMethods Add public methods (ignored for signals).
+ \value ProtectedMethods Add protected methods (ignored for signals).
+ \value PrivateMethods All private methods (ignored for signals).
+ \value AllMembers Add all members.
+ \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
+*/
+
+// copied from moc's generator.cpp
+uint qvariant_nameToType(const char* name)
+{
+ if (!name)
+ return 0;
+
+ if (strcmp(name, "QVariant") == 0)
+ return 0xffffffff;
+ if (strcmp(name, "QCString") == 0)
+ return QMetaType::QByteArray;
+ if (strcmp(name, "Q_LLONG") == 0)
+ return QMetaType::LongLong;
+ if (strcmp(name, "Q_ULLONG") == 0)
+ return QMetaType::ULongLong;
+ if (strcmp(name, "QIconSet") == 0)
+ return QMetaType::QIcon;
+
+ uint tp = QMetaType::type(name);
+ return tp < QMetaType::User ? tp : 0;
+}
+
+/*
+ Returns true if the type is a QVariant types.
+*/
+bool isVariantType(const char* type)
+{
+ return qvariant_nameToType(type) != 0;
+}
+
+// copied from qmetaobject.cpp
+// do not touch without touching the moc as well
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+};
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData;
+ int flags;
+};
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+// end of copied lines from qmetaobject.cpp
+
+class QMetaMethodBuilderPrivate
+{
+public:
+ QMetaMethodBuilderPrivate
+ (QMetaMethod::MethodType _methodType,
+ const QByteArray& _signature,
+ const QByteArray& _returnType = QByteArray(),
+ QMetaMethod::Access _access = QMetaMethod::Public)
+ : signature(QMetaObject::normalizedSignature(_signature.constData())),
+ returnType(QMetaObject::normalizedType(_returnType)),
+ attributes(((int)_access) | (((int)_methodType) << 2))
+ {
+ }
+
+ QByteArray signature;
+ QByteArray returnType;
+ QList<QByteArray> parameterNames;
+ QByteArray tag;
+ int attributes;
+
+ QMetaMethod::MethodType methodType() const
+ {
+ return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
+ }
+
+ QMetaMethod::Access access() const
+ {
+ return (QMetaMethod::Access)(attributes & AccessMask);
+ }
+
+ void setAccess(QMetaMethod::Access value)
+ {
+ attributes = ((attributes & ~AccessMask) | (int)value);
+ }
+};
+
+class QMetaPropertyBuilderPrivate
+{
+public:
+ QMetaPropertyBuilderPrivate
+ (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1)
+ : name(_name),
+ type(QMetaObject::normalizedType(_type.constData())),
+ flags(Readable | Writable), notifySignal(-1)
+ {
+ if (notifierIdx >= 0) {
+ flags |= Notify;
+ notifySignal = notifierIdx;
+ }
+ }
+
+ QByteArray name;
+ QByteArray type;
+ int flags;
+ int notifySignal;
+
+ bool flag(int f) const
+ {
+ return ((flags & f) != 0);
+ }
+
+ void setFlag(int f, bool value)
+ {
+ if (value)
+ flags |= f;
+ else
+ flags &= ~f;
+ }
+};
+
+class QMetaEnumBuilderPrivate
+{
+public:
+ QMetaEnumBuilderPrivate(const QByteArray& _name)
+ : name(_name), isFlag(false)
+ {
+ }
+
+ QByteArray name;
+ bool isFlag;
+ QList<QByteArray> keys;
+ QList<int> values;
+};
+
+class QMetaObjectBuilderPrivate
+{
+public:
+ QMetaObjectBuilderPrivate()
+ : flags(0)
+ {
+ superClass = &QObject::staticMetaObject;
+ staticMetacallFunction = 0;
+ }
+
+ QByteArray className;
+ const QMetaObject *superClass;
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
+ QList<QMetaMethodBuilderPrivate> methods;
+ QList<QMetaMethodBuilderPrivate> constructors;
+ QList<QMetaPropertyBuilderPrivate> properties;
+ QList<QByteArray> classInfoNames;
+ QList<QByteArray> classInfoValues;
+ QList<QMetaEnumBuilderPrivate> enumerators;
+#ifdef Q_NO_DATA_RELOCATION
+ QList<QMetaObjectAccessor> relatedMetaObjects;
+#else
+ QList<const QMetaObject *> relatedMetaObjects;
+#endif
+ int flags;
+};
+
+/*!
+ Constructs a new QMetaObjectBuilder.
+*/
+QMetaObjectBuilder::QMetaObjectBuilder()
+{
+ d = new QMetaObjectBuilderPrivate();
+}
+
+/*!
+ Constructs a new QMetaObjectBuilder which is a copy of the
+ meta object information in \a prototype. Note: the super class
+ contents for \a prototype are not copied, only the immediate
+ class that is defined by \a prototype.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+
+ \sa addMetaObject()
+*/
+QMetaObjectBuilder::QMetaObjectBuilder
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ d = new QMetaObjectBuilderPrivate();
+ addMetaObject(prototype, members);
+}
+
+/*!
+ Destroys this meta object builder.
+*/
+QMetaObjectBuilder::~QMetaObjectBuilder()
+{
+ delete d;
+}
+
+/*!
+ Returns the name of the class being constructed by this
+ meta object builder. The default value is an empty QByteArray.
+
+ \sa setClassName(), superClass()
+*/
+QByteArray QMetaObjectBuilder::className() const
+{
+ return d->className;
+}
+
+/*!
+ Sets the \a name of the class being constructed by this
+ meta object builder.
+
+ \sa className(), setSuperClass()
+*/
+void QMetaObjectBuilder::setClassName(const QByteArray& name)
+{
+ d->className = name;
+}
+
+/*!
+ Returns the superclass meta object of the class being constructed
+ by this meta object builder. The default value is the meta object
+ for QObject.
+
+ \sa setSuperClass(), className()
+*/
+const QMetaObject *QMetaObjectBuilder::superClass() const
+{
+ return d->superClass;
+}
+
+/*!
+ Sets the superclass meta object of the class being constructed
+ by this meta object builder to \a meta. The \a meta parameter
+ must not be null.
+
+ \sa superClass(), setClassName()
+*/
+void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ d->superClass = meta;
+}
+
+/*!
+ Returns the flags of the class being constructed by this meta object
+ builder.
+
+ \sa setFlags()
+*/
+QMetaObjectBuilder::MetaObjectFlags QMetaObjectBuilder::flags() const
+{
+ return (QMetaObjectBuilder::MetaObjectFlags)d->flags;
+}
+
+/*!
+ Sets the \a flags of the class being constructed by this meta object
+ builder.
+
+ \sa flags()
+*/
+void QMetaObjectBuilder::setFlags(MetaObjectFlags flags)
+{
+ d->flags = flags;
+}
+
+/*!
+ Returns the number of methods in this class, excluding the number
+ of methods in the base class. These include signals and slots
+ as well as normal member functions.
+
+ \sa addMethod(), method(), removeMethod(), indexOfMethod()
+*/
+int QMetaObjectBuilder::methodCount() const
+{
+ return d->methods.size();
+}
+
+/*!
+ Returns the number of constructors in this class.
+
+ \sa addConstructor(), constructor(), removeConstructor(), indexOfConstructor()
+*/
+int QMetaObjectBuilder::constructorCount() const
+{
+ return d->constructors.size();
+}
+
+/*!
+ Returns the number of properties in this class, excluding the number
+ of properties in the base class.
+
+ \sa addProperty(), property(), removeProperty(), indexOfProperty()
+*/
+int QMetaObjectBuilder::propertyCount() const
+{
+ return d->properties.size();
+}
+
+/*!
+ Returns the number of enumerators in this class, excluding the
+ number of enumerators in the base class.
+
+ \sa addEnumerator(), enumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+int QMetaObjectBuilder::enumeratorCount() const
+{
+ return d->enumerators.size();
+}
+
+/*!
+ Returns the number of items of class information in this class,
+ exclusing the number of items of class information in the base class.
+
+ \sa addClassInfo(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::classInfoCount() const
+{
+ return d->classInfoNames.size();
+}
+
+/*!
+ Returns the number of related meta objects that are associated
+ with this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa addRelatedMetaObject(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::relatedMetaObjectCount() const
+{
+ return d->relatedMetaObjects.size();
+}
+
+/*!
+ Adds a new public method to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the method. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class with the specified
+ \a signature and \a returnType. Returns an object that can be
+ used to adjust the other attributes of the method. The \a signature
+ and \a returnType will be normalized before they are added to
+ the class. If \a returnType is empty, then it indicates that
+ the method has \c{void} as its return type.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod
+ (const QByteArray& signature, const QByteArray& returnType)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Method, signature, returnType));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class that has the same information as
+ \a prototype. This is used to clone the methods of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the method.
+
+ This function will detect if \a prototype is an ordinary method,
+ signal, slot, or constructor and act accordingly.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
+{
+ QMetaMethodBuilder method;
+ if (prototype.methodType() == QMetaMethod::Method)
+ method = addMethod(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Signal)
+ method = addSignal(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Slot)
+ method = addSlot(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Constructor)
+ method = addConstructor(prototype.signature());
+ method.setReturnType(prototype.typeName());
+ method.setParameterNames(prototype.parameterNames());
+ method.setTag(prototype.tag());
+ method.setAccess(prototype.access());
+ method.setAttributes(prototype.attributes());
+ return method;
+}
+
+/*!
+ Adds a new public slot to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the slot. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSignal(), indexOfSlot()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new signal to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the signal. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSlot(), indexOfSignal()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Signal, signature, QByteArray(), QMetaMethod::Protected));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new constructor to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the constructor. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
+{
+ int index = d->constructors.size();
+ d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature));
+ return QMetaMethodBuilder(this, -(index + 1));
+}
+
+/*!
+ Adds a new constructor to this class that has the same information as
+ \a prototype. This is used to clone the constructors of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the constructor.
+
+ This function requires that \a prototype be a constructor.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
+{
+ Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
+ QMetaMethodBuilder ctor = addConstructor(prototype.signature());
+ ctor.setReturnType(prototype.typeName());
+ ctor.setParameterNames(prototype.parameterNames());
+ ctor.setTag(prototype.tag());
+ ctor.setAccess(prototype.access());
+ ctor.setAttributes(prototype.attributes());
+ return ctor;
+}
+
+/*!
+ Adds a new readable/writable property to this class with the
+ specified \a name and \a type. Returns an object that can be used
+ to adjust the other attributes of the property. The \a type will
+ be normalized before it is added to the class. \a notifierId will
+ be registered as the property's \e notify signal.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty
+ (const QByteArray& name, const QByteArray& type, int notifierId)
+{
+ int index = d->properties.size();
+ d->properties.append(QMetaPropertyBuilderPrivate(name, type, notifierId));
+ return QMetaPropertyBuilder(this, index);
+}
+
+/*!
+ Adds a new property to this class that has the same information as
+ \a prototype. This is used to clone the properties of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the property.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
+{
+ QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
+ property.setReadable(prototype.isReadable());
+ property.setWritable(prototype.isWritable());
+ property.setResettable(prototype.isResettable());
+ property.setDesignable(prototype.isDesignable());
+ property.setScriptable(prototype.isScriptable());
+ property.setStored(prototype.isStored());
+ property.setEditable(prototype.isEditable());
+ property.setUser(prototype.isUser());
+ property.setStdCppSet(prototype.hasStdCppSet());
+ property.setEnumOrFlag(prototype.isEnumType());
+ if (prototype.hasNotifySignal()) {
+ // Find an existing method for the notify signal, or add a new one.
+ QMetaMethod method = prototype.notifySignal();
+ int index = indexOfMethod(method.signature());
+ if (index == -1)
+ index = addMethod(method).index();
+ d->properties[property._index].notifySignal = index;
+ d->properties[property._index].setFlag(Notify, true);
+ }
+ return property;
+}
+
+/*!
+ Adds a new enumerator to this class with the specified
+ \a name. Returns an object that can be used to adjust
+ the other attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
+{
+ int index = d->enumerators.size();
+ d->enumerators.append(QMetaEnumBuilderPrivate(name));
+ return QMetaEnumBuilder(this, index);
+}
+
+/*!
+ Adds a new enumerator to this class that has the same information as
+ \a prototype. This is used to clone the enumerators of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
+{
+ QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setIsFlag(prototype.isFlag());
+ int count = prototype.keyCount();
+ for (int index = 0; index < count; ++index)
+ en.addKey(prototype.key(index), prototype.value(index));
+ return en;
+}
+
+/*!
+ Adds \a name and \a value as an item of class information to this class.
+ Returns the index of the new item of class information.
+
+ \sa classInfoCount(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
+{
+ int index = d->classInfoNames.size();
+ d->classInfoNames += name;
+ d->classInfoValues += value;
+ return index;
+}
+
+/*!
+ Adds \a meta to this class as a related meta object. Returns
+ the index of the new related meta object entry.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+#ifdef Q_NO_DATA_RELOCATION
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObjectAccessor &meta)
+#else
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
+#endif
+{
+ Q_ASSERT(meta);
+ int index = d->relatedMetaObjects.size();
+ d->relatedMetaObjects.append(meta);
+ return index;
+}
+
+/*!
+ Adds the contents of \a prototype to this meta object builder.
+ This function is useful for cloning the contents of an existing QMetaObject.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+*/
+void QMetaObjectBuilder::addMetaObject
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ Q_ASSERT(prototype);
+ int index;
+
+ if ((members & ClassName) != 0)
+ d->className = prototype->className();
+
+ if ((members & SuperClass) != 0)
+ d->superClass = prototype->superClass();
+
+ if ((members & (Methods | Signals | Slots)) != 0) {
+ for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
+ QMetaMethod method = prototype->method(index);
+ if (method.methodType() != QMetaMethod::Signal) {
+ if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
+ continue;
+ }
+ if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Signal &&
+ (members & Signals) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Slot &&
+ (members & Slots) != 0) {
+ addMethod(method);
+ }
+ }
+ }
+
+ if ((members & Constructors) != 0) {
+ for (index = 0; index < prototype->constructorCount(); ++index)
+ addConstructor(prototype->constructor(index));
+ }
+
+ if ((members & Properties) != 0) {
+ for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
+ addProperty(prototype->property(index));
+ }
+
+ if ((members & Enumerators) != 0) {
+ for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
+ addEnumerator(prototype->enumerator(index));
+ }
+
+ if ((members & ClassInfos) != 0) {
+ for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
+ QMetaClassInfo ci = prototype->classInfo(index);
+ addClassInfo(ci.name(), ci.value());
+ }
+ }
+
+ if ((members & RelatedMetaObjects) != 0) {
+#ifdef Q_NO_DATA_RELOCATION
+ const QMetaObjectAccessor *objects = 0;
+#else
+ const QMetaObject **objects;
+ if (priv(prototype->d.data)->revision < 2) {
+ objects = (const QMetaObject **)(prototype->d.extradata);
+ } else
+#endif
+ {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra)
+ objects = extra->objects;
+ else
+ objects = 0;
+ }
+ if (objects) {
+ while (*objects != 0) {
+ addRelatedMetaObject(*objects);
+ ++objects;
+ }
+ }
+ }
+
+ if ((members & StaticMetacall) != 0) {
+ if (priv(prototype->d.data)->revision >= 2) {
+ const QMetaObjectExtraData *extra =
+ (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra && extra->static_metacall)
+ setStaticMetacallFunction(extra->static_metacall);
+ }
+ }
+}
+
+/*!
+ Returns the method at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
+{
+ if (index >= 0 && index < d->methods.size())
+ return QMetaMethodBuilder(this, index);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the constructor at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
+{
+ if (index >= 0 && index < d->constructors.size())
+ return QMetaMethodBuilder(this, -(index + 1));
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the property at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
+{
+ if (index >= 0 && index < d->properties.size())
+ return QMetaPropertyBuilder(this, index);
+ else
+ return QMetaPropertyBuilder();
+}
+
+/*!
+ Returns the enumerator at \a index in this class.
+
+ \sa enumeratorCount(), addEnumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
+{
+ if (index >= 0 && index < d->enumerators.size())
+ return QMetaEnumBuilder(this, index);
+ else
+ return QMetaEnumBuilder();
+}
+
+/*!
+ Returns the related meta object at \a index in this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+#ifdef Q_NO_DATA_RELOCATION
+ return &((*(d->relatedMetaObjects[index]))());
+#else
+ return d->relatedMetaObjects[index];
+#endif
+ else
+ return 0;
+}
+
+/*!
+ Returns the name of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoName(int index) const
+{
+ if (index >= 0 && index < d->classInfoNames.size())
+ return d->classInfoNames[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoValue(int index) const
+{
+ if (index >= 0 && index < d->classInfoValues.size())
+ return d->classInfoValues[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Removes the method at \a index from this class. The indices of
+ all following methods will be adjusted downwards by 1. If the
+ method is registered as a notify signal on a property, then the
+ notify signal will be removed from the property.
+
+ \sa methodCount(), addMethod(), method(), indexOfMethod()
+*/
+void QMetaObjectBuilder::removeMethod(int index)
+{
+ if (index >= 0 && index < d->methods.size()) {
+ d->methods.removeAt(index);
+ for (int prop = 0; prop < d->properties.size(); ++prop) {
+ // Adjust the indices of property notify signal references.
+ if (d->properties[prop].notifySignal == index) {
+ d->properties[prop].notifySignal = -1;
+ d->properties[prop].setFlag(Notify, false);
+ } else if (d->properties[prop].notifySignal > index)
+ (d->properties[prop].notifySignal)--;
+ }
+ }
+}
+
+/*!
+ Removes the constructor at \a index from this class. The indices of
+ all following constructors will be adjusted downwards by 1.
+
+ \sa constructorCount(), addConstructor(), constructor()
+ \sa indexOfConstructor()
+*/
+void QMetaObjectBuilder::removeConstructor(int index)
+{
+ if (index >= 0 && index < d->constructors.size())
+ d->constructors.removeAt(index);
+}
+
+/*!
+ Removes the property at \a index from this class. The indices of
+ all following properties will be adjusted downwards by 1.
+
+ \sa propertyCount(), addProperty(), property(), indexOfProperty()
+*/
+void QMetaObjectBuilder::removeProperty(int index)
+{
+ if (index >= 0 && index < d->properties.size())
+ d->properties.removeAt(index);
+}
+
+/*!
+ Removes the enumerator at \a index from this class. The indices of
+ all following enumerators will be adjusted downwards by 1.
+
+ \sa enumertorCount(), addEnumerator(), enumerator()
+ \sa indexOfEnumerator()
+*/
+void QMetaObjectBuilder::removeEnumerator(int index)
+{
+ if (index >= 0 && index < d->enumerators.size())
+ d->enumerators.removeAt(index);
+}
+
+/*!
+ Removes the item of class information at \a index from this class.
+ The indices of all following items will be adjusted downwards by 1.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), classInfoValue()
+ \sa indexOfClassInfo()
+*/
+void QMetaObjectBuilder::removeClassInfo(int index)
+{
+ if (index >= 0 && index < d->classInfoNames.size()) {
+ d->classInfoNames.removeAt(index);
+ d->classInfoValues.removeAt(index);
+ }
+}
+
+/*!
+ Removes the related meta object at \a index from this class.
+ The indices of all following related meta objects will be adjusted
+ downwards by 1.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa relatedMetaObject()
+*/
+void QMetaObjectBuilder::removeRelatedMetaObject(int index)
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ d->relatedMetaObjects.removeAt(index);
+}
+
+/*!
+ Finds a method with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa method(), methodCount(), addMethod(), removeMethod()
+*/
+int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a signal with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSlot()
+*/
+int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Signal)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a slot with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSignal()
+*/
+int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Slot)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a constructor with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa constructor(), constructorCount(), addConstructor(), removeConstructor()
+*/
+int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->constructors.size(); ++index) {
+ if (sig == d->constructors[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a property with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa property(), propertyCount(), addProperty(), removeProperty()
+*/
+int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
+{
+ for (int index = 0; index < d->properties.size(); ++index) {
+ if (name == d->properties[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an enumerator with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa enumertor(), enumeratorCount(), addEnumerator(), removeEnumerator()
+*/
+int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
+{
+ for (int index = 0; index < d->enumerators.size(); ++index) {
+ if (name == d->enumerators[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an item of class information with the specified \a name and
+ returns its index; otherwise returns -1.
+
+ \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
+ \sa removeClassInfo()
+*/
+int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
+{
+ for (int index = 0; index < d->classInfoNames.size(); ++index) {
+ if (name == d->classInfoNames[index])
+ return index;
+ }
+ return -1;
+}
+
+// Align on a specific type boundary.
+#define ALIGN(size,type) \
+ (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
+
+// Build a string into a QMetaObject representation. Returns the
+// position in the string table where the string was placed.
+static int buildString
+ (char *buf, char *str, int *offset, const QByteArray& value, int empty)
+{
+ if (value.size() == 0 && empty >= 0)
+ return empty;
+ if (buf) {
+ memcpy(str + *offset, value.constData(), value.size());
+ str[*offset + value.size()] = '\0';
+ }
+ int posn = *offset;
+ *offset += value.size() + 1;
+ return posn;
+}
+
+// Build the parameter array string for a method.
+static QByteArray buildParameterNames
+ (const QByteArray& signature, const QList<QByteArray>& parameterNames)
+{
+ // If the parameter name list is specified, then concatenate them.
+ if (!parameterNames.isEmpty()) {
+ QByteArray names;
+ bool first = true;
+ foreach (QByteArray name, parameterNames) {
+ if (first)
+ first = false;
+ else
+ names += (char)',';
+ names += name;
+ }
+ return names;
+ }
+
+ // Count commas in the signature, excluding those inside template arguments.
+ int index = signature.indexOf('(');
+ if (index < 0)
+ return QByteArray();
+ ++index;
+ if (index >= signature.size())
+ return QByteArray();
+ if (signature[index] == ')')
+ return QByteArray();
+ int count = 1;
+ int brackets = 0;
+ while (index < signature.size() && signature[index] != ',') {
+ char ch = signature[index++];
+ if (ch == '<')
+ ++brackets;
+ else if (ch == '>')
+ --brackets;
+ else if (ch == ',' && brackets <= 0)
+ ++count;
+ }
+ return QByteArray(count - 1, ',');
+}
+
+// Build a QMetaObject in "buf" based on the information in "d".
+// If "buf" is null, then return the number of bytes needed to
+// build the QMetaObject. Returns -1 if the metaobject if
+// relocatable is set, but the metaobject contains extradata.
+static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
+ bool relocatable)
+{
+ int size = 0;
+ int dataIndex;
+ int enumIndex;
+ int index;
+ bool hasNotifySignals = false;
+
+ if (relocatable &&
+ (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction))
+ return -1;
+
+ // Create the main QMetaObject structure at the start of the buffer.
+ QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
+ size += sizeof(QMetaObject);
+ ALIGN(size, int);
+ if (buf) {
+ if (!relocatable) meta->d.superdata = d->superClass;
+ meta->d.extradata = 0;
+ }
+
+ // Populate the QMetaObjectPrivate structure.
+ QMetaObjectPrivate *pmeta
+ = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
+ int pmetaSize = size;
+ dataIndex = 13; // Number of fields in the QMetaObjectPrivate.
+ for (index = 0; index < d->properties.size(); ++index) {
+ if (d->properties[index].notifySignal != -1) {
+ hasNotifySignals = true;
+ break;
+ }
+ }
+ if (buf) {
+ pmeta->revision = 3;
+ pmeta->flags = d->flags;
+ pmeta->className = 0; // Class name is always the first string.
+
+ pmeta->classInfoCount = d->classInfoNames.size();
+ pmeta->classInfoData = dataIndex;
+ dataIndex += 2 * d->classInfoNames.size();
+
+ pmeta->methodCount = d->methods.size();
+ pmeta->methodData = dataIndex;
+ dataIndex += 5 * d->methods.size();
+
+ pmeta->propertyCount = d->properties.size();
+ pmeta->propertyData = dataIndex;
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+
+ pmeta->enumeratorCount = d->enumerators.size();
+ pmeta->enumeratorData = dataIndex;
+ dataIndex += 4 * d->enumerators.size();
+
+ pmeta->constructorCount = d->constructors.size();
+ pmeta->constructorData = dataIndex;
+ dataIndex += 5 * d->constructors.size();
+ } else {
+ dataIndex += 2 * d->classInfoNames.size();
+ dataIndex += 5 * d->methods.size();
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+ dataIndex += 4 * d->enumerators.size();
+ dataIndex += 5 * d->constructors.size();
+ }
+
+ // Allocate space for the enumerator key names and values.
+ enumIndex = dataIndex;
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ dataIndex += 2 * enumerator->keys.size();
+ }
+
+ // Zero terminator at the end of the data offset table.
+ ++dataIndex;
+
+ // Find the start of the data and string tables.
+ int *data = reinterpret_cast<int *>(pmeta);
+ size += dataIndex * sizeof(int);
+ char *str = reinterpret_cast<char *>(buf + size);
+ if (buf) {
+ if (relocatable) {
+ meta->d.stringdata = reinterpret_cast<const char *>((intptr_t)size);
+ meta->d.data = reinterpret_cast<uint *>((intptr_t)pmetaSize);
+ } else {
+ meta->d.stringdata = str;
+ meta->d.data = reinterpret_cast<uint *>(data);
+ }
+ }
+
+ // Reset the current data position to just past the QMetaObjectPrivate.
+ dataIndex = 13;
+
+ // Add the class name to the string table.
+ int offset = 0;
+ buildString(buf, str, &offset, d->className, -1);
+
+ // Add a common empty string, which is used to indicate "void"
+ // method returns, empty tag strings, etc.
+ int empty = buildString(buf, str, &offset, QByteArray(), -1);
+
+ // Output the class infos,
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ int name = buildString(buf, str, &offset, d->classInfoNames[index], empty);
+ int value = buildString(buf, str, &offset, d->classInfoValues[index], empty);
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = value;
+ }
+ dataIndex += 2;
+ }
+
+ // Output the methods in the class.
+ for (index = 0; index < d->methods.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // Output the properties in the class.
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ int name = buildString(buf, str, &offset, prop->name, empty);
+ int type = buildString(buf, str, &offset, prop->type, empty);
+ int flags = prop->flags;
+
+ if (!isVariantType(prop->type)) {
+ flags |= EnumOrFlag;
+ } else {
+ flags |= qvariant_nameToType(prop->type) << 24;
+ }
+
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = type;
+ data[dataIndex + 2] = flags;
+ }
+ dataIndex += 3;
+ }
+ if (hasNotifySignals) {
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ if (buf) {
+ if (prop->notifySignal != -1)
+ data[dataIndex] = prop->notifySignal;
+ else
+ data[dataIndex] = 0;
+ }
+ ++dataIndex;
+ }
+ }
+
+ // Output the enumerators in the class.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ int name = buildString(buf, str, &offset, enumerator->name, empty);
+ int isFlag = (int)(enumerator->isFlag);
+ int count = enumerator->keys.size();
+ int enumOffset = enumIndex;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = isFlag;
+ data[dataIndex + 2] = count;
+ data[dataIndex + 3] = enumOffset;
+ }
+ for (int key = 0; key < count; ++key) {
+ int keyIndex = buildString(buf, str, &offset, enumerator->keys[key], empty);
+ if (buf) {
+ data[enumOffset++] = keyIndex;
+ data[enumOffset++] = enumerator->values[key];
+ }
+ }
+ dataIndex += 4;
+ enumIndex += 2 * count;
+ }
+
+ // Output the constructors in the class.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // One more empty string to act as a terminator.
+ buildString(buf, str, &offset, QByteArray(), -1);
+ size += offset;
+
+ // Output the zero terminator in the data array.
+ if (buf)
+ data[enumIndex] = 0;
+
+ // Create the extradata block if we need one.
+ if (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction) {
+ ALIGN(size, QMetaObject **);
+ ALIGN(size, QMetaObjectBuilder::StaticMetacallFunction);
+ QMetaObjectExtraData *extra =
+ reinterpret_cast<QMetaObjectExtraData *>(buf + size);
+ size += sizeof(QMetaObjectExtraData);
+ ALIGN(size, QMetaObject *);
+#ifdef Q_NO_DATA_RELOCATION
+ QMetaObjectAccessor *objects =
+ reinterpret_cast<QMetaObjectAccessor *>(buf + size);
+#else
+ const QMetaObject **objects =
+ reinterpret_cast<const QMetaObject **>(buf + size);
+#endif
+ if (buf) {
+ if (d->relatedMetaObjects.size() > 0) {
+ extra->objects = objects;
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index)
+ objects[index] = d->relatedMetaObjects[index];
+ objects[index] = 0;
+ } else {
+ extra->objects = 0;
+ }
+ extra->static_metacall = d->staticMetacallFunction;
+ meta->d.extradata = reinterpret_cast<void *>(extra);
+ }
+ if (d->relatedMetaObjects.size() > 0)
+ size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1);
+ }
+
+ // Align the final size and return it.
+ ALIGN(size, void *);
+ return size;
+}
+
+/*!
+ Converts this meta object builder into a concrete QMetaObject.
+ The return value should be deallocated using qFree() once it
+ is no longer needed.
+
+ The returned meta object is a snapshot of the state of the
+ QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
+ will not be reflected in previous meta objects returned by
+ this method.
+*/
+QMetaObject *QMetaObjectBuilder::toMetaObject() const
+{
+ int size = buildMetaObject(d, 0, false);
+ char *buf = reinterpret_cast<char *>(qMalloc(size));
+ buildMetaObject(d, buf, false);
+ return reinterpret_cast<QMetaObject *>(buf);
+}
+
+/*
+ \internal
+
+ Converts this meta object builder into relocatable data. This data can
+ be stored, copied and later passed to fromRelocatableData() to create a
+ concrete QMetaObject.
+
+ The data is specific to the architecture on which it was created, but is not
+ specific to the process that created it. Not all meta object builder's can
+ be converted to data in this way. If \a ok is provided, it will be set to
+ true if the conversion succeeds, and false otherwise. If a
+ staticMetacallFunction() or any relatedMetaObject()'s are specified the
+ conversion to relocatable data will fail.
+*/
+QByteArray QMetaObjectBuilder::toRelocatableData(bool *ok) const
+{
+ int size = buildMetaObject(d, 0, true);
+ if (size == -1) {
+ if (ok) *ok = false;
+ return QByteArray();
+ }
+
+ QByteArray data;
+ data.resize(size);
+ char *buf = data.data();
+ buildMetaObject(d, buf, true);
+ if (ok) *ok = true;
+ return data;
+}
+
+/*
+ \internal
+
+ Sets the \a data returned from toRelocatableData() onto a concrete
+ QMetaObject instance, \a output. As the meta object's super class is not
+ saved in the relocatable data, it must be passed as \a superClass.
+*/
+void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
+ const QMetaObject *superclass,
+ const QByteArray &data)
+{
+ if (!output)
+ return;
+
+ const char *buf = data.constData();
+ const QMetaObject *dataMo = reinterpret_cast<const QMetaObject *>(buf);
+
+ intptr_t stringdataOffset = (intptr_t)dataMo->d.stringdata;
+ intptr_t dataOffset = (intptr_t)dataMo->d.data;
+
+ output->d.superdata = superclass;
+ output->d.stringdata = buf + stringdataOffset;
+ output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
+}
+
+/*!
+ \typedef QMetaObjectBuilder::StaticMetacallFunction
+
+ Typedef for static metacall functions. The three parameters are
+ the call type value, the constructor index, and the
+ array of parameters.
+*/
+
+/*!
+ Returns the static metacall function to use to construct objects
+ of this class. The default value is null.
+
+ \sa setStaticMetacallFunction()
+*/
+QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
+{
+ return d->staticMetacallFunction;
+}
+
+/*!
+ Sets the static metacall function to use to construct objects
+ of this class to \a value. The default value is null.
+
+ \sa staticMetacallFunction()
+*/
+void QMetaObjectBuilder::setStaticMetacallFunction
+ (QMetaObjectBuilder::StaticMetacallFunction value)
+{
+ d->staticMetacallFunction = value;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ Serializes the contents of the meta object builder onto \a stream.
+
+ \sa deserialize()
+*/
+void QMetaObjectBuilder::serialize(QDataStream& stream) const
+{
+ int index;
+
+ // Write the class and super class names.
+ stream << d->className;
+ if (d->superClass)
+ stream << QByteArray(d->superClass->className());
+ else
+ stream << QByteArray();
+
+ // Write the counts for each type of class member.
+ stream << d->classInfoNames.size();
+ stream << d->methods.size();
+ stream << d->properties.size();
+ stream << d->enumerators.size();
+ stream << d->constructors.size();
+ stream << d->relatedMetaObjects.size();
+
+ // Write the items of class information.
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ stream << d->classInfoNames[index];
+ stream << d->classInfoValues[index];
+ }
+
+ // Write the methods.
+ for (index = 0; index < d->methods.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the properties.
+ for (index = 0; index < d->properties.size(); ++index) {
+ const QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream << property->name;
+ stream << property->type;
+ stream << property->flags;
+ stream << property->notifySignal;
+ }
+
+ // Write the enumerators.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ const QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream << enumerator->name;
+ stream << enumerator->isFlag;
+ stream << enumerator->keys;
+ stream << enumerator->values;
+ }
+
+ // Write the constructors.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the related meta objects.
+#ifdef Q_NO_DATA_RELOCATION
+ //### What do we do here?
+#else
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
+ const QMetaObject *meta = d->relatedMetaObjects[index];
+ stream << QByteArray(meta->className());
+ }
+#endif
+
+ // Add an extra empty QByteArray for additional data in future versions.
+ // This should help maintain backwards compatibility, allowing older
+ // versions to read newer data.
+ stream << QByteArray();
+}
+
+// Resolve a class name using the name reference map.
+static const QMetaObject *resolveClassName
+ (const QMap<QByteArray, const QMetaObject *>& references,
+ const QByteArray& name)
+{
+ if (name == QByteArray("QObject"))
+ return &QObject::staticMetaObject;
+ else
+ return references.value(name, 0);
+}
+
+/*!
+ Deserializes a meta object builder from \a stream into
+ this meta object builder.
+
+ The \a references parameter specifies a mapping from class names
+ to QMetaObject instances for resolving the super class name and
+ related meta objects in the object that is deserialized.
+ The meta object for QObject is implicitly added to \a references
+ and does not need to be supplied.
+
+ The QDataStream::status() value on \a stream will be set to
+ QDataStream::ReadCorruptData if the input data is corrupt.
+ The status will be set to QDataStream::ReadPastEnd if the
+ input was exhausted before the full meta object was read.
+
+ \sa serialize()
+*/
+void QMetaObjectBuilder::deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references)
+{
+ QByteArray name;
+ const QMetaObject *cl;
+ int index;
+
+ // Clear all members in the builder to their default states.
+ d->className.clear();
+ d->superClass = &QObject::staticMetaObject;
+ d->classInfoNames.clear();
+ d->classInfoValues.clear();
+ d->methods.clear();
+ d->properties.clear();
+ d->enumerators.clear();
+ d->constructors.clear();
+ d->relatedMetaObjects.clear();
+ d->staticMetacallFunction = 0;
+
+ // Read the class and super class names.
+ stream >> d->className;
+ stream >> name;
+ if (name.isEmpty()) {
+ d->superClass = 0;
+ } else if ((cl = resolveClassName(references, name)) != 0) {
+ d->superClass = cl;
+ } else {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the counts for each type of class member.
+ int classInfoCount, methodCount, propertyCount;
+ int enumeratorCount, constructorCount, relatedMetaObjectCount;
+ stream >> classInfoCount;
+ stream >> methodCount;
+ stream >> propertyCount;
+ stream >> enumeratorCount;
+ stream >> constructorCount;
+ stream >> relatedMetaObjectCount;
+ if (classInfoCount < 0 || methodCount < 0 ||
+ propertyCount < 0 || enumeratorCount < 0 ||
+ constructorCount < 0 || relatedMetaObjectCount < 0) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the items of class information.
+ for (index = 0; index < classInfoCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray value;
+ stream >> name;
+ stream >> value;
+ addClassInfo(name, value);
+ }
+
+ // Read the member methods.
+ for (index = 0; index < methodCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addMethod(name);
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() == QMetaMethod::Constructor) {
+ // Cannot add a constructor in this set of methods.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the properties.
+ for (index = 0; index < propertyCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray type;
+ stream >> name;
+ stream >> type;
+ addProperty(name, type);
+ QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream >> property->flags;
+ stream >> property->notifySignal;
+ if (property->notifySignal < -1 ||
+ property->notifySignal >= d->methods.size()) {
+ // Notify signal method index is out of range.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ if (property->notifySignal >= 0 &&
+ d->methods[property->notifySignal].methodType() != QMetaMethod::Signal) {
+ // Notify signal method index does not refer to a signal.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the enumerators.
+ for (index = 0; index < enumeratorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addEnumerator(name);
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream >> enumerator->isFlag;
+ stream >> enumerator->keys;
+ stream >> enumerator->values;
+ if (enumerator->keys.size() != enumerator->values.size()) {
+ // Mismatch between number of keys and number of values.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the constructor methods.
+ for (index = 0; index < constructorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addConstructor(name);
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() != QMetaMethod::Constructor) {
+ // The type must be Constructor.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the related meta objects.
+#ifdef Q_NO_DATA_RELOCATION
+ //### What do we do here
+#else
+ for (index = 0; index < relatedMetaObjectCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ cl = resolveClassName(references, name);
+ if (!cl) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ addRelatedMetaObject(cl);
+ }
+#endif
+
+ // Read the extra data block, which is reserved for future use.
+ stream >> name;
+}
+
+#endif // !QT_NO_DATASTREAM
+
+/*!
+ \class QMetaMethodBuilder
+ \internal
+ \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
+*/
+
+QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
+{
+ // Positive indices indicate methods, negative indices indicate constructors.
+ if (_mobj && _index >= 0 && _index < _mobj->d->methods.size())
+ return &(_mobj->d->methods[_index]);
+ else if (_mobj && -_index >= 1 && -_index <= _mobj->d->constructors.size())
+ return &(_mobj->d->constructors[(-_index) - 1]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaMethodBuilder::QMetaMethodBuilder()
+ \internal
+*/
+
+/*!
+ Returns the index of this method within its QMetaObjectBuilder.
+*/
+int QMetaMethodBuilder::index() const
+{
+ if (_index >= 0)
+ return _index; // Method, signal, or slot
+ else
+ return (-_index) - 1; // Constructor
+}
+
+/*!
+ Returns the type of this method (signal, slot, method, or constructor).
+*/
+QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->methodType();
+ else
+ return QMetaMethod::Method;
+}
+
+/*!
+ Returns the signature of this method.
+
+ \sa parameterNames(), returnType()
+*/
+QByteArray QMetaMethodBuilder::signature() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->signature;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the return type for this method; empty if the method's
+ return type is \c{void}.
+
+ \sa setReturnType(), signature()
+*/
+QByteArray QMetaMethodBuilder::returnType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->returnType;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the return type for this method to \a value. If \a value
+ is empty, then the method's return type is \c{void}. The \a value
+ will be normalized before it is added to the method.
+
+ \sa returnType(), signature()
+*/
+void QMetaMethodBuilder::setReturnType(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->returnType = QMetaObject::normalizedType(value);
+}
+
+/*!
+ Returns the list of parameter names for this method.
+
+ \sa setParameterNames()
+*/
+QList<QByteArray> QMetaMethodBuilder::parameterNames() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->parameterNames;
+ else
+ return QList<QByteArray>();
+}
+
+/*!
+ Sets the list of parameter names for this method to \a value.
+
+ \sa parameterNames()
+*/
+void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->parameterNames = value;
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ \sa setTag()
+*/
+QByteArray QMetaMethodBuilder::tag() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->tag;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the tag associated with this method to \a value.
+
+ \sa setTag()
+*/
+void QMetaMethodBuilder::setTag(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->tag = value;
+}
+
+/*!
+ Returns the access specification of this method (private, protected,
+ or public). The default value is QMetaMethod::Public for methods,
+ slots, and constructors. The default value is QMetaMethod::Protected
+ for signals.
+
+ \sa setAccess()
+*/
+QMetaMethod::Access QMetaMethodBuilder::access() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->access();
+ else
+ return QMetaMethod::Public;
+}
+
+/*!
+ Sets the access specification of this method (private, protected,
+ or public) to \a value. If the method is a signal, this function
+ will be ignored.
+
+ \sa access()
+*/
+void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d && d->methodType() != QMetaMethod::Signal)
+ d->setAccess(value);
+}
+
+/*!
+ Returns the additional attributes for this method.
+
+ \sa setAttributes()
+*/
+int QMetaMethodBuilder::attributes() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return (d->attributes >> 4);
+ else
+ return 0;
+}
+
+/*!
+ Sets the additional attributes for this method to \a value.
+
+ \sa attributes()
+*/
+void QMetaMethodBuilder::setAttributes(int value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->attributes = ((d->attributes & 0x0f) | (value << 4));
+}
+
+/*!
+ \class QMetaPropertyBuilder
+ \internal
+ \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
+*/
+
+QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->properties.size())
+ return &(_mobj->d->properties[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaPropertyBuilder::index() const
+
+ Returns the index of this property within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name associated with this property.
+
+ \sa type()
+*/
+QByteArray QMetaPropertyBuilder::name() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the type associated with this property.
+
+ \sa name()
+*/
+QByteArray QMetaPropertyBuilder::type() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->type;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this property has a notify signal; false otherwise.
+
+ \sa notifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+bool QMetaPropertyBuilder::hasNotifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Notify);
+ else
+ return false;
+}
+
+/*!
+ Returns the notify signal associated with this property.
+
+ \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d && d->notifySignal >= 0)
+ return QMetaMethodBuilder(_mobj, d->notifySignal);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Sets the notify signal associated with this property to \a value.
+
+ \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
+*/
+void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ if (value._mobj) {
+ d->notifySignal = value._index;
+ d->setFlag(Notify, true);
+ } else {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+ }
+}
+
+/*!
+ Removes the notify signal from this property.
+
+ \sa hasNotifySignal(), notifySignal(), setNotifySignal()
+*/
+void QMetaPropertyBuilder::removeNotifySignal()
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+ The default value is true.
+
+ \sa setReadable(), isWritable()
+*/
+bool QMetaPropertyBuilder::isReadable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Readable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns false.
+ The default value is true.
+
+ \sa setWritable(), isReadable()
+*/
+bool QMetaPropertyBuilder::isWritable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Writable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false. The default value is false.
+
+ \sa setResettable()
+*/
+bool QMetaPropertyBuilder::isResettable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Resettable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designable; otherwise returns false.
+ This default value is false.
+
+ \sa setDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isDesignable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Designable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is scriptable; otherwise returns false.
+ This default value is false.
+
+ \sa setScriptable(), isDesignable(), isStored()
+*/
+bool QMetaPropertyBuilder::isScriptable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Scriptable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is stored; otherwise returns false.
+ This default value is false.
+
+ \sa setStored(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isStored() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Stored);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is editable; otherwise returns false.
+ This default value is false.
+
+ \sa setEditable(), isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isEditable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Editable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit or that is
+ significant in some other way. Otherwise it returns
+ false. This default value is false.
+
+ \sa setUser(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isUser() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(User);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern. The default value is false.
+
+ \sa setStdCppSet()
+*/
+bool QMetaPropertyBuilder::hasStdCppSet() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(StdCppSet);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is an enumerator or flag type;
+ otherwise returns false. This default value is false.
+
+ \sa setEnumOrFlag()
+*/
+bool QMetaPropertyBuilder::isEnumOrFlag() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(EnumOrFlag);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has the dynamic flag set;
+ otherwise returns false. The default value is false.
+
+ \sa setDynamic()
+*/
+bool QMetaPropertyBuilder::isDynamic() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Dynamic);
+ else
+ return false;
+}
+
+/*!
+ Sets this property to readable if \a value is true.
+
+ \sa isReadable(), setWritable()
+*/
+void QMetaPropertyBuilder::setReadable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Readable, value);
+}
+
+/*!
+ Sets this property to writable if \a value is true.
+
+ \sa isWritable(), setReadable()
+*/
+void QMetaPropertyBuilder::setWritable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Writable, value);
+}
+
+/*!
+ Sets this property to resettable if \a value is true.
+
+ \sa isResettable()
+*/
+void QMetaPropertyBuilder::setResettable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Resettable, value);
+}
+
+/*!
+ Sets this property to designable if \a value is true.
+
+ \sa isDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setDesignable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Designable, value);
+}
+
+/*!
+ Sets this property to scriptable if \a value is true.
+
+ \sa isScriptable(), setDesignable(), setStored()
+*/
+void QMetaPropertyBuilder::setScriptable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Scriptable, value);
+}
+
+/*!
+ Sets this property to storable if \a value is true.
+
+ \sa isStored(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setStored(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Stored, value);
+}
+
+/*!
+ Sets this property to editable if \a value is true.
+
+ \sa isEditable(), setDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setEditable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Editable, value);
+}
+
+/*!
+ Sets the \c USER flag on this property to \a value.
+
+ \sa isUser(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setUser(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(User, value);
+}
+
+/*!
+ Sets the C++ setter flag on this property to \a value, which is
+ true if the property has a C++ setter function that follows Qt's
+ standard "name" / "setName" pattern.
+
+ \sa hasStdCppSet()
+*/
+void QMetaPropertyBuilder::setStdCppSet(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(StdCppSet, value);
+}
+
+/*!
+ Sets this property to be of an enumerator or flag type if
+ \a value is true.
+
+ \sa isEnumOrFlag()
+*/
+void QMetaPropertyBuilder::setEnumOrFlag(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(EnumOrFlag, value);
+}
+
+/*!
+ Sets this property to have the dynamic flag if \a value is
+ true.
+
+ \sa isDynamic()
+*/
+void QMetaPropertyBuilder::setDynamic(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Dynamic, value);
+}
+
+/*!
+ \class QMetaEnumBuilder
+ \internal
+ \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
+*/
+
+QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->enumerators.size())
+ return &(_mobj->d->enumerators[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaEnumBuilder::QMetaEnumBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaEnumBuilder::index() const
+
+ Returns the index of this enumerator within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+*/
+QByteArray QMetaEnumBuilder::name() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ \sa setIsFlag()
+*/
+bool QMetaEnumBuilder::isFlag() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->isFlag;
+ else
+ return false;
+}
+
+/*!
+ Sets this enumerator to be used as a flag if \a value is true.
+
+ \sa isFlag()
+*/
+void QMetaEnumBuilder::setIsFlag(bool value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->isFlag = value;
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key(), addKey()
+*/
+int QMetaEnumBuilder::keyCount() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->keys.size();
+ else
+ return 0;
+}
+
+/*!
+ Returns the key with the given \a index, or an empty QByteArray
+ if no such key exists.
+
+ \sa keyCount(), addKey(), value()
+*/
+QByteArray QMetaEnumBuilder::key(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->keys[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), addKey(), key()
+*/
+int QMetaEnumBuilder::value(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->values[index];
+ else
+ return -1;
+}
+
+/*!
+ Adds a new key called \a name to this enumerator, associated
+ with \a value. Returns the index of the new key.
+
+ \sa keyCount(), key(), value(), removeKey()
+*/
+int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d) {
+ int index = d->keys.size();
+ d->keys += name;
+ d->values += value;
+ return index;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Removes the key at \a index from this enumerator.
+
+ \sa addKey()
+*/
+void QMetaEnumBuilder::removeKey(int index)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size()) {
+ d->keys.removeAt(index);
+ d->values.removeAt(index);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmetaobjectbuilder_p.h b/src/declarative/qml/qmetaobjectbuilder_p.h
new file mode 100644
index 0000000..3eff4ff
--- /dev/null
+++ b/src/declarative/qml/qmetaobjectbuilder_p.h
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECTBUILDER_H
+#define QMETAOBJECTBUILDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of moc. This header file may change from version to version without notice,
+// or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmap.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMetaObjectBuilderPrivate;
+class QMetaMethodBuilder;
+class QMetaMethodBuilderPrivate;
+class QMetaPropertyBuilder;
+class QMetaPropertyBuilderPrivate;
+class QMetaEnumBuilder;
+class QMetaEnumBuilderPrivate;
+
+class Q_DECLARATIVE_EXPORT QMetaObjectBuilder
+{
+public:
+ enum AddMember
+ {
+ ClassName = 0x00000001,
+ SuperClass = 0x00000002,
+ Methods = 0x00000004,
+ Signals = 0x00000008,
+ Slots = 0x00000010,
+ Constructors = 0x00000020,
+ Properties = 0x00000040,
+ Enumerators = 0x00000080,
+ ClassInfos = 0x00000100,
+ RelatedMetaObjects = 0x00000200,
+ StaticMetacall = 0x00000400,
+ PublicMethods = 0x00000800,
+ ProtectedMethods = 0x00001000,
+ PrivateMethods = 0x00002000,
+ AllMembers = 0x7FFFFFFF,
+ AllPrimaryMembers = 0x7FFFFBFC
+ };
+ Q_DECLARE_FLAGS(AddMembers, AddMember)
+
+ enum MetaObjectFlag {
+ DynamicMetaObject = 0x01
+ };
+ Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
+
+ QMetaObjectBuilder();
+ explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+ virtual ~QMetaObjectBuilder();
+
+ QByteArray className() const;
+ void setClassName(const QByteArray& name);
+
+ const QMetaObject *superClass() const;
+ void setSuperClass(const QMetaObject *meta);
+
+ MetaObjectFlags flags() const;
+ void setFlags(MetaObjectFlags);
+
+ int methodCount() const;
+ int constructorCount() const;
+ int propertyCount() const;
+ int enumeratorCount() const;
+ int classInfoCount() const;
+ int relatedMetaObjectCount() const;
+
+ QMetaMethodBuilder addMethod(const QByteArray& signature);
+ QMetaMethodBuilder addMethod(const QByteArray& signature, const QByteArray& returnType);
+ QMetaMethodBuilder addMethod(const QMetaMethod& prototype);
+
+ QMetaMethodBuilder addSlot(const QByteArray& signature);
+ QMetaMethodBuilder addSignal(const QByteArray& signature);
+
+ QMetaMethodBuilder addConstructor(const QByteArray& signature);
+ QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
+
+ QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
+ QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
+
+ QMetaEnumBuilder addEnumerator(const QByteArray& name);
+ QMetaEnumBuilder addEnumerator(const QMetaEnum& prototype);
+
+ int addClassInfo(const QByteArray& name, const QByteArray& value);
+
+#ifdef Q_NO_DATA_RELOCATION
+ int addRelatedMetaObject(const QMetaObjectAccessor &meta);
+#else
+ int addRelatedMetaObject(const QMetaObject *meta);
+#endif
+
+ void addMetaObject(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+
+ QMetaMethodBuilder method(int index) const;
+ QMetaMethodBuilder constructor(int index) const;
+ QMetaPropertyBuilder property(int index) const;
+ QMetaEnumBuilder enumerator(int index) const;
+ const QMetaObject *relatedMetaObject(int index) const;
+
+ QByteArray classInfoName(int index) const;
+ QByteArray classInfoValue(int index) const;
+
+ void removeMethod(int index);
+ void removeConstructor(int index);
+ void removeProperty(int index);
+ void removeEnumerator(int index);
+ void removeClassInfo(int index);
+ void removeRelatedMetaObject(int index);
+
+ int indexOfMethod(const QByteArray& signature);
+ int indexOfSignal(const QByteArray& signature);
+ int indexOfSlot(const QByteArray& signature);
+ int indexOfConstructor(const QByteArray& signature);
+ int indexOfProperty(const QByteArray& name);
+ int indexOfEnumerator(const QByteArray& name);
+ int indexOfClassInfo(const QByteArray& name);
+
+ typedef int (*StaticMetacallFunction)(QMetaObject::Call, int, void **);
+
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const;
+ void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
+
+ QMetaObject *toMetaObject() const;
+ QByteArray toRelocatableData(bool * = 0) const;
+ static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &);
+
+#ifndef QT_NO_DATASTREAM
+ void serialize(QDataStream& stream) const;
+ void deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references);
+#endif
+
+private:
+ Q_DISABLE_COPY(QMetaObjectBuilder)
+
+ QMetaObjectBuilderPrivate *d;
+
+ friend class QMetaMethodBuilder;
+ friend class QMetaPropertyBuilder;
+ friend class QMetaEnumBuilder;
+};
+
+class Q_DECLARATIVE_EXPORT QMetaMethodBuilder
+{
+public:
+ QMetaMethodBuilder() : _mobj(0), _index(0) {}
+
+ int index() const;
+
+ QMetaMethod::MethodType methodType() const;
+ QByteArray signature() const;
+
+ QByteArray returnType() const;
+ void setReturnType(const QByteArray& value);
+
+ QList<QByteArray> parameterNames() const;
+ void setParameterNames(const QList<QByteArray>& value);
+
+ QByteArray tag() const;
+ void setTag(const QByteArray& value);
+
+ QMetaMethod::Access access() const;
+ void setAccess(QMetaMethod::Access value);
+
+ int attributes() const;
+ void setAttributes(int value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+ friend class QMetaPropertyBuilder;
+
+ QMetaMethodBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaMethodBuilderPrivate *d_func() const;
+};
+
+class Q_DECLARATIVE_EXPORT QMetaPropertyBuilder
+{
+public:
+ QMetaPropertyBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+ QByteArray type() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethodBuilder notifySignal() const;
+ void setNotifySignal(const QMetaMethodBuilder& value);
+ void removeNotifySignal();
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable() const;
+ bool isScriptable() const;
+ bool isStored() const;
+ bool isEditable() const;
+ bool isUser() const;
+ bool hasStdCppSet() const;
+ bool isEnumOrFlag() const;
+ bool isDynamic() const;
+
+ void setReadable(bool value);
+ void setWritable(bool value);
+ void setResettable(bool value);
+ void setDesignable(bool value);
+ void setScriptable(bool value);
+ void setStored(bool value);
+ void setEditable(bool value);
+ void setUser(bool value);
+ void setStdCppSet(bool value);
+ void setEnumOrFlag(bool value);
+ void setDynamic(bool value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaPropertyBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaPropertyBuilderPrivate *d_func() const;
+};
+
+class Q_DECLARATIVE_EXPORT QMetaEnumBuilder
+{
+public:
+ QMetaEnumBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+
+ bool isFlag() const;
+ void setIsFlag(bool value);
+
+ int keyCount() const;
+ QByteArray key(int index) const;
+ int value(int index) const;
+
+ int addKey(const QByteArray& name, int value);
+ void removeKey(int index);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaEnumBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaEnumBuilderPrivate *d_func() const;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::MetaObjectFlags)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h
new file mode 100644
index 0000000..c009093
--- /dev/null
+++ b/src/declarative/qml/qml.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QML_H
+#define QML_H
+
+#include "qmlmetatype.h"
+#include "qmlmetaproperty.h"
+#include "qmlparserstatus.h"
+#include "qmlpropertyvaluesource.h"
+#include "qmllist.h"
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Declarative)
+
+#define QML_DECLARE_TYPE(TYPE) \
+ Q_DECLARE_METATYPE(TYPE *) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *) \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *)
+
+#define QML_DECLARE_TYPE_HASMETATYPE(TYPE) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *) \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *)
+
+#define QML_DECLARE_INTERFACE(INTERFACE) \
+ QML_DECLARE_TYPE(INTERFACE)
+
+#define QML_DECLARE_INTERFACE_HASMETATYPE(INTERFACE) \
+ QML_DECLARE_TYPE_HASMETATYPE(INTERFACE)
+
+enum { /* TYPEINFO flags */
+ QML_HAS_ATTACHED_PROPERTIES = 0x01,
+};
+
+#define QML_DECLARE_TYPEINFO(TYPE, FLAGS) \
+template <> \
+class QmlTypeInfo<TYPE > \
+{ \
+public: \
+ enum { \
+ hasAttachedProperties = (((FLAGS) & QML_HAS_ATTACHED_PROPERTIES) == QML_HAS_ATTACHED_PROPERTIES) \
+ }; \
+};
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_SYMBIAN)
+#define QML_DEFINE_INTERFACE(INTERFACE) \
+ static int defineInterface##INTERFACE = qmlRegisterInterface<INTERFACE>(#INTERFACE);
+
+#define QML_DEFINE_EXTENDED_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE, EXTENSION) \
+ static int registerExtended##TYPE = qmlRegisterExtendedType<TYPE,EXTENSION>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE);
+
+#define QML_DEFINE_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE) \
+ static int defineType##TYPE = qmlRegisterType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE);
+
+#define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \
+ static int registerExtendedNoCreate##TYPE = qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE);
+
+#define QML_DEFINE_NOCREATE_TYPE(TYPE) \
+ static int registerNoCreate##TYPE = qmlRegisterType<TYPE>(#TYPE);
+
+#else
+
+#define QML_DEFINE_INTERFACE(INTERFACE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<INTERFACE *,0,0>::instance(qmlRegisterInterface<INTERFACE>(#INTERFACE));
+
+#define QML_DEFINE_EXTENDED_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,(VERSION_MAJ), (VERSION_MIN)>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE));
+
+#define QML_DEFINE_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,(VERSION_MAJ), (VERSION_MIN)>::instance(qmlRegisterType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE));
+
+#define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,0,0>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE));
+
+#define QML_DEFINE_NOCREATE_TYPE(TYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,0,0>::instance(qmlRegisterType<TYPE>(#TYPE));
+
+#endif
+
+class QmlContext;
+class QmlEngine;
+Q_DECLARATIVE_EXPORT void qmlExecuteDeferred(QObject *);
+Q_DECLARATIVE_EXPORT QmlContext *qmlContext(const QObject *);
+Q_DECLARATIVE_EXPORT QmlEngine *qmlEngine(const QObject *);
+Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true);
+
+template<typename T>
+QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
+{
+ // ### is this threadsafe?
+ static int idx = -1;
+
+ if (idx == -1)
+ idx = QmlMetaType::attachedPropertiesFuncId(&T::staticMetaObject);
+
+ if (idx == -1 || !obj)
+ return 0;
+
+ return qmlAttachedPropertiesObjectById(idx, obj, create);
+}
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QObject)
+Q_DECLARE_METATYPE(QVariant)
+
+QT_END_HEADER
+
+#endif // QML_H
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
new file mode 100644
index 0000000..cd2fbff
--- /dev/null
+++ b/src/declarative/qml/qml.pri
@@ -0,0 +1,123 @@
+INCLUDEPATH += $$PWD
+SOURCES += \
+ $$PWD/qmlparser.cpp \
+ $$PWD/qmlinstruction.cpp \
+ $$PWD/qmlvmemetaobject.cpp \
+ $$PWD/qmlengine.cpp \
+ $$PWD/qmlexpression.cpp \
+ $$PWD/qmlbinding.cpp \
+ $$PWD/qmlmetaproperty.cpp \
+ $$PWD/qmlmoduleplugin.cpp \
+ $$PWD/qmlcomponent.cpp \
+ $$PWD/qmlcontext.cpp \
+ $$PWD/qmlcustomparser.cpp \
+ $$PWD/qmlpropertyvaluesource.cpp \
+ $$PWD/qmlpropertyvalueinterceptor.cpp \
+ $$PWD/qmlproxymetaobject.cpp \
+ $$PWD/qmlvme.cpp \
+ $$PWD/qmlcompiler.cpp \
+ $$PWD/qmlcompileddata.cpp \
+ $$PWD/qmlboundsignal.cpp \
+ $$PWD/qmldom.cpp \
+ $$PWD/qmlrefcount.cpp \
+ $$PWD/qmlprivate.cpp \
+ $$PWD/qmlmetatype.cpp \
+ $$PWD/qmlstringconverters.cpp \
+ $$PWD/qmlclassfactory.cpp \
+ $$PWD/qmlparserstatus.cpp \
+ $$PWD/qmlcompositetypemanager.cpp \
+ $$PWD/qmlinfo.cpp \
+ $$PWD/qmlerror.cpp \
+ $$PWD/qmlscriptparser.cpp \
+ $$PWD/qmlenginedebug.cpp \
+ $$PWD/qmlrewrite.cpp \
+ $$PWD/qmlvaluetype.cpp \
+ $$PWD/qmlcompiledbindings.cpp \
+ $$PWD/qmlxmlhttprequest.cpp \
+ $$PWD/qmlsqldatabase.cpp \
+ $$PWD/qmetaobjectbuilder.cpp \
+ $$PWD/qmlwatcher.cpp \
+ $$PWD/qmlscript.cpp \
+ $$PWD/qmlcleanup.cpp \
+ $$PWD/qmlpropertycache.cpp \
+ $$PWD/qmlintegercache.cpp \
+ $$PWD/qmltypenamecache.cpp \
+ $$PWD/qmlscriptstring.cpp \
+ $$PWD/qmlobjectscriptclass.cpp \
+ $$PWD/qmlcontextscriptclass.cpp \
+ $$PWD/qmlglobalscriptclass.cpp \
+ $$PWD/qmlvaluetypescriptclass.cpp \
+ $$PWD/qmltypenamescriptclass.cpp \
+ $$PWD/qmllistscriptclass.cpp \
+ $$PWD/qmlworkerscript.cpp \
+ $$PWD/qmlnetworkaccessmanagerfactory.cpp
+HEADERS += \
+ $$PWD/qmlparser_p.h \
+ $$PWD/qmlglobal_p.h \
+ $$PWD/qmlinstruction_p.h \
+ $$PWD/qmlvmemetaobject_p.h \
+ $$PWD/qml.h \
+ $$PWD/qmlbinding.h \
+ $$PWD/qmlbinding_p.h \
+ $$PWD/qmlmetaproperty.h \
+ $$PWD/qmlmoduleplugin.h \
+ $$PWD/qmlcomponent.h \
+ $$PWD/qmlcomponent_p.h \
+ $$PWD/qmlcustomparser_p.h \
+ $$PWD/qmlcustomparser_p_p.h \
+ $$PWD/qmlpropertyvaluesource.h \
+ $$PWD/qmlpropertyvalueinterceptor.h \
+ $$PWD/qmlboundsignal_p.h \
+ $$PWD/qmlparserstatus.h \
+ $$PWD/qmlproxymetaobject_p.h \
+ $$PWD/qmlvme_p.h \
+ $$PWD/qmlcompiler_p.h \
+ $$PWD/qmlengine_p.h \
+ $$PWD/qmlexpression_p.h \
+ $$PWD/qmlprivate.h \
+ $$PWD/qmldom.h \
+ $$PWD/qmldom_p.h \
+ $$PWD/qmlrefcount_p.h \
+ $$PWD/qmlmetatype.h \
+ $$PWD/qmlengine.h \
+ $$PWD/qmlcontext.h \
+ $$PWD/qmlexpression.h \
+ $$PWD/qmlstringconverters_p.h \
+ $$PWD/qmlclassfactory_p.h \
+ $$PWD/qmlinfo.h \
+ $$PWD/qmlmetaproperty_p.h \
+ $$PWD/qmlcontext_p.h \
+ $$PWD/qmlcompositetypedata_p.h \
+ $$PWD/qmlcompositetypemanager_p.h \
+ $$PWD/qmllist.h \
+ $$PWD/qmldeclarativedata_p.h \
+ $$PWD/qmlerror.h \
+ $$PWD/qmlscriptparser_p.h \
+ $$PWD/qmlenginedebug_p.h \
+ $$PWD/qmlrewrite_p.h \
+ $$PWD/qpodvector_p.h \
+ $$PWD/qbitfield_p.h \
+ $$PWD/qmlvaluetype_p.h \
+ $$PWD/qmlcompiledbindings_p.h \
+ $$PWD/qmlxmlhttprequest_p.h \
+ $$PWD/qmlsqldatabase_p.h \
+ $$PWD/qmetaobjectbuilder_p.h \
+ $$PWD/qmlwatcher_p.h \
+ $$PWD/qmlcleanup_p.h \
+ $$PWD/qmlpropertycache_p.h \
+ $$PWD/qmlintegercache_p.h \
+ $$PWD/qmltypenamecache_p.h \
+ $$PWD/qmlscriptstring.h \
+ $$PWD/qmlobjectscriptclass_p.h \
+ $$PWD/qmlcontextscriptclass_p.h \
+ $$PWD/qmlglobalscriptclass_p.h \
+ $$PWD/qmlvaluetypescriptclass_p.h \
+ $$PWD/qmltypenamescriptclass_p.h \
+ $$PWD/qmllistscriptclass_p.h \
+ $$PWD/qmlworkerscript_p.h \
+ $$PWD/qmlscriptclass_p.h \
+ $$PWD/qmlguard_p.h \
+ $$PWD/qmlnetworkaccessmanagerfactory.h
+QT += sql
+include(parser/parser.pri)
+include(rewriter/rewriter.pri)
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
new file mode 100644
index 0000000..3e29a3c
--- /dev/null
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlbinding.h"
+#include "qmlbinding_p.h"
+
+#include "qml.h"
+#include "qmlcontext.h"
+#include "qmlinfo.h"
+#include "qmlcontext_p.h"
+#include "qmldeclarativedata_p.h"
+#include "qmlstringconverters_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QVariant>
+#include <QtCore/qdebug.h>
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_NOCREATE_TYPE(QmlBinding);
+
+QmlBindingData::QmlBindingData()
+: updating(false), enabled(false)
+{
+}
+
+QmlBindingData::~QmlBindingData()
+{
+ removeError();
+}
+
+void QmlBindingData::refresh()
+{
+ if (enabled && !updating && q) {
+ QmlBinding *b = static_cast<QmlBinding *>(QmlExpressionPrivate::get(q));
+ b->update();
+ }
+}
+
+QmlBindingPrivate::QmlBindingPrivate()
+: QmlExpressionPrivate(new QmlBindingData)
+{
+}
+
+QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, const QString &url, int lineNumber, QObject *parent)
+: QmlExpression(ctxt, data, rc, obj, url, lineNumber, *new QmlBindingPrivate)
+{
+ setParent(parent);
+}
+
+QmlBinding::QmlBinding(const QString &str, QObject *obj, QmlContext *ctxt, QObject *parent)
+: QmlExpression(ctxt, str, obj, *new QmlBindingPrivate)
+{
+ setParent(parent);
+}
+
+QmlBinding::~QmlBinding()
+{
+}
+
+void QmlBinding::setTarget(const QmlMetaProperty &prop)
+{
+ Q_D(QmlBinding);
+ d->bindingData()->property = prop;
+
+ update();
+}
+
+QmlMetaProperty QmlBinding::property() const
+{
+ Q_D(const QmlBinding);
+ return d->bindingData()->property;
+}
+
+void QmlBinding::update(QmlMetaProperty::WriteFlags flags)
+{
+ Q_D(QmlBinding);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::BindableValueUpdate> bu;
+#endif
+ QmlBindingData *data = d->bindingData();
+
+ if (!data->enabled)
+ return;
+
+ data->addref();
+
+ if (!data->updating) {
+ data->updating = true;
+
+ if (data->property.propertyCategory() == QmlMetaProperty::Bindable) {
+
+ int idx = data->property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+
+ QmlBinding *t = this;
+ int status = -1;
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(data->property.object(),
+ QMetaObject::WriteProperty,
+ idx, a);
+
+ } else {
+ bool isUndefined = false;
+ QVariant value = this->value(&isUndefined);
+
+ if (isUndefined && !data->error.isValid() && data->property.isResettable()) {
+
+ data->property.reset();
+
+ } else if (isUndefined && !data->error.isValid()) {
+
+ QUrl url = QUrl(data->url);
+ int line = data->line;
+ if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
+
+ data->error.setUrl(url);
+ data->error.setLine(line);
+ data->error.setColumn(-1);
+ data->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(data->property.propertyType())));
+
+ } else if (!isUndefined && data->property.object() &&
+ !data->property.write(value, flags)) {
+
+ QUrl url = QUrl(data->url);
+ int line = data->line;
+ if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
+
+ const char *valueType = 0;
+ if (value.userType() == QVariant::Invalid) valueType = "null";
+ else valueType = QMetaType::typeName(value.userType());
+
+ data->error.setUrl(url);
+ data->error.setLine(line);
+ data->error.setColumn(-1);
+ data->error.setDescription(QLatin1String("Unable to assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(QMetaType::typeName(data->property.propertyType())));
+ }
+
+ if (data->error.isValid()) {
+ QmlEnginePrivate *p = (data->context() && data->context()->engine())?
+ QmlEnginePrivate::get(data->context()->engine()):0;
+ if (!data->addError(p))
+ qWarning().nospace() << qPrintable(this->error().toString());
+ } else {
+ data->removeError();
+ }
+ }
+
+ data->updating = false;
+ } else {
+ qmlInfo(data->property.object()) << tr("Binding loop detected for property \"%1\"").arg(data->property.name());
+ }
+
+ data->release();
+}
+
+void QmlBinding::emitValueChanged()
+{
+ update();
+ // don't bother calling valueChanged()
+}
+
+void QmlBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
+{
+ Q_D(QmlBinding);
+ d->bindingData()->enabled = e;
+ setTrackChange(e);
+
+ QmlAbstractBinding::setEnabled(e, flags);
+
+ if (e) {
+ addToObject(d->bindingData()->property.object());
+ update(flags);
+ } else {
+ removeFromObject();
+ }
+}
+
+int QmlBinding::propertyIndex()
+{
+ Q_D(QmlBinding);
+ return d->bindingData()->property.coreIndex();
+}
+
+bool QmlBinding::enabled() const
+{
+ Q_D(const QmlBinding);
+
+ return d->bindingData()->enabled;
+}
+
+QString QmlBinding::expression() const
+{
+ return QmlExpression::expression();
+}
+
+QmlAbstractBinding::QmlAbstractBinding()
+: m_object(0), m_mePtr(0), m_prevBinding(0), m_nextBinding(0)
+{
+}
+
+QmlAbstractBinding::~QmlAbstractBinding()
+{
+ removeFromObject();
+ if (m_mePtr)
+ *m_mePtr = 0;
+}
+
+void QmlAbstractBinding::destroy()
+{
+ delete this;
+}
+
+void QmlAbstractBinding::addToObject(QObject *object)
+{
+ Q_ASSERT(object);
+
+ removeFromObject();
+
+ Q_ASSERT(!m_prevBinding);
+
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object, true);
+ m_nextBinding = data->bindings;
+ if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding;
+ m_prevBinding = &data->bindings;
+ data->bindings = this;
+ m_object = object;
+
+ data->setBindingBit(m_object, propertyIndex());
+}
+
+void QmlAbstractBinding::removeFromObject()
+{
+ if (m_prevBinding) {
+ Q_ASSERT(m_object);
+
+ *m_prevBinding = m_nextBinding;
+ if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding;
+ m_prevBinding = 0;
+ m_nextBinding = 0;
+
+ QmlDeclarativeData *data = QmlDeclarativeData::get(m_object, false);
+ if (data) data->clearBindingBit(propertyIndex());
+ m_object = 0;
+ }
+}
+
+QString QmlAbstractBinding::expression() const
+{
+ return QLatin1String("<Unknown>");
+}
+
+void QmlAbstractBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags)
+{
+ if (e) m_mePtr = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
new file mode 100644
index 0000000..cefb4fe
--- /dev/null
+++ b/src/declarative/qml/qmlbinding.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBINDING_H
+#define QMLBINDING_H
+
+#include "qml.h"
+#include "qmlpropertyvaluesource.h"
+#include "qmlexpression.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QMetaProperty>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlAbstractBinding
+{
+public:
+ QmlAbstractBinding();
+ virtual ~QmlAbstractBinding();
+
+ virtual void destroy();
+
+ virtual QString expression() const;
+
+ void setEnabled(bool e) { setEnabled(e, QmlMetaProperty::DontRemoveBinding); }
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags) = 0;
+ virtual int propertyIndex() = 0;
+
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
+ virtual void update(QmlMetaProperty::WriteFlags) = 0;
+
+ void addToObject(QObject *);
+ void removeFromObject();
+
+private:
+ friend class QmlDeclarativeData;
+ friend class QmlMetaProperty;
+ friend class QmlMetaPropertyPrivate;
+ friend class QmlVME;
+
+ QObject *m_object;
+ QmlAbstractBinding **m_mePtr;
+ QmlAbstractBinding **m_prevBinding;
+ QmlAbstractBinding *m_nextBinding;
+};
+
+class QmlContext;
+class QmlBindingPrivate;
+class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression,
+ public QmlAbstractBinding
+{
+Q_OBJECT
+public:
+ QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0);
+ QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, const QString &, int,
+ QObject *parent);
+ ~QmlBinding();
+
+ void setTarget(const QmlMetaProperty &);
+ QmlMetaProperty property() const;
+
+ bool enabled() const;
+
+ // Inherited from QmlAbstractBinding
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
+ virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
+ virtual QString expression() const;
+
+public Q_SLOTS:
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
+
+protected:
+ void emitValueChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QmlBinding)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlBinding);
+
+QT_END_HEADER
+
+#endif // QMLBINDING_H
diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h
new file mode 100644
index 0000000..c6c1935
--- /dev/null
+++ b/src/declarative/qml/qmlbinding_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBINDING_P_H
+#define QMLBINDING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlbinding.h"
+
+#include "qmlmetaproperty.h"
+#include "qmlexpression_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlBindingData : public QmlExpressionData
+{
+public:
+ QmlBindingData();
+ virtual ~QmlBindingData();
+
+ bool updating:1;
+ bool enabled:1;
+
+ QmlMetaProperty property;
+
+ virtual void refresh();
+};
+
+class QmlBindingPrivate : public QmlExpressionPrivate
+{
+ Q_DECLARE_PUBLIC(QmlBinding)
+public:
+ QmlBindingPrivate();
+
+ QmlBindingData *bindingData() { return static_cast<QmlBindingData *>(data); }
+ const QmlBindingData *bindingData() const { return static_cast<const QmlBindingData *>(data); }
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLBINDING_P_H
diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp
new file mode 100644
index 0000000..d42e7ba
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlboundsignal_p.h"
+
+#include "qmetaobjectbuilder_p.h"
+#include "qmlengine_p.h"
+#include "qmlexpression_p.h"
+#include "qmlcontext_p.h"
+#include "qmlmetatype.h"
+#include "qml.h"
+#include "qmlcontext.h"
+#include "qmlglobal_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlBoundSignalParameters : public QObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
+ ~QmlBoundSignalParameters();
+
+ void setValues(void **);
+ void clearValues();
+
+private:
+ friend class MetaObject;
+ int metaCall(QMetaObject::Call, int _id, void **);
+ struct MetaObject : public QAbstractDynamicMetaObject {
+ MetaObject(QmlBoundSignalParameters *b)
+ : parent(b) {}
+
+ int metaCall(QMetaObject::Call c, int id, void **a) {
+ return parent->metaCall(c, id, a);
+ }
+ QmlBoundSignalParameters *parent;
+ };
+
+ int *types;
+ void **values;
+ QMetaObject *myMetaObject;
+};
+
+static int evaluateIdx = -1;
+
+QmlAbstractBoundSignal::QmlAbstractBoundSignal(QObject *parent)
+: QObject(parent)
+{
+}
+
+QmlAbstractBoundSignal::~QmlAbstractBoundSignal()
+{
+}
+
+QmlBoundSignal::QmlBoundSignal(QObject *scope, const QMetaMethod &signal,
+ QObject *parent)
+: m_expression(0), m_signal(signal), m_paramsValid(false), m_params(0)
+{
+ // A cached evaluation of the QmlExpression::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
+
+ QmlGraphics_setParent_noEvent(this, parent);
+ QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
+}
+
+QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val,
+ QObject *scope, const QMetaMethod &signal,
+ QObject *parent)
+: m_expression(0), m_signal(signal), m_paramsValid(false), m_params(0)
+{
+ // A cached evaluation of the QmlExpression::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
+
+ QmlGraphics_setParent_noEvent(this, parent);
+ QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
+
+ m_expression = new QmlExpression(ctxt, val, scope);
+ m_expression->setTrackChange(false);
+}
+
+QmlBoundSignal::~QmlBoundSignal()
+{
+ delete m_expression;
+ m_expression = 0;
+}
+
+int QmlBoundSignal::index() const
+{
+ return m_signal.methodIndex();
+}
+
+/*!
+ Returns the signal expression.
+*/
+QmlExpression *QmlBoundSignal::expression() const
+{
+ return m_expression;
+}
+
+/*!
+ Sets the signal expression to \a e. Returns the current signal expression,
+ or null if there is no signal expression.
+
+ The QmlBoundSignal instance takes ownership of \a e. The caller is
+ assumes ownership of the returned QmlExpression.
+*/
+QmlExpression *QmlBoundSignal::setExpression(QmlExpression *e)
+{
+ QmlExpression *rv = m_expression;
+ m_expression = e;
+ if (m_expression) m_expression->setTrackChange(false);
+ return rv;
+}
+
+QmlBoundSignal *QmlBoundSignal::cast(QObject *o)
+{
+ QmlAbstractBoundSignal *s = qobject_cast<QmlAbstractBoundSignal*>(o);
+ return static_cast<QmlBoundSignal *>(s);
+}
+
+int QmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
+{
+ if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
+ if (!m_paramsValid) {
+ if (!m_signal.parameterTypes().isEmpty())
+ m_params = new QmlBoundSignalParameters(m_signal, this);
+ m_paramsValid = true;
+ }
+
+ if (m_params) m_params->setValues(a);
+ if (m_expression) {
+ QmlExpressionPrivate::get(m_expression)->value(m_params);
+ if (m_expression && m_expression->hasError())
+ qWarning().nospace() << qPrintable(m_expression->error().toString());
+ }
+ if (m_params) m_params->clearValues();
+ return -1;
+ } else {
+ return QObject::qt_metacall(c, id, a);
+ }
+}
+
+QmlBoundSignalParameters::QmlBoundSignalParameters(const QMetaMethod &method,
+ QObject *parent)
+: QObject(parent), types(0), values(0)
+{
+ MetaObject *mo = new MetaObject(this);
+
+ // ### Optimize!
+ // ### Ensure only supported types are allowed, otherwise it might crash
+ QMetaObjectBuilder mob;
+ mob.setSuperClass(&QmlBoundSignalParameters::staticMetaObject);
+ mob.setClassName("QmlBoundSignalParameters");
+
+ QList<QByteArray> paramTypes = method.parameterTypes();
+ QList<QByteArray> paramNames = method.parameterNames();
+ types = new int[paramTypes.count()];
+ for (int ii = 0; ii < paramTypes.count(); ++ii) {
+ const QByteArray &type = paramTypes.at(ii);
+ const QByteArray &name = paramNames.at(ii);
+
+ if (name.isEmpty() || type.isEmpty()) {
+ types[ii] = 0;
+ continue;
+ }
+
+ QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
+ if (QmlMetaType::isQObject(t)) {
+ types[ii] = QMetaType::QObjectStar;
+ QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
+ prop.setWritable(false);
+ } else {
+ types[ii] = t;
+ QMetaPropertyBuilder prop = mob.addProperty(name, type);
+ prop.setWritable(false);
+ }
+ }
+ myMetaObject = mob.toMetaObject();
+ *static_cast<QMetaObject *>(mo) = *myMetaObject;
+
+ d_ptr->metaObject = mo;
+}
+
+QmlBoundSignalParameters::~QmlBoundSignalParameters()
+{
+ delete [] types;
+ qFree(myMetaObject);
+}
+
+void QmlBoundSignalParameters::setValues(void **v)
+{
+ values = v;
+}
+
+void QmlBoundSignalParameters::clearValues()
+{
+ values = 0;
+}
+
+int QmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (!values)
+ return -1;
+
+ if (c == QMetaObject::ReadProperty && id >= 1) {
+ QmlMetaType::copy(types[id - 1], a[0], values[id]);
+ return -1;
+ } else {
+ return qt_metacall(c, id, a);
+ }
+}
+
+QT_END_NAMESPACE
+
+#include <qmlboundsignal.moc>
diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h
new file mode 100644
index 0000000..971fc89
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBOUNDSIGNAL_P_H
+#define QMLBOUNDSIGNAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlexpression.h"
+
+#include <QtCore/qmetaobject.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlAbstractBoundSignal : public QObject
+{
+ Q_OBJECT
+public:
+ QmlAbstractBoundSignal(QObject *parent = 0);
+ virtual ~QmlAbstractBoundSignal() = 0;
+};
+
+class QmlBoundSignalParameters;
+class QmlBoundSignal : public QmlAbstractBoundSignal
+{
+public:
+ QmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *parent);
+ QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *scope,
+ const QMetaMethod &signal, QObject *parent);
+ virtual ~QmlBoundSignal();
+
+ int index() const;
+
+ QmlExpression *expression() const;
+ QmlExpression *setExpression(QmlExpression *);
+
+ static QmlBoundSignal *cast(QObject *);
+
+protected:
+ virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
+
+private:
+ QmlExpression *m_expression;
+ QMetaMethod m_signal;
+ bool m_paramsValid;
+ QmlBoundSignalParameters *m_params;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLBOUNDSIGNAL_P_H
diff --git a/src/declarative/qml/qmlclassfactory.cpp b/src/declarative/qml/qmlclassfactory.cpp
new file mode 100644
index 0000000..3c19c2f
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlclassfactory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlClassFactory::~QmlClassFactory()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlclassfactory_p.h b/src/declarative/qml/qmlclassfactory_p.h
new file mode 100644
index 0000000..91f616e
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCLASSFACTORY_P_H
+#define QMLCLASSFACTORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QByteArray;
+class QUrl;
+class QmlComponent;
+
+class QmlClassFactory
+{
+public:
+ virtual ~QmlClassFactory();
+ virtual QmlComponent *create(const QByteArray &, const QUrl& baseUrl, QmlEngine*) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCLASSFACTORY_P_H
diff --git a/src/declarative/qml/qmlcleanup.cpp b/src/declarative/qml/qmlcleanup.cpp
new file mode 100644
index 0000000..599e4e7
--- /dev/null
+++ b/src/declarative/qml/qmlcleanup.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcleanup_p.h"
+
+#include "qmlengine_p.h"
+
+/*!
+\internal
+\class QmlCleanup
+\brief The QmlCleanup provides a callback when a QmlEngine is deleted.
+
+Any object that needs cleanup to occur before the QmlEngine's QScriptEngine is
+destroyed should inherit from QmlCleanup. The clear() virtual method will be
+called by QmlEngine just before it deletes the QScriptEngine.
+*/
+
+/*!
+\internal
+
+Create a QmlCleanup for \a engine
+*/
+QmlCleanup::QmlCleanup(QmlEngine *engine)
+: prev(0), next(0)
+{
+ if (!engine)
+ return;
+
+ QmlEnginePrivate *p = QmlEnginePrivate::get(engine);
+
+ if (p->cleanup) next = p->cleanup;
+ p->cleanup = this;
+ prev = &p->cleanup;
+ if (next) next->prev = &next;
+}
+
+/*!
+\internal
+*/
+QmlCleanup::~QmlCleanup()
+{
+ if (prev) *prev = next;
+ if (next) next->prev = prev;
+ prev = 0;
+ next = 0;
+}
+
diff --git a/src/declarative/qml/qmlcleanup_p.h b/src/declarative/qml/qmlcleanup_p.h
new file mode 100644
index 0000000..c140e43
--- /dev/null
+++ b/src/declarative/qml/qmlcleanup_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCLEANUP_P_H
+#define QMLCLEANUP_P_H
+
+#include <QtCore/qglobal.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlCleanup
+{
+public:
+ QmlCleanup(QmlEngine *);
+ virtual ~QmlCleanup();
+
+protected:
+ virtual void clear() = 0;
+
+private:
+ friend class QmlEnginePrivate;
+ QmlCleanup **prev;
+ QmlCleanup *next;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCLEANUP_P_H
+
diff --git a/src/declarative/qml/qmlcompiledbindings.cpp b/src/declarative/qml/qmlcompiledbindings.cpp
new file mode 100644
index 0000000..b5fbab9
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledbindings.cpp
@@ -0,0 +1,2720 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcompiledbindings_p.h"
+
+#include <QtDeclarative/qmlinfo.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmljsast_p.h>
+#include <private/qmljsengine_p.h>
+#include <private/qmlexpression_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qnumeric.h>
+#include <private/qmlgraphicsanchors_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+
+namespace {
+// Supported types: int, qreal, QString (needs constr/destr), QObject*, bool
+struct Register {
+ void setUndefined() { type = 0; }
+ void setUnknownButDefined() { type = -1; }
+ void setNaN() { setqreal(qSNaN()); }
+ bool isUndefined() const { return type == 0; }
+
+ void setQObject(QObject *o) { *((QObject **)data) = o; type = QMetaType::QObjectStar; }
+ QObject *getQObject() const { return *((QObject **)data); }
+
+ void setqreal(qreal v) { *((qreal *)data) = v; type = QMetaType::QReal; }
+ qreal getqreal() const { return *((qreal *)data); }
+
+ void setint(int v) { *((int *)data) = v; type = QMetaType::Int; }
+ int getint() const { return *((int *)data); }
+
+ void setbool(bool v) { *((bool *)data) = v; type = QMetaType::Bool; }
+ bool getbool() const { return *((bool *)data); }
+
+ QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
+ QString *getstringptr() { return (QString *)typeDataPtr(); }
+ QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
+ const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
+ const QString *getstringptr() const { return (QString *)typeDataPtr(); }
+ const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
+
+ void *typeDataPtr() { return (void *)&data; }
+ void *typeMemory() { return (void *)data; }
+ const void *typeDataPtr() const { return (void *)&data; }
+ const void *typeMemory() const { return (void *)data; }
+
+ int gettype() const { return type; }
+ void settype(int t) { type = t; }
+
+ int type; // Optional type
+ void *data[2]; // Object stored here
+};
+}
+
+class QmlCompiledBindingsPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlCompiledBindings)
+
+public:
+ QmlCompiledBindingsPrivate();
+ virtual ~QmlCompiledBindingsPrivate();
+
+ struct Binding : public QmlAbstractBinding, public QmlDelayedError {
+ Binding() : enabled(false), updating(0), property(0),
+ scope(0), target(0), parent(0) {}
+
+ // Inherited from QmlAbstractBinding
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
+ virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
+ virtual void destroy();
+
+ int index:30;
+ bool enabled:1;
+ bool updating:1;
+ int property;
+ QObject *scope;
+ QObject *target;
+
+ QmlCompiledBindingsPrivate *parent;
+ };
+
+ struct Subscription {
+ struct Signal {
+ QmlGuard<QObject> source;
+ int notifyIndex;
+ };
+
+ enum { InvalidType, SignalType, IdType } type;
+ inline Subscription();
+ inline ~Subscription();
+ bool isSignal() const { return type == SignalType; }
+ bool isId() const { return type == IdType; }
+ inline Signal *signal();
+ inline QmlContextPrivate::IdNotifier *id();
+ union {
+ char signalData[sizeof(Signal)];
+ char idData[sizeof(QmlContextPrivate::IdNotifier)];
+ };
+ };
+ Subscription *subscriptions;
+ QScriptDeclarativeClass::PersistentIdentifier *identifiers;
+
+ void run(Binding *);
+
+ const char *programData;
+ Binding *m_bindings;
+ quint32 *m_signalTable;
+
+ static int methodCount;
+
+ void init();
+ void run(int instr, QmlContextPrivate *context,
+ QmlDelayedError *error, QObject *scope, QObject *output);
+
+
+ inline void unsubscribe(int subIndex);
+ inline void subscribeId(QmlContextPrivate *p, int idIndex, int subIndex);
+ inline void subscribe(QObject *o, int notifyIndex, int subIndex);
+
+ QmlPropertyCache::Data *findproperty(QObject *obj,
+ const QScriptDeclarativeClass::Identifier &name,
+ QmlEnginePrivate *enginePriv,
+ QmlPropertyCache::Data &local);
+ bool findproperty(QObject *obj,
+ Register *output,
+ QmlEnginePrivate *enginePriv,
+ int subIdx,
+ const QScriptDeclarativeClass::Identifier &name,
+ bool isTerminal);
+ void findgeneric(Register *output, // value output
+ int subIdx, // Subscription index in config
+ QmlContextPrivate *context, // Context to search in
+ const QScriptDeclarativeClass::Identifier &name,
+ bool isTerminal);
+};
+
+QmlCompiledBindingsPrivate::QmlCompiledBindingsPrivate()
+: subscriptions(0), identifiers(0)
+{
+}
+
+QmlCompiledBindingsPrivate::~QmlCompiledBindingsPrivate()
+{
+ delete [] subscriptions; subscriptions = 0;
+ delete [] identifiers; identifiers = 0;
+}
+
+QmlCompiledBindingsPrivate::Subscription::Subscription()
+: type(InvalidType)
+{
+}
+
+QmlCompiledBindingsPrivate::Subscription::~Subscription()
+{
+ if (type == SignalType) ((Signal *)signalData)->~Signal();
+ else if (type == IdType) ((QmlContextPrivate::IdNotifier *)idData)->~IdNotifier();
+}
+
+
+int QmlCompiledBindingsPrivate::methodCount = -1;
+
+QmlCompiledBindings::QmlCompiledBindings(const char *program, QmlContext *context)
+: QObject(*(new QmlCompiledBindingsPrivate))
+{
+ Q_D(QmlCompiledBindings);
+
+ if (d->methodCount == -1)
+ d->methodCount = QmlCompiledBindings::staticMetaObject.methodCount();
+
+ d->programData = program;
+
+ d->init();
+
+ QmlAbstractExpression::setContext(context);
+}
+
+QmlCompiledBindings::~QmlCompiledBindings()
+{
+ Q_D(QmlCompiledBindings);
+
+ delete [] d->m_bindings;
+}
+
+QmlAbstractBinding *QmlCompiledBindings::configBinding(int index, QObject *target,
+ QObject *scope, int property)
+{
+ Q_D(QmlCompiledBindings);
+
+ QmlCompiledBindingsPrivate::Binding *rv = d->m_bindings + index;
+
+ rv->index = index;
+ rv->property = property;
+ rv->target = target;
+ rv->scope = scope;
+ rv->parent = d;
+
+ addref(); // This is decremented in Binding::destroy()
+
+ return rv;
+}
+
+void QmlCompiledBindingsPrivate::Binding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
+{
+ if (e) {
+ addToObject(target);
+ update(flags);
+ } else {
+ removeFromObject();
+ }
+
+ QmlAbstractBinding::setEnabled(e, flags);
+
+ if (enabled != e) {
+ enabled = e;
+
+ if (e) update(flags);
+ }
+}
+
+int QmlCompiledBindingsPrivate::Binding::propertyIndex()
+{
+ return property & 0xFFFF;
+}
+
+void QmlCompiledBindingsPrivate::Binding::update(QmlMetaProperty::WriteFlags)
+{
+ parent->run(this);
+}
+
+void QmlCompiledBindingsPrivate::Binding::destroy()
+{
+ enabled = false;
+ removeFromObject();
+ parent->q_func()->release();
+}
+
+int QmlCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **)
+{
+ Q_D(QmlCompiledBindings);
+
+ if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) {
+ id -= d->methodCount;
+
+ quint32 *reeval = d->m_signalTable + d->m_signalTable[id];
+ quint32 count = *reeval;
+ ++reeval;
+ for (quint32 ii = 0; ii < count; ++ii) {
+ d->run(d->m_bindings + reeval[ii]);
+ }
+ }
+ return -1;
+}
+
+void QmlCompiledBindingsPrivate::run(Binding *binding)
+{
+ Q_Q(QmlCompiledBindings);
+
+ if (!binding->enabled)
+ return;
+ if (binding->updating)
+ qWarning("ERROR: Circular binding");
+
+ QmlContext *context = q->QmlAbstractExpression::context();
+ if (!context) {
+ qWarning("QmlCompiledBindings: Attempted to evaluate an expression in an invalid context");
+ return;
+ }
+ QmlContextPrivate *cp = QmlContextPrivate::get(context);
+
+ if (binding->property & 0xFFFF0000) {
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(cp->engine);
+
+ QmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
+ Q_ASSERT(vt);
+ vt->read(binding->target, binding->property & 0xFFFF);
+
+ QObject *target = vt;
+ run(binding->index, cp, binding, binding->scope, target);
+
+ vt->write(binding->target, binding->property & 0xFFFF,
+ QmlMetaProperty::DontRemoveBinding);
+ } else {
+ run(binding->index, cp, binding, binding->scope, binding->target);
+ }
+}
+
+QmlCompiledBindingsPrivate::Subscription::Signal *QmlCompiledBindingsPrivate::Subscription::signal()
+{
+ if (type == IdType) ((QmlContextPrivate::IdNotifier *)idData)->~IdNotifier();
+ if (type != SignalType) new (signalData) Signal;
+ type = SignalType;
+ return (Signal *)signalData;
+}
+
+QmlContextPrivate::IdNotifier *QmlCompiledBindingsPrivate::Subscription::id()
+{
+ if (type == SignalType) ((Signal *)signalData)->~Signal();
+ if (type != IdType) new (idData) QmlContextPrivate::IdNotifier;
+ type = IdType;
+ return (QmlContextPrivate::IdNotifier *)idData;
+}
+
+namespace {
+// This structure is exactly 8-bytes in size
+struct Instr {
+ enum {
+ Noop,
+
+ Subscribe, // subscribe
+ SubscribeId, // subscribe
+
+ LoadId, // load
+ LoadScope, // load
+ LoadRoot, // load
+ LoadAttached, // attached
+
+ ConvertIntToReal, // unaryop
+ ConvertRealToInt, // unaryop
+
+ Real, // real_value
+ Int, // int_value
+ Bool, // bool_value
+ String, // string_value
+
+ AddReal, // binaryop
+ AddInt, // binaryop
+ AddString, // binaryop
+
+ MinusReal, // binaryop
+ MinusInt, // binaryop
+
+ CompareReal, // binaryop
+ CompareString, // binaryop
+
+ NotCompareReal, // binaryop
+ NotCompareString, // binaryop
+
+ GreaterThanReal, // binaryop
+ MaxReal, // binaryop
+ MinReal, // binaryop
+
+ NewString, // construct
+ NewUrl, // construct
+
+ CleanupUrl, // cleanup
+ CleanupString, // cleanup
+
+ Copy, // copy
+ Fetch, // fetch
+ Store, // store
+
+ Skip, // skip
+
+ Done,
+
+ // Speculative property resolution
+ InitString, // initstring
+ FindGeneric, // find
+ FindGenericTerminal, // find
+ FindProperty, // find
+ FindPropertyTerminal, // find
+ CleanupGeneric, // cleanup
+ ConvertGenericToReal, // unaryop
+ ConvertGenericToBool, // unaryop
+ ConvertGenericToString, // unaryop
+ ConvertGenericToUrl, // unaryop
+ };
+
+ union {
+ struct {
+ quint8 type;
+ quint8 packing[7];
+ } common;
+ struct {
+ quint8 type;
+ quint8 packing[3];
+ quint16 subscriptions;
+ quint16 identifiers;
+ } init;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint16 offset;
+ quint32 index;
+ } subscribe;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint8 packing[2];
+ quint32 index;
+ } load;
+ struct {
+ quint8 type;
+ qint8 output;
+ qint8 reg;
+ quint8 exceptionId;
+ quint32 index;
+ } attached;
+ struct {
+ quint8 type;
+ qint8 output;
+ qint8 reg;
+ quint8 exceptionId;
+ quint32 index;
+ } store;
+ struct {
+ quint8 type;
+ qint8 output;
+ qint8 objectReg;
+ quint8 exceptionId;
+ quint32 index;
+ } fetch;
+ struct {
+ quint8 type;
+ qint8 reg;
+ qint8 src;
+ quint8 packing[5];
+ } copy;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint8 packing[6];
+ } construct;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint8 packing[2];
+ float value;
+ } real_value;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint8 packing[2];
+ int value;
+ } int_value;
+ struct {
+ quint8 type;
+ qint8 reg;
+ bool value;
+ quint8 packing[5];
+ } bool_value;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint16 length;
+ quint32 offset;
+ } string_value;
+ struct {
+ quint8 type;
+ qint8 output;
+ qint8 src1;
+ qint8 src2;
+ quint8 packing[4];
+ } binaryop;
+ struct {
+ quint8 type;
+ qint8 output;
+ qint8 src;
+ quint8 packing[5];
+ } unaryop;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint8 packing[2];
+ quint32 count;
+ } skip;
+ struct {
+ quint8 type;
+ qint8 reg;
+ qint8 src;
+ quint8 exceptionId;
+ quint16 name;
+ quint16 subscribeIndex;
+ } find;
+ struct {
+ quint8 type;
+ qint8 reg;
+ quint8 packing[6];
+ } cleanup;
+ struct {
+ quint8 type;
+ quint8 packing[1];
+ quint16 offset;
+ quint32 dataIdx;
+ } initstring;
+ };
+};
+
+struct Program {
+ quint32 bindings;
+ quint32 dataLength;
+ quint32 signalTableOffset;
+ quint32 exceptionDataOffset;
+ quint16 subscriptions;
+ quint16 identifiers;
+ quint16 instructionCount;
+ quint16 dummy;
+
+ const char *data() const { return ((const char *)this) + sizeof(Program); }
+ const Instr *instructions() const { return (const Instr *)(data() + dataLength); }
+};
+}
+
+struct QmlBindingCompilerPrivate
+{
+ struct Result {
+ Result() : unknownType(false), metaObject(0), type(-1), reg(-1) {}
+ bool operator==(const Result &o) const {
+ return unknownType == o.unknownType &&
+ metaObject == o.metaObject &&
+ type == o.type &&
+ reg == o.reg;
+ }
+ bool operator!=(const Result &o) const {
+ return !(*this == o);
+ }
+ bool unknownType;
+ const QMetaObject *metaObject;
+ int type;
+ int reg;
+
+ QSet<QString> subscriptionSet;
+ };
+
+ QmlBindingCompilerPrivate() : registers(0) {}
+
+ void resetInstanceState();
+ int commitCompile();
+
+ QmlParser::Object *context;
+ QmlParser::Object *component;
+ QmlParser::Property *destination;
+ QHash<QString, QmlParser::Object *> ids;
+ QmlEnginePrivate::Imports imports;
+ QmlEnginePrivate *engine;
+
+ QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((intptr_t)context, 16); }
+
+ bool compile(QmlJS::AST::Node *);
+
+ bool parseExpression(QmlJS::AST::Node *, Result &);
+
+ bool tryName(QmlJS::AST::Node *);
+ bool parseName(QmlJS::AST::Node *, Result &);
+
+ bool tryArith(QmlJS::AST::Node *);
+ bool parseArith(QmlJS::AST::Node *, Result &);
+ bool numberArith(Result &, const Result &, const Result &, QSOperator::Op op);
+ bool stringArith(Result &, const Result &, const Result &, QSOperator::Op op);
+
+ bool tryLogic(QmlJS::AST::Node *);
+ bool parseLogic(QmlJS::AST::Node *, Result &);
+
+ bool tryConditional(QmlJS::AST::Node *);
+ bool parseConditional(QmlJS::AST::Node *, Result &);
+
+ bool tryConstant(QmlJS::AST::Node *);
+ bool parseConstant(QmlJS::AST::Node *, Result &);
+
+ bool tryMethod(QmlJS::AST::Node *);
+ bool parseMethod(QmlJS::AST::Node *, Result &);
+
+ bool buildName(QStringList &, QmlJS::AST::Node *, QList<QmlJS::AST::ExpressionNode *> *nodes = 0);
+ bool fetch(Result &type, const QMetaObject *, int reg, int idx, const QStringList &, QmlJS::AST::ExpressionNode *);
+
+ quint32 registers;
+ QHash<int, QPair<int, int> > registerCleanups;
+ int acquireReg(int cleanup = Instr::Noop, int cleanupType = 0);
+ void registerCleanup(int reg, int cleanup, int cleanupType = 0);
+ void releaseReg(int);
+
+ int registerLiteralString(const QString &);
+ int registerString(const QString &);
+ QHash<QString, QPair<int, int> > registeredStrings;
+ QByteArray data;
+
+ bool subscription(const QStringList &, Result *);
+ int subscriptionIndex(const QStringList &);
+ bool subscriptionNeutral(const QSet<QString> &base, const QSet<QString> &lhs, const QSet<QString> &rhs);
+
+ quint8 exceptionId(QmlJS::AST::ExpressionNode *);
+ QVector<quint64> exceptions;
+
+ QSet<int> usedSubscriptionIds;
+ QSet<QString> subscriptionSet;
+ QHash<QString, int> subscriptionIds;
+ QVector<Instr> bytecode;
+
+ // Committed binding data
+ struct {
+ QList<int> offsets;
+ QList<QSet<int> > dependencies;
+
+ QVector<Instr> bytecode;
+ QByteArray data;
+ QHash<QString, int> subscriptionIds;
+ QVector<quint64> exceptions;
+
+ QHash<QString, QPair<int, int> > registeredStrings;
+
+ int count() const { return offsets.count(); }
+ } committed;
+
+ QByteArray buildSignalTable() const;
+ QByteArray buildExceptionData() const;
+};
+
+void QmlCompiledBindingsPrivate::unsubscribe(int subIndex)
+{
+ Q_Q(QmlCompiledBindings);
+
+ QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
+ if (sub->isSignal()) {
+ QmlCompiledBindingsPrivate::Subscription::Signal *s = sub->signal();
+ if (s->source)
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+ QMetaObject::disconnectOne(s->source, s->notifyIndex,
+ q, methodCount + subIndex);
+#else
+ // QTBUG-6781
+ QMetaObject::disconnect(s->source, s->notifyIndex,
+ q, methodCount + subIndex);
+#endif
+ } else if (sub->isId()) {
+ sub->id()->clear();
+ }
+}
+
+void QmlCompiledBindingsPrivate::subscribeId(QmlContextPrivate *p, int idIndex, int subIndex)
+{
+ Q_Q(QmlCompiledBindings);
+
+ unsubscribe(subIndex);
+
+ if (p->idValues[idIndex]) {
+ QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
+ QmlContextPrivate::IdNotifier *i = sub->id();
+
+ i->next = p->idValues[idIndex].bindings;
+ i->prev = &p->idValues[idIndex].bindings;
+ p->idValues[idIndex].bindings = i;
+ if (i->next) i->next->prev = &i->next;
+
+ i->target = q;
+ i->methodIndex = methodCount + subIndex;
+ }
+}
+
+void QmlCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex)
+{
+ Q_Q(QmlCompiledBindings);
+
+ QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
+
+ if (sub->isId())
+ unsubscribe(subIndex);
+
+ QmlCompiledBindingsPrivate::Subscription::Signal *s = sub->signal();
+ if (o != s->source || notifyIndex != s->notifyIndex) {
+ if (s->source)
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+ QMetaObject::disconnectOne(s->source, s->notifyIndex,
+ q, methodCount + subIndex);
+#else
+ // QTBUG-6781
+ QMetaObject::disconnect(s->source, s->notifyIndex,
+ q, methodCount + subIndex);
+#endif
+ s->source = o;
+ s->notifyIndex = notifyIndex;
+ if (s->source && s->notifyIndex != -1)
+ QMetaObject::connect(s->source, s->notifyIndex, q,
+ methodCount + subIndex, Qt::DirectConnection);
+ }
+}
+
+// Conversion functions - these MUST match the QtScript expression path
+inline static qreal toReal(Register *reg, int type, bool *ok = 0)
+{
+ if (ok) *ok = true;
+
+ if (type == QMetaType::QReal) {
+ return reg->getqreal();
+ } else if (type == qMetaTypeId<QVariant>()) {
+ return reg->getvariantptr()->toReal();
+ } else {
+ if (ok) *ok = false;
+ return 0;
+ }
+}
+
+inline static QString toString(Register *reg, int type, bool *ok = 0)
+{
+ if (ok) *ok = true;
+
+ if (type == QMetaType::QReal) {
+ return QString::number(reg->getqreal());
+ } else if (type == QMetaType::Int) {
+ return QString::number(reg->getint());
+ } else if (type == qMetaTypeId<QVariant>()) {
+ return reg->getvariantptr()->toString();
+ } else if (type == QMetaType::QString) {
+ return *reg->getstringptr();
+ } else {
+ if (ok) *ok = false;
+ return QString();
+ }
+}
+
+inline static bool toBool(Register *reg, int type, bool *ok = 0)
+{
+ if (ok) *ok = true;
+
+ if (type == QMetaType::Bool) {
+ return reg->getbool();
+ } else if (type == qMetaTypeId<QVariant>()) {
+ return reg->getvariantptr()->toBool();
+ } else {
+ if (ok) *ok = false;
+ return false;
+ }
+}
+
+inline static QUrl toUrl(Register *reg, int type, QmlContextPrivate *context, bool *ok = 0)
+{
+ if (ok) *ok = true;
+
+ QUrl base;
+ if (type == qMetaTypeId<QVariant>()) {
+ QVariant *var = reg->getvariantptr();
+ int vt = var->type();
+ if (vt == QVariant::Url) {
+ base = var->toUrl();
+ } else if (vt == QVariant::ByteArray) {
+ base = QUrl(QString::fromUtf8(var->toByteArray()));
+ } else if (vt == QVariant::String) {
+ base = QUrl(var->toString());
+ } else {
+ if (ok) *ok = false;
+ return QUrl();
+ }
+ } else if (type == QMetaType::QString) {
+ base = QUrl(*reg->getstringptr());
+ } else {
+ if (ok) *ok = false;
+ return QUrl();
+ }
+
+ if (!base.isEmpty() && base.isRelative())
+ return context->url.resolved(base);
+ else
+ return base;
+}
+
+static QObject *variantToQObject(const QVariant &value, bool *ok)
+{
+ if (ok) *ok = true;
+
+ if (value.userType() == QMetaType::QObjectStar) {
+ return qvariant_cast<QObject*>(value);
+ } else {
+ if (ok) *ok = false;
+ return 0;
+ }
+}
+
+bool QmlCompiledBindingsPrivate::findproperty(QObject *obj, Register *output,
+ QmlEnginePrivate *enginePriv,
+ int subIdx, const QScriptDeclarativeClass::Identifier &name,
+ bool isTerminal)
+{
+ if (!obj) {
+ output->setUndefined();
+ return false;
+ }
+
+ QmlPropertyCache::Data local;
+ QmlPropertyCache::Data *property =
+ QmlPropertyCache::property(QmlEnginePrivate::get(enginePriv), obj, name, local);
+
+ if (property) {
+ if (subIdx != -1)
+ subscribe(obj, property->notifyIndex, subIdx);
+
+ if (property->flags & QmlPropertyCache::Data::IsQObjectDerived) {
+ void *args[] = { output->typeDataPtr(), 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
+ output->settype(QMetaType::QObjectStar);
+ } else if (property->propType == qMetaTypeId<QVariant>()) {
+ QVariant v;
+ void *args[] = { &v, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
+
+ if (isTerminal) {
+ new (output->typeDataPtr()) QVariant(v);
+ output->settype(qMetaTypeId<QVariant>());
+ } else {
+ bool ok;
+ output->setQObject(variantToQObject(v, &ok));
+ if (!ok)
+ output->setUndefined();
+ else
+ output->settype(QMetaType::QObjectStar);
+ }
+
+ } else {
+ if (!isTerminal) {
+ output->setUndefined();
+ } else if (property->propType == QMetaType::QReal) {
+ void *args[] = { output->typeDataPtr(), 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
+ output->settype(QMetaType::QReal);
+ } else if (property->propType == QMetaType::Int) {
+ void *args[] = { output->typeDataPtr(), 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
+ output->settype(QMetaType::Int);
+ } else if (property->propType == QMetaType::Bool) {
+ void *args[] = { output->typeDataPtr(), 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
+ output->settype(QMetaType::Bool);
+ } else if (property->propType == QMetaType::QString) {
+ new (output->typeDataPtr()) QString();
+ void *args[] = { output->typeDataPtr(), 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
+ output->settype(QMetaType::QString);
+ } else {
+ new (output->typeDataPtr())
+ QVariant(obj->metaObject()->property(property->coreIndex).read(obj));
+ output->settype(qMetaTypeId<QVariant>());
+ }
+ }
+
+ return true;
+ } else {
+ output->setUndefined();
+ return false;
+ }
+}
+
+void QmlCompiledBindingsPrivate::findgeneric(Register *output,
+ int subIdx,
+ QmlContextPrivate *context,
+ const QScriptDeclarativeClass::Identifier &name,
+ bool isTerminal)
+{
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(context->engine);
+
+ while (context) {
+
+ int contextPropertyIndex = context->propertyNames?context->propertyNames->value(name):-1;
+
+
+ if (contextPropertyIndex != -1) {
+
+ if (subIdx != -1)
+ subscribe(QmlContextPrivate::get(context), contextPropertyIndex + context->notifyIndex, subIdx);
+
+ if (contextPropertyIndex < context->idValueCount) {
+ output->setQObject(context->idValues[contextPropertyIndex]);
+ output->settype(QMetaType::QObjectStar);
+ } else {
+ const QVariant &value = context->propertyValues.at(contextPropertyIndex);
+ if (isTerminal) {
+ new (output->typeDataPtr()) QVariant(value);
+ output->settype(qMetaTypeId<QVariant>());
+ } else {
+ bool ok;
+ output->setQObject(variantToQObject(value, &ok));
+ if (!ok) { output->setUndefined(); }
+ else { output->settype(QMetaType::QObjectStar); }
+ return;
+ }
+ }
+
+ return;
+ }
+
+ for (int ii = 0; ii < context->scripts.count(); ++ii) {
+ QScriptValue function = QScriptDeclarativeClass::function(context->scripts.at(ii), name);
+ if (function.isValid()) {
+ qFatal("Binding optimizer resolved name to QScript method");
+ }
+ }
+
+ if (QObject *root = context->defaultObjects.isEmpty()?0:context->defaultObjects.first()) {
+
+ if (findproperty(root, output, enginePriv, subIdx, name, isTerminal))
+ return;
+
+ }
+
+ if (context->parent) {
+ context = QmlContextPrivate::get(context->parent);
+ } else {
+ context = 0;
+ }
+ }
+
+ output->setUndefined();
+}
+
+void QmlCompiledBindingsPrivate::init()
+{
+ Program *program = (Program *)programData;
+ if (program->subscriptions)
+ subscriptions = new QmlCompiledBindingsPrivate::Subscription[program->subscriptions];
+ if (program->identifiers)
+ identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers];
+
+ m_signalTable = (quint32 *)(program->data() + program->signalTableOffset);
+ m_bindings = new QmlCompiledBindingsPrivate::Binding[program->bindings];
+}
+
+static void throwException(int id, QmlDelayedError *error,
+ Program *program, QmlContextPrivate *context,
+ const QString &description = QString())
+{
+ error->error.setUrl(context->url);
+ if (description.isEmpty())
+ error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object"));
+ else
+ error->error.setDescription(description);
+ if (id != 0xFF) {
+ quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id);
+ error->error.setLine((e >> 32) & 0xFFFFFFFF);
+ error->error.setColumn(e & 0xFFFFFFFF);
+ } else {
+ error->error.setLine(-1);
+ error->error.setColumn(-1);
+ }
+ if (!context->engine || !error->addError(QmlEnginePrivate::get(context->engine)))
+ qWarning() << error->error;
+}
+
+void QmlCompiledBindingsPrivate::run(int instrIndex,
+ QmlContextPrivate *context, QmlDelayedError *error,
+ QObject *scope, QObject *output)
+{
+ error->removeError();
+
+ Register registers[32];
+ int storeFlags = 0;
+
+ QmlEnginePrivate *engine = QmlEnginePrivate::get(context->engine);
+ Program *program = (Program *)programData;
+ const Instr *instr = program->instructions();
+ instr += instrIndex;
+ const char *data = program->data();
+
+ while (instr) {
+
+ switch (instr->common.type) {
+ case Instr::Noop:
+ break;
+
+ case Instr::SubscribeId:
+ subscribeId(context, instr->subscribe.index, instr->subscribe.offset);
+ break;
+
+ case Instr::Subscribe:
+ {
+ QObject *o = 0;
+ const Register &object = registers[instr->subscribe.reg];
+ if (!object.isUndefined()) o = object.getQObject();
+ subscribe(o, instr->subscribe.index, instr->subscribe.offset);
+ }
+ break;
+
+ case Instr::LoadId:
+ registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
+ break;
+
+ case Instr::LoadScope:
+ registers[instr->load.reg].setQObject(scope);
+ break;
+
+ case Instr::LoadRoot:
+ registers[instr->load.reg].setQObject(context->defaultObjects.at(0));
+ break;
+
+ case Instr::LoadAttached:
+ {
+ const Register &input = registers[instr->attached.reg];
+ Register &output = registers[instr->attached.output];
+ if (input.isUndefined()) {
+ throwException(instr->attached.exceptionId, error, program, context);
+ return;
+ }
+
+ QObject *object = registers[instr->attached.reg].getQObject();
+ if (!object) {
+ output.setUndefined();
+ } else {
+ QObject *attached =
+ qmlAttachedPropertiesObjectById(instr->attached.index,
+ registers[instr->attached.reg].getQObject(),
+ true);
+ Q_ASSERT(attached);
+ output.setQObject(attached);
+ }
+ }
+ break;
+
+ case Instr::ConvertIntToReal:
+ {
+ const Register &input = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ if (input.isUndefined()) output.setUndefined();
+ else output.setqreal(qreal(input.getint()));
+ }
+ break;
+
+ case Instr::ConvertRealToInt:
+ {
+ const Register &input = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ if (input.isUndefined()) output.setUndefined();
+ else output.setint(int(input.getqreal()));
+ }
+ break;
+
+ case Instr::Real:
+ registers[instr->real_value.reg].setqreal(instr->real_value.value);
+ break;
+
+ case Instr::Int:
+ registers[instr->int_value.reg].setint(instr->int_value.value);
+ break;
+
+ case Instr::Bool:
+ registers[instr->bool_value.reg].setbool(instr->bool_value.value);
+ break;
+
+ case Instr::String:
+ {
+ Register &output = registers[instr->string_value.reg];
+ new (output.getstringptr())
+ QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
+ output.settype(QMetaType::QString);
+ }
+ break;
+
+ case Instr::AddReal:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
+ else output.setqreal(lhs.getqreal() + rhs.getqreal());
+ }
+ break;
+
+ case Instr::AddInt:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
+ else output.setint(lhs.getint() + rhs.getint());
+ }
+ break;
+
+ case Instr::AddString:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() && rhs.isUndefined()) { output.setNaN(); }
+ else {
+ if (lhs.isUndefined())
+ new (output.getstringptr())
+ QString(QLatin1String("undefined") + *registers[instr->binaryop.src2].getstringptr());
+ else if (rhs.isUndefined())
+ new (output.getstringptr())
+ QString(*registers[instr->binaryop.src1].getstringptr() + QLatin1String("undefined"));
+ else
+ new (output.getstringptr())
+ QString(*registers[instr->binaryop.src1].getstringptr() +
+ *registers[instr->binaryop.src2].getstringptr());
+ output.settype(QMetaType::QString);
+ }
+ }
+ break;
+
+ case Instr::MinusReal:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
+ else output.setqreal(lhs.getqreal() - rhs.getqreal());
+ }
+ break;
+
+ case Instr::MinusInt:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
+ else output.setint(lhs.getint() - rhs.getint());
+ }
+ break;
+
+ case Instr::CompareReal:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined());
+ else output.setbool(lhs.getqreal() == rhs.getqreal());
+ }
+ break;
+
+ case Instr::CompareString:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined());
+ else output.setbool(*lhs.getstringptr() == *rhs.getstringptr());
+ }
+ break;
+
+ case Instr::NotCompareReal:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined());
+ else output.setbool(lhs.getqreal() != rhs.getqreal());
+ }
+ break;
+
+ case Instr::NotCompareString:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined());
+ else output.setbool(*lhs.getstringptr() != *rhs.getstringptr());
+ }
+ break;
+
+ case Instr::GreaterThanReal:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(false);
+ else output.setbool(lhs.getqreal() > rhs.getqreal());
+ }
+ break;
+
+ case Instr::MaxReal:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
+ else output.setqreal(qMax(lhs.getqreal(), rhs.getqreal()));
+ }
+ break;
+
+ case Instr::MinReal:
+ {
+ const Register &lhs = registers[instr->binaryop.src1];
+ const Register &rhs = registers[instr->binaryop.src2];
+ Register &output = registers[instr->binaryop.output];
+ if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
+ else output.setqreal(qMin(lhs.getqreal(), rhs.getqreal()));
+ }
+ break;
+
+ case Instr::NewString:
+ {
+ Register &output = registers[instr->construct.reg];
+ new (output.getstringptr()) QString;
+ output.settype(QMetaType::QString);
+ }
+ break;
+
+ case Instr::NewUrl:
+ {
+ Register &output = registers[instr->construct.reg];
+ new (output.geturlptr()) QUrl;
+ output.settype(QMetaType::QUrl);
+ }
+ break;
+
+ case Instr::CleanupString:
+ registers[instr->cleanup.reg].getstringptr()->~QString();
+ break;
+
+ case Instr::CleanupUrl:
+ registers[instr->cleanup.reg].geturlptr()->~QUrl();
+ break;
+
+ case Instr::Fetch:
+ {
+ const Register &input = registers[instr->fetch.objectReg];
+ Register &output = registers[instr->fetch.output];
+
+ if (input.isUndefined()) {
+ throwException(instr->fetch.exceptionId, error, program, context);
+ return;
+ }
+
+ QObject *object = input.getQObject();
+ if (!object) {
+ output.setUndefined();
+ } else {
+ void *argv[] = { output.typeDataPtr(), 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
+ }
+ }
+ break;
+
+ case Instr::Store:
+ {
+ Register &data = registers[instr->store.reg];
+ if (data.isUndefined()) {
+ throwException(instr->store.exceptionId, error, program, context,
+ QLatin1String("Unable to assign undefined value"));
+ return;
+ }
+
+ int status = -1;
+ void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
+ QMetaObject::metacall(output, QMetaObject::WriteProperty,
+ instr->store.index, argv);
+ }
+ break;
+
+ case Instr::Copy:
+ registers[instr->copy.reg] = registers[instr->copy.src];
+ break;
+
+ case Instr::Skip:
+ if (instr->skip.reg == -1 || !registers[instr->skip.reg].getbool())
+ instr += instr->skip.count;
+ break;
+
+ case Instr::Done:
+ return;
+
+ case Instr::InitString:
+ if (!identifiers[instr->initstring.offset].identifier) {
+ quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
+ QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
+
+ QString str = QString::fromRawData(strdata, len);
+
+ identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
+ }
+ break;
+
+ case Instr::FindGenericTerminal:
+ case Instr::FindGeneric:
+ // We start the search in the parent context, as we know that the
+ // name is not present in the current context or it would have been
+ // found during the static compile
+ findgeneric(registers + instr->find.reg, instr->find.subscribeIndex,
+ QmlContextPrivate::get(context->parent),
+ identifiers[instr->find.name].identifier,
+ instr->common.type == Instr::FindGenericTerminal);
+ break;
+
+ case Instr::FindPropertyTerminal:
+ case Instr::FindProperty:
+ {
+ const Register &object = registers[instr->find.src];
+ if (object.isUndefined()) {
+ throwException(instr->find.exceptionId, error, program, context);
+ return;
+ }
+
+ findproperty(object.getQObject(), registers + instr->find.reg,
+ QmlEnginePrivate::get(context->engine),
+ instr->find.subscribeIndex, identifiers[instr->find.name].identifier,
+ instr->common.type == Instr::FindPropertyTerminal);
+ }
+ break;
+
+ case Instr::CleanupGeneric:
+ {
+ int type = registers[instr->cleanup.reg].gettype();
+ if (type == qMetaTypeId<QVariant>()) {
+ registers[instr->cleanup.reg].getvariantptr()->~QVariant();
+ } else if (type == QMetaType::QString) {
+ registers[instr->cleanup.reg].getstringptr()->~QString();
+ } else if (type == QMetaType::QUrl) {
+ registers[instr->cleanup.reg].geturlptr()->~QUrl();
+ }
+ }
+ break;
+
+ case Instr::ConvertGenericToReal:
+ {
+ Register &output = registers[instr->unaryop.output];
+ Register &input = registers[instr->unaryop.src];
+ bool ok = true;
+ output.setqreal(toReal(&input, input.gettype(), &ok));
+ if (!ok) output.setUndefined();
+ }
+ break;
+
+ case Instr::ConvertGenericToBool:
+ {
+ Register &output = registers[instr->unaryop.output];
+ Register &input = registers[instr->unaryop.src];
+ bool ok = true;
+ output.setbool(toBool(&input, input.gettype(), &ok));
+ if (!ok) output.setUndefined();
+ }
+ break;
+
+ case Instr::ConvertGenericToString:
+ {
+ Register &output = registers[instr->unaryop.output];
+ Register &input = registers[instr->unaryop.src];
+ bool ok = true;
+ QString str = toString(&input, input.gettype(), &ok);
+ if (ok) { new (output.getstringptr()) QString(str); output.settype(QMetaType::QString); }
+ else { output.setUndefined(); }
+ }
+ break;
+
+ case Instr::ConvertGenericToUrl:
+ {
+ Register &output = registers[instr->unaryop.output];
+ Register &input = registers[instr->unaryop.src];
+ bool ok = true;
+ QUrl url = toUrl(&input, input.gettype(), context, &ok);
+ if (ok) { new (output.geturlptr()) QUrl(url); output.settype(QMetaType::QUrl); }
+ else { output.setUndefined(); }
+ }
+ break;
+
+ default:
+ qFatal("EEK");
+ break;
+ }
+
+ instr++;
+ }
+}
+
+void QmlBindingCompiler::dump(const QByteArray &programData)
+{
+ const Program *program = (const Program *)programData.constData();
+
+ qWarning() << "Program.bindings:" << program->bindings;
+ qWarning() << "Program.dataLength:" << program->dataLength;
+ qWarning() << "Program.subscriptions:" << program->subscriptions;
+ qWarning() << "Program.indentifiers:" << program->identifiers;
+
+ int count = program->instructionCount;
+ const Instr *instr = program->instructions();
+
+ while (count--) {
+
+ switch (instr->common.type) {
+ case Instr::Noop:
+ qWarning().nospace() << "Noop";
+ break;
+ case Instr::Subscribe:
+ qWarning().nospace() << "Subscribe" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index;
+ break;
+ case Instr::SubscribeId:
+ qWarning().nospace() << "SubscribeId" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index;
+ break;
+ case Instr::LoadId:
+ qWarning().nospace() << "LoadId" << "\t\t\t" << instr->load.index << "\t" << instr->load.reg;
+ break;
+ case Instr::LoadScope:
+ qWarning().nospace() << "LoadScope" << "\t\t" << instr->load.index << "\t" << instr->load.reg;
+ break;
+ case Instr::LoadRoot:
+ qWarning().nospace() << "LoadRoot" << "\t\t" << instr->load.index << "\t" << instr->load.reg;
+ break;
+ case Instr::LoadAttached:
+ qWarning().nospace() << "LoadAttached" << "\t\t" << instr->attached.output << "\t" << instr->attached.reg << "\t" << instr->attached.index;
+ break;
+ case Instr::ConvertIntToReal:
+ qWarning().nospace() << "ConvertIntToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
+ break;
+ case Instr::ConvertRealToInt:
+ qWarning().nospace() << "ConvertRealToInt" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
+ break;
+ case Instr::Real:
+ qWarning().nospace() << "Real" << "\t\t\t" << instr->real_value.reg << "\t" << instr->real_value.value;
+ break;
+ case Instr::Int:
+ qWarning().nospace() << "Int" << "\t\t\t" << instr->int_value.reg << "\t" << instr->int_value.value;
+ break;
+ case Instr::Bool:
+ qWarning().nospace() << "Bool" << "\t\t\t" << instr->bool_value.reg << "\t" << instr->bool_value.value;
+ break;
+ case Instr::String:
+ qWarning().nospace() << "String" << "\t\t\t" << instr->string_value.reg << "\t" << instr->string_value.offset << "\t" << instr->string_value.length;
+ break;
+ case Instr::AddReal:
+ qWarning().nospace() << "AddReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::AddInt:
+ qWarning().nospace() << "AddInt" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::AddString:
+ qWarning().nospace() << "AddString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::MinusReal:
+ qWarning().nospace() << "MinusReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::MinusInt:
+ qWarning().nospace() << "MinusInt" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::CompareReal:
+ qWarning().nospace() << "CompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::CompareString:
+ qWarning().nospace() << "CompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::NotCompareReal:
+ qWarning().nospace() << "NotCompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::NotCompareString:
+ qWarning().nospace() << "NotCompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::GreaterThanReal:
+ qWarning().nospace() << "GreaterThanReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::MaxReal:
+ qWarning().nospace() << "MaxReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::MinReal:
+ qWarning().nospace() << "MinReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
+ break;
+ case Instr::NewString:
+ qWarning().nospace() << "NewString" << "\t\t" << instr->construct.reg;
+ break;
+ case Instr::NewUrl:
+ qWarning().nospace() << "NewUrl" << "\t\t\t" << instr->construct.reg;
+ break;
+ case Instr::CleanupString:
+ qWarning().nospace() << "CleanupString" << "\t\t" << instr->cleanup.reg;
+ break;
+ case Instr::CleanupUrl:
+ qWarning().nospace() << "CleanupUrl" << "\t\t" << instr->cleanup.reg;
+ break;
+ case Instr::Fetch:
+ qWarning().nospace() << "Fetch" << "\t\t\t" << instr->fetch.output << "\t" << instr->fetch.index << "\t" << instr->fetch.objectReg;
+ break;
+ case Instr::Store:
+ qWarning().nospace() << "Store" << "\t\t\t" << instr->store.output << "\t" << instr->store.index << "\t" << instr->store.reg;
+ break;
+ case Instr::Copy:
+ qWarning().nospace() << "Copy" << "\t\t\t" << instr->copy.reg << "\t" << instr->copy.src;
+ break;
+ case Instr::Skip:
+ qWarning().nospace() << "Skip" << "\t\t\t" << instr->skip.reg << "\t" << instr->skip.count;
+ break;
+ case Instr::Done:
+ qWarning().nospace() << "Done";
+ break;
+ case Instr::InitString:
+ qWarning().nospace() << "InitString" << "\t\t" << instr->initstring.offset << "\t" << instr->initstring.dataIdx;
+ break;
+ case Instr::FindGeneric:
+ qWarning().nospace() << "FindGeneric" << "\t\t" << instr->find.reg << "\t" << instr->find.name;
+ break;
+ case Instr::FindGenericTerminal:
+ qWarning().nospace() << "FindGenericTerminal" << "\t" << instr->find.reg << "\t" << instr->find.name;
+ break;
+ case Instr::FindProperty:
+ qWarning().nospace() << "FindProperty" << "\t\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name;
+ break;
+ case Instr::FindPropertyTerminal:
+ qWarning().nospace() << "FindPropertyTerminal" << "\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name;
+ break;
+ case Instr::CleanupGeneric:
+ qWarning().nospace() << "CleanupGeneric" << "\t\t" << instr->cleanup.reg;
+ break;
+ case Instr::ConvertGenericToReal:
+ qWarning().nospace() << "ConvertGenericToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
+ break;
+ case Instr::ConvertGenericToBool:
+ qWarning().nospace() << "ConvertGenericToBool" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
+ break;
+ case Instr::ConvertGenericToString:
+ qWarning().nospace() << "ConvertGenericToString" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
+ break;
+ case Instr::ConvertGenericToUrl:
+ qWarning().nospace() << "ConvertGenericToUrl" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
+ break;
+ default:
+ qWarning().nospace() << "Unknown";
+ break;
+ }
+
+ ++instr;
+ }
+}
+
+/*!
+Clear the state associated with attempting to compile a specific binding.
+This does not clear the global "commited binding" states.
+*/
+void QmlBindingCompilerPrivate::resetInstanceState()
+{
+ registers = 0;
+ registerCleanups.clear();
+ data = committed.data;
+ exceptions = committed.exceptions;
+ usedSubscriptionIds.clear();
+ subscriptionSet.clear();
+ subscriptionIds = committed.subscriptionIds;
+ registeredStrings = committed.registeredStrings;
+ bytecode.clear();
+}
+
+/*!
+Mark the last compile as successful, and add it to the "committed data"
+section.
+
+Returns the index for the committed binding.
+*/
+int QmlBindingCompilerPrivate::commitCompile()
+{
+ int rv = committed.count();
+ committed.offsets << committed.bytecode.count();
+ committed.dependencies << usedSubscriptionIds;
+ committed.bytecode << bytecode;
+ committed.data = data;
+ committed.exceptions = exceptions;
+ committed.subscriptionIds = subscriptionIds;
+ committed.registeredStrings = registeredStrings;
+ return rv;
+}
+
+bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node)
+{
+ resetInstanceState();
+
+ Result type;
+
+ if (!parseExpression(node, type))
+ return false;
+
+ if (subscriptionSet.count() > 0xFFFF ||
+ registeredStrings.count() > 0xFFFF)
+ return false;
+
+ if (type.unknownType) {
+ if (destination->type != QMetaType::QReal &&
+ destination->type != QVariant::String &&
+ destination->type != QMetaType::Bool &&
+ destination->type != QVariant::Url)
+ return false;
+
+ int convertReg = acquireReg();
+
+ if (destination->type == QMetaType::QReal) {
+ Instr convert;
+ convert.common.type = Instr::ConvertGenericToReal;
+ convert.unaryop.output = convertReg;
+ convert.unaryop.src = type.reg;
+ bytecode << convert;
+ } else if (destination->type == QVariant::String) {
+ Instr convert;
+ convert.common.type = Instr::ConvertGenericToString;
+ convert.unaryop.output = convertReg;
+ convert.unaryop.src = type.reg;
+ bytecode << convert;
+ } else if (destination->type == QMetaType::Bool) {
+ Instr convert;
+ convert.common.type = Instr::ConvertGenericToBool;
+ convert.unaryop.output = convertReg;
+ convert.unaryop.src = type.reg;
+ bytecode << convert;
+ } else if (destination->type == QVariant::Url) {
+ Instr convert;
+ convert.common.type = Instr::ConvertGenericToUrl;
+ convert.unaryop.output = convertReg;
+ convert.unaryop.src = type.reg;
+ bytecode << convert;
+ }
+
+ Instr cleanup;
+ cleanup.common.type = Instr::CleanupGeneric;
+ cleanup.cleanup.reg = type.reg;
+ bytecode << cleanup;
+
+ Instr instr;
+ instr.common.type = Instr::Store;
+ instr.store.output = 0;
+ instr.store.index = destination->index;
+ instr.store.reg = convertReg;
+ instr.store.exceptionId = exceptionId(node->expressionCast());
+ bytecode << instr;
+
+ if (destination->type == QVariant::String) {
+ Instr cleanup;
+ cleanup.common.type = Instr::CleanupString;
+ cleanup.cleanup.reg = convertReg;
+ bytecode << cleanup;
+ } else if (destination->type == QVariant::Url) {
+ Instr cleanup;
+ cleanup.common.type = Instr::CleanupUrl;
+ cleanup.cleanup.reg = convertReg;
+ bytecode << cleanup;
+ }
+
+ releaseReg(convertReg);
+
+ Instr done;
+ done.common.type = Instr::Done;
+ bytecode << done;
+
+ return true;
+ } else {
+ // Can we store the final value?
+ if (type.type == QVariant::Int &&
+ destination->type == QMetaType::QReal) {
+ Instr instr;
+ instr.common.type = Instr::ConvertIntToReal;
+ instr.unaryop.output = type.reg;
+ instr.unaryop.src = type.reg;
+ bytecode << instr;
+ type.type = QMetaType::QReal;
+ } else if (type.type == QMetaType::QReal &&
+ destination->type == QVariant::Int) {
+ Instr instr;
+ instr.common.type = Instr::ConvertRealToInt;
+ instr.unaryop.output = type.reg;
+ instr.unaryop.src = type.reg;
+ bytecode << instr;
+ type.type = QVariant::Int;
+ } else if (type.type == destination->type) {
+ } else {
+ const QMetaObject *from = type.metaObject;
+ const QMetaObject *to = engine->rawMetaObjectForType(destination->type);
+
+ if (QmlMetaPropertyPrivate::canConvert(from, to))
+ type.type = destination->type;
+ }
+
+ if (type.type == destination->type) {
+ Instr instr;
+ instr.common.type = Instr::Store;
+ instr.store.output = 0;
+ instr.store.index = destination->index;
+ instr.store.reg = type.reg;
+ instr.store.exceptionId = exceptionId(node->expressionCast());
+ bytecode << instr;
+
+ releaseReg(type.reg);
+
+ Instr done;
+ done.common.type = Instr::Done;
+ bytecode << done;
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+bool QmlBindingCompilerPrivate::parseExpression(QmlJS::AST::Node *node, Result &type)
+{
+ while (node->kind == AST::Node::Kind_NestedExpression)
+ node = static_cast<AST::NestedExpression *>(node)->expression;
+
+ if (tryArith(node)) {
+ if (!parseArith(node, type)) return false;
+ } else if (tryLogic(node)) {
+ if (!parseLogic(node, type)) return false;
+ } else if (tryConditional(node)) {
+ if (!parseConditional(node, type)) return false;
+ } else if (tryName(node)) {
+ if (!parseName(node, type)) return false;
+ } else if (tryConstant(node)) {
+ if (!parseConstant(node, type)) return false;
+ } else if (tryMethod(node)) {
+ if (!parseMethod(node, type)) return false;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool QmlBindingCompilerPrivate::tryName(QmlJS::AST::Node *node)
+{
+ return node->kind == AST::Node::Kind_IdentifierExpression ||
+ node->kind == AST::Node::Kind_FieldMemberExpression;
+}
+
+bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type)
+{
+ QStringList nameParts;
+ QList<AST::ExpressionNode *> nameNodes;
+ if (!buildName(nameParts, node, &nameNodes))
+ return false;
+
+ int reg = acquireReg();
+ if (reg == -1)
+ return false;
+ type.reg = reg;
+
+ QmlParser::Object *absType = 0;
+
+ QStringList subscribeName;
+
+ bool wasAttachedObject = false;
+
+ for (int ii = 0; ii < nameParts.count(); ++ii) {
+ const QString &name = nameParts.at(ii);
+
+ // We don't handle signal properties or attached properties
+ if (name.length() > 2 && name.startsWith(QLatin1String("on")) &&
+ name.at(2).isUpper())
+ return false;
+
+ QmlType *attachType = 0;
+ if (name.at(0).isUpper()) {
+ // Could be an attached property
+ if (ii == nameParts.count() - 1)
+ return false;
+ if (nameParts.at(ii + 1).at(0).isUpper())
+ return false;
+
+ QmlEnginePrivate::ImportedNamespace *ns = 0;
+ if (!engine->resolveType(imports, name.toUtf8(), &attachType, 0, 0, 0, &ns))
+ return false;
+ if (ns || !attachType || !attachType->attachedPropertiesType())
+ return false;
+
+ wasAttachedObject = true;
+ }
+
+ if (ii == 0) {
+
+ if (attachType) {
+ Instr instr;
+ instr.common.type = Instr::LoadScope;
+ instr.load.index = 0;
+ instr.load.reg = reg;
+ bytecode << instr;
+
+ Instr attach;
+ attach.common.type = Instr::LoadAttached;
+ attach.attached.output = reg;
+ attach.attached.reg = reg;
+ attach.attached.index = attachType->index();
+ attach.attached.exceptionId = exceptionId(nameNodes.at(ii));
+ bytecode << attach;
+
+ subscribeName << contextName();
+ subscribeName << QLatin1String("$$$ATTACH_") + name;
+
+ absType = 0;
+ type.metaObject = attachType->attachedPropertiesType();
+
+ continue;
+ } else if (ids.contains(name)) {
+ QmlParser::Object *idObject = ids.value(name);
+ absType = idObject;
+ type.metaObject = absType->metaObject();
+
+ // We check if the id object is the root or
+ // scope object to avoid a subscription
+ if (idObject == component) {
+ Instr instr;
+ instr.common.type = Instr::LoadRoot;
+ instr.load.index = 0;
+ instr.load.reg = reg;
+ bytecode << instr;
+ } else if (idObject == context) {
+ Instr instr;
+ instr.common.type = Instr::LoadScope;
+ instr.load.index = 0;
+ instr.load.reg = reg;
+ bytecode << instr;
+ } else {
+ Instr instr;
+ instr.common.type = Instr::LoadId;
+ instr.load.index = idObject->idIndex;
+ instr.load.reg = reg;
+ bytecode << instr;
+
+ subscribeName << QLatin1String("$$$ID_") + name;
+
+ if (subscription(subscribeName, &type)) {
+ Instr sub;
+ sub.common.type = Instr::SubscribeId;
+ sub.subscribe.offset = subscriptionIndex(subscribeName);
+ sub.subscribe.reg = reg;
+ sub.subscribe.index = instr.load.index;
+ bytecode << sub;
+ }
+ }
+
+ } else {
+
+ QByteArray utf8Name = name.toUtf8();
+ const char *cname = utf8Name.constData();
+
+ int d0Idx = (context == component)?-1:context->metaObject()->indexOfProperty(cname);
+ int d1Idx = -1;
+ if (d0Idx == -1)
+ d1Idx = component->metaObject()->indexOfProperty(cname);
+
+ if (d0Idx != -1) {
+ Instr instr;
+ instr.common.type = Instr::LoadScope;
+ instr.load.index = 0;
+ instr.load.reg = reg;
+ bytecode << instr;
+
+ subscribeName << contextName();
+ subscribeName << name;
+
+ fetch(type, context->metaObject(), reg, d0Idx, subscribeName, nameNodes.at(ii));
+ } else if(d1Idx != -1) {
+ Instr instr;
+ instr.common.type = Instr::LoadRoot;
+ instr.load.index = 0;
+ instr.load.reg = reg;
+ bytecode << instr;
+
+ subscribeName << QLatin1String("$$$ROOT");
+ subscribeName << name;
+
+ fetch(type, component->metaObject(), reg, d1Idx, subscribeName, nameNodes.at(ii));
+ } else {
+ Instr find;
+ if (nameParts.count() == 1)
+ find.common.type = Instr::FindGenericTerminal;
+ else
+ find.common.type = Instr::FindGeneric;
+
+ find.find.reg = reg;
+ find.find.src = -1;
+ find.find.name = registerString(name);
+ find.find.exceptionId = exceptionId(nameNodes.at(ii));
+
+ subscribeName << QString(QLatin1String("$$$Generic_") + name);
+ if (subscription(subscribeName, &type))
+ find.find.subscribeIndex = subscriptionIndex(subscribeName);
+ else
+ find.find.subscribeIndex = -1;
+
+ bytecode << find;
+ type.unknownType = true;
+ }
+
+ if (!type.unknownType && type.type == -1)
+ return false; // Couldn't fetch that type
+ }
+
+ } else {
+
+ if (attachType) {
+ Instr attach;
+ attach.common.type = Instr::LoadAttached;
+ attach.attached.output = reg;
+ attach.attached.reg = reg;
+ attach.attached.index = attachType->index();
+ bytecode << attach;
+
+ absType = 0;
+ type.metaObject = attachType->attachedPropertiesType();
+
+ subscribeName << QLatin1String("$$$ATTACH_") + name;
+ continue;
+ }
+
+ const QMetaObject *mo = 0;
+ if (absType)
+ mo = absType->metaObject();
+ else if (type.metaObject)
+ mo = type.metaObject;
+
+ QByteArray utf8Name = name.toUtf8();
+ const char *cname = utf8Name.constData();
+ int idx = mo?mo->indexOfProperty(cname):-1;
+ if (absType && idx == -1)
+ return false;
+
+ subscribeName << name;
+
+ if (absType || (wasAttachedObject && idx != -1) || (mo && mo->property(idx).isFinal())) {
+ absType = 0;
+ fetch(type, mo, reg, idx, subscribeName, nameNodes.at(ii));
+ if (type.type == -1)
+ return false;
+ } else {
+
+ Instr prop;
+ if (ii == nameParts.count() -1 )
+ prop.common.type = Instr::FindPropertyTerminal;
+ else
+ prop.common.type = Instr::FindProperty;
+
+ prop.find.reg = reg;
+ prop.find.src = reg;
+ prop.find.name = registerString(name);
+ prop.find.exceptionId = exceptionId(nameNodes.at(ii));
+
+ if (subscription(subscribeName, &type))
+ prop.find.subscribeIndex = subscriptionIndex(subscribeName);
+ else
+ prop.find.subscribeIndex = -1;
+
+ type.unknownType = true;
+ type.metaObject = 0;
+ type.type = -1;
+ type.reg = reg;
+ bytecode << prop;
+ }
+ }
+
+ wasAttachedObject = false;
+ }
+
+ return true;
+}
+
+bool QmlBindingCompilerPrivate::tryArith(QmlJS::AST::Node *node)
+{
+ if (node->kind != AST::Node::Kind_BinaryExpression)
+ return false;
+
+ AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
+ if (expression->op == QSOperator::Add ||
+ expression->op == QSOperator::Sub)
+ return true;
+ else
+ return false;
+}
+
+bool QmlBindingCompilerPrivate::parseArith(QmlJS::AST::Node *node, Result &type)
+{
+ AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
+
+ type.reg = acquireReg();
+
+ Result lhs;
+ Result rhs;
+
+ if (!parseExpression(expression->left, lhs)) return false;
+ if (!parseExpression(expression->right, rhs)) return false;
+
+ if ((lhs.type == QVariant::Int || lhs.type == QMetaType::QReal) &&
+ (rhs.type == QVariant::Int || rhs.type == QMetaType::QReal))
+ return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op);
+ else if(expression->op == QSOperator::Sub)
+ return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op);
+ else if ((lhs.type == QMetaType::QString || lhs.unknownType) &&
+ (rhs.type == QMetaType::QString || rhs.unknownType) &&
+ (lhs.type == QMetaType::QString || rhs.type == QMetaType::QString))
+ return stringArith(type, lhs, rhs, (QSOperator::Op)expression->op);
+ else
+ return false;
+}
+
+bool QmlBindingCompilerPrivate::numberArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op)
+{
+ bool nativeReal = rhs.type == QMetaType::QReal ||
+ lhs.type == QMetaType::QReal ||
+ lhs.unknownType ||
+ rhs.unknownType;
+
+ if (nativeReal && lhs.type == QMetaType::Int) {
+ Instr convert;
+ convert.common.type = Instr::ConvertIntToReal;
+ convert.unaryop.output = lhs.reg;
+ convert.unaryop.src = lhs.reg;
+ bytecode << convert;
+ }
+
+ if (nativeReal && rhs.type == QMetaType::Int) {
+ Instr convert;
+ convert.common.type = Instr::ConvertIntToReal;
+ convert.unaryop.output = rhs.reg;
+ convert.unaryop.src = rhs.reg;
+ bytecode << convert;
+ }
+
+ int lhsTmp = -1;
+ int rhsTmp = -1;
+ if (lhs.unknownType) {
+ lhsTmp = acquireReg();
+
+ Instr conv;
+ conv.common.type = Instr::ConvertGenericToReal;
+ conv.unaryop.output = lhsTmp;
+ conv.unaryop.src = lhs.reg;
+ bytecode << conv;
+ }
+
+ if (rhs.unknownType) {
+ rhsTmp = acquireReg();
+
+ Instr conv;
+ conv.common.type = Instr::ConvertGenericToReal;
+ conv.unaryop.output = rhsTmp;
+ conv.unaryop.src = rhs.reg;
+ bytecode << conv;
+ }
+
+ Instr arith;
+ if (op == QSOperator::Add) {
+ arith.common.type = nativeReal?Instr::AddReal:Instr::AddInt;
+ } else if (op == QSOperator::Sub) {
+ arith.common.type = nativeReal?Instr::MinusReal:Instr::MinusInt;
+ } else {
+ qFatal("Unsupported arithmetic operator");
+ }
+
+ arith.binaryop.output = type.reg;
+ arith.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp;
+ arith.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp;
+ bytecode << arith;
+
+ type.metaObject = 0;
+ type.type = nativeReal?QMetaType::QReal:QMetaType::Int;
+ type.subscriptionSet.unite(lhs.subscriptionSet);
+ type.subscriptionSet.unite(rhs.subscriptionSet);
+
+ if (lhsTmp != -1) releaseReg(lhsTmp);
+ if (rhsTmp != -1) releaseReg(rhsTmp);
+ releaseReg(lhs.reg);
+ releaseReg(rhs.reg);
+
+ return true;
+}
+
+bool QmlBindingCompilerPrivate::stringArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op)
+{
+ if (op != QSOperator::Add)
+ return false;
+
+ int lhsTmp = -1;
+ int rhsTmp = -1;
+
+ if (lhs.unknownType) {
+ lhsTmp = acquireReg(Instr::CleanupString);
+
+ Instr convert;
+ convert.common.type = Instr::ConvertGenericToString;
+ convert.unaryop.output = lhsTmp;
+ convert.unaryop.src = lhs.reg;
+ bytecode << convert;
+ }
+
+ if (rhs.unknownType) {
+ rhsTmp = acquireReg(Instr::CleanupString);
+
+ Instr convert;
+ convert.common.type = Instr::ConvertGenericToString;
+ convert.unaryop.output = rhsTmp;
+ convert.unaryop.src = rhs.reg;
+ bytecode << convert;
+ }
+
+ type.reg = acquireReg(Instr::CleanupString);
+ type.type = QMetaType::QString;
+
+ Instr add;
+ add.common.type = Instr::AddString;
+ add.binaryop.output = type.reg;
+ add.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp;
+ add.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp;
+ bytecode << add;
+
+ if (lhsTmp != -1) releaseReg(lhsTmp);
+ if (rhsTmp != -1) releaseReg(rhsTmp);
+
+ return true;
+}
+
+bool QmlBindingCompilerPrivate::tryLogic(QmlJS::AST::Node *node)
+{
+ if (node->kind != AST::Node::Kind_BinaryExpression)
+ return false;
+
+ AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
+ if (expression->op == QSOperator::Gt ||
+ expression->op == QSOperator::Equal ||
+ expression->op == QSOperator::NotEqual)
+ return true;
+ else
+ return false;
+}
+
+bool QmlBindingCompilerPrivate::parseLogic(QmlJS::AST::Node *node, Result &type)
+{
+ AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
+
+ Result lhs;
+ Result rhs;
+
+ if (!parseExpression(expression->left, lhs)) return false;
+ if (!parseExpression(expression->right, rhs)) return false;
+
+ type.reg = acquireReg();
+ type.metaObject = 0;
+ type.type = QVariant::Bool;
+
+ if (lhs.type == QMetaType::QReal && rhs.type == QMetaType::QReal) {
+
+ Instr op;
+ if (expression->op == QSOperator::Gt)
+ op.common.type = Instr::GreaterThanReal;
+ else if (expression->op == QSOperator::Equal)
+ op.common.type = Instr::CompareReal;
+ else if (expression->op == QSOperator::NotEqual)
+ op.common.type = Instr::NotCompareReal;
+ else
+ return false;
+ op.binaryop.output = type.reg;
+ op.binaryop.src1 = lhs.reg;
+ op.binaryop.src2 = rhs.reg;
+ bytecode << op;
+
+
+ } else if (lhs.type == QMetaType::QString && rhs.type == QMetaType::QString) {
+
+ Instr op;
+ if (expression->op == QSOperator::Equal)
+ op.common.type = Instr::CompareString;
+ else if (expression->op == QSOperator::NotEqual)
+ op.common.type = Instr::NotCompareString;
+ else
+ return false;
+ op.binaryop.output = type.reg;
+ op.binaryop.src1 = lhs.reg;
+ op.binaryop.src2 = rhs.reg;
+ bytecode << op;
+
+ } else {
+ return false;
+ }
+
+ releaseReg(lhs.reg);
+ releaseReg(rhs.reg);
+
+ return true;
+}
+
+bool QmlBindingCompilerPrivate::tryConditional(QmlJS::AST::Node *node)
+{
+ return (node->kind == AST::Node::Kind_ConditionalExpression);
+}
+
+bool QmlBindingCompilerPrivate::parseConditional(QmlJS::AST::Node *node, Result &type)
+{
+ AST::ConditionalExpression *expression = static_cast<AST::ConditionalExpression *>(node);
+
+ AST::Node *test = expression->expression;
+ if (test->kind == AST::Node::Kind_NestedExpression)
+ test = static_cast<AST::NestedExpression*>(test)->expression;
+
+ Result etype;
+ if (!parseExpression(test, etype)) return false;
+
+ if (etype.type != QVariant::Bool)
+ return false;
+
+ Instr skip;
+ skip.common.type = Instr::Skip;
+ skip.skip.reg = etype.reg;
+ skip.skip.count = 0;
+ int skipIdx = bytecode.count();
+ bytecode << skip;
+
+ // Release to allow reuse of reg
+ releaseReg(etype.reg);
+
+ QSet<QString> preSubSet = subscriptionSet;
+
+ // int preConditionalSubscriptions = subscriptionSet.count();
+
+ Result ok;
+ if (!parseExpression(expression->ok, ok)) return false;
+ if (ok.unknownType) return false;
+
+ int skipIdx2 = bytecode.count();
+ skip.skip.reg = -1;
+ bytecode << skip;
+
+ // Release to allow reuse of reg
+ releaseReg(ok.reg);
+ bytecode[skipIdx].skip.count = bytecode.count() - skipIdx - 1;
+
+ subscriptionSet = preSubSet;
+
+ Result ko;
+ if (!parseExpression(expression->ko, ko)) return false;
+ if (ko.unknownType) return false;
+
+ // Release to allow reuse of reg
+ releaseReg(ko.reg);
+ bytecode[skipIdx2].skip.count = bytecode.count() - skipIdx2 - 1;
+
+ if (ok != ko)
+ return false; // Must be same type and in same register
+
+ subscriptionSet = preSubSet;
+
+ if (!subscriptionNeutral(subscriptionSet, ok.subscriptionSet, ko.subscriptionSet))
+ return false; // Conditionals cannot introduce new subscriptions
+
+ type = ok;
+
+ return true;
+}
+
+bool QmlBindingCompilerPrivate::tryConstant(QmlJS::AST::Node *node)
+{
+ return node->kind == AST::Node::Kind_TrueLiteral ||
+ node->kind == AST::Node::Kind_FalseLiteral ||
+ node->kind == AST::Node::Kind_NumericLiteral ||
+ node->kind == AST::Node::Kind_StringLiteral;
+}
+
+bool QmlBindingCompilerPrivate::parseConstant(QmlJS::AST::Node *node, Result &type)
+{
+ type.metaObject = 0;
+ type.type = -1;
+ type.reg = acquireReg();
+
+ if (node->kind == AST::Node::Kind_TrueLiteral) {
+ type.type = QVariant::Bool;
+ Instr instr;
+ instr.common.type = Instr::Bool;
+ instr.bool_value.reg = type.reg;
+ instr.bool_value.value = true;
+ bytecode << instr;
+ return true;
+ } else if (node->kind == AST::Node::Kind_FalseLiteral) {
+ type.type = QVariant::Bool;
+ Instr instr;
+ instr.common.type = Instr::Bool;
+ instr.bool_value.reg = type.reg;
+ instr.bool_value.value = false;
+ bytecode << instr;
+ return true;
+ } else if (node->kind == AST::Node::Kind_NumericLiteral) {
+ qreal value = qreal(static_cast<AST::NumericLiteral *>(node)->value);
+
+ if (qreal(float(value)) != value)
+ return false;
+
+ type.type = QMetaType::QReal;
+ Instr instr;
+ instr.common.type = Instr::Real;
+ instr.real_value.reg = type.reg;
+ instr.real_value.value = float(value);
+ bytecode << instr;
+ return true;
+ } else if (node->kind == AST::Node::Kind_StringLiteral) {
+ QString str = static_cast<AST::StringLiteral *>(node)->value->asString();
+ type.type = QMetaType::QString;
+ type.reg = registerLiteralString(str);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QmlBindingCompilerPrivate::tryMethod(QmlJS::AST::Node *node)
+{
+ return node->kind == AST::Node::Kind_CallExpression;
+}
+
+bool QmlBindingCompilerPrivate::parseMethod(QmlJS::AST::Node *node, Result &result)
+{
+ AST::CallExpression *expr = static_cast<AST::CallExpression *>(node);
+
+ QStringList name;
+ if (!buildName(name, expr->base))
+ return false;
+
+ if (name.count() != 2 || name.at(0) != QLatin1String("Math"))
+ return false;
+
+ QString method = name.at(1);
+
+ AST::ArgumentList *args = expr->arguments;
+ if (!args) return false;
+ AST::ExpressionNode *arg0 = args->expression;
+ args = args->next;
+ if (!args) return false;
+ AST::ExpressionNode *arg1 = args->expression;
+ if (args->next != 0) return false;
+ if (!arg0 || !arg1) return false;
+
+ Result r0;
+ if (!parseExpression(arg0, r0)) return false;
+ Result r1;
+ if (!parseExpression(arg1, r1)) return false;
+
+ if (r0.type != QMetaType::QReal || r1.type != QMetaType::QReal)
+ return false;
+
+ Instr op;
+ if (method == QLatin1String("max")) {
+ op.common.type = Instr::MaxReal;
+ } else if (method == QLatin1String("min")) {
+ op.common.type = Instr::MinReal;
+ } else {
+ return false;
+ }
+ // We release early to reuse registers
+ releaseReg(r0.reg);
+ releaseReg(r1.reg);
+
+ op.binaryop.output = acquireReg();
+ op.binaryop.src1 = r0.reg;
+ op.binaryop.src2 = r1.reg;
+ bytecode << op;
+
+ result.type = QMetaType::QReal;
+ result.reg = op.binaryop.output;
+
+ return true;
+}
+
+bool QmlBindingCompilerPrivate::buildName(QStringList &name,
+ QmlJS::AST::Node *node,
+ QList<QmlJS::AST::ExpressionNode *> *nodes)
+{
+ if (node->kind == AST::Node::Kind_IdentifierExpression) {
+ name << static_cast<AST::IdentifierExpression*>(node)->name->asString();
+ if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
+ } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
+ AST::FieldMemberExpression *expr =
+ static_cast<AST::FieldMemberExpression *>(node);
+
+ if (!buildName(name, expr->base, nodes))
+ return false;
+
+ name << expr->name->asString();
+ if (nodes) *nodes << expr;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+
+bool QmlBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg,
+ int idx, const QStringList &subName, QmlJS::AST::ExpressionNode *node)
+{
+ QMetaProperty prop = mo->property(idx);
+ rv.metaObject = 0;
+ rv.type = 0;
+
+ if (subscription(subName, &rv) && prop.hasNotifySignal() && prop.notifySignalIndex() != -1) {
+ Instr sub;
+ sub.common.type = Instr::Subscribe;
+ sub.subscribe.offset = subscriptionIndex(subName);
+ sub.subscribe.reg = reg;
+ sub.subscribe.index = prop.notifySignalIndex();
+ bytecode << sub;
+ }
+
+ Instr fetch;
+ fetch.common.type = Instr::Fetch;
+ fetch.fetch.objectReg = reg;
+ fetch.fetch.index = idx;
+ fetch.fetch.output = reg;
+ fetch.fetch.exceptionId = exceptionId(node);
+
+ rv.type = prop.userType();
+ rv.metaObject = engine->metaObjectForType(rv.type);
+ rv.reg = reg;
+
+ if (rv.type == QMetaType::QString) {
+ int tmp = acquireReg();
+ Instr copy;
+ copy.common.type = Instr::Copy;
+ copy.copy.reg = tmp;
+ copy.copy.src = reg;
+ bytecode << copy;
+ releaseReg(tmp);
+ fetch.fetch.objectReg = tmp;
+
+ Instr setup;
+ setup.common.type = Instr::NewString;
+ setup.construct.reg = reg;
+ bytecode << setup;
+ registerCleanup(reg, Instr::CleanupString);
+ }
+
+ bytecode << fetch;
+
+ if (!rv.metaObject &&
+ rv.type != QMetaType::QReal &&
+ rv.type != QMetaType::Int &&
+ rv.type != QMetaType::Bool &&
+ rv.type != qMetaTypeId<QmlGraphicsAnchorLine>() &&
+ rv.type != QMetaType::QString) {
+ rv.metaObject = 0;
+ rv.type = 0;
+ return false; // Unsupported type (string not supported yet);
+ }
+
+ return true;
+}
+
+void QmlBindingCompilerPrivate::registerCleanup(int reg, int cleanup, int cleanupType)
+{
+ registerCleanups.insert(reg, qMakePair(cleanup, cleanupType));
+}
+
+int QmlBindingCompilerPrivate::acquireReg(int cleanup, int cleanupType)
+{
+ for (int ii = 0; ii < 32; ++ii) {
+ if (!(registers & (1 << ii))) {
+ registers |= (1 << ii);
+
+ if (cleanup != Instr::Noop)
+ registerCleanup(ii, cleanup, cleanupType);
+
+ return ii;
+ }
+ }
+ return -1;
+}
+
+void QmlBindingCompilerPrivate::releaseReg(int reg)
+{
+ Q_ASSERT(reg >= 0 && reg <= 31);
+
+ if (registerCleanups.contains(reg)) {
+ QPair<int, int> c = registerCleanups[reg];
+ registerCleanups.remove(reg);
+ Instr cleanup;
+ cleanup.common.type = (quint8)c.first;
+ cleanup.cleanup.reg = reg;
+ bytecode << cleanup;
+ }
+
+ quint32 mask = 1 << reg;
+ registers &= ~mask;
+}
+
+// Returns a reg
+int QmlBindingCompilerPrivate::registerLiteralString(const QString &str)
+{
+ QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar));
+ int offset = data.count();
+ data += strdata;
+
+ int reg = acquireReg(Instr::CleanupString);
+
+ Instr string;
+ string.common.type = Instr::String;
+ string.string_value.reg = reg;
+ string.string_value.offset = offset;
+ string.string_value.length = str.length();
+ bytecode << string;
+
+ return reg;
+}
+
+// Returns an identifier offset
+int QmlBindingCompilerPrivate::registerString(const QString &string)
+{
+ Q_ASSERT(!string.isEmpty());
+
+ QHash<QString, QPair<int, int> >::ConstIterator iter = registeredStrings.find(string);
+
+ if (iter == registeredStrings.end()) {
+ quint32 len = string.length();
+ QByteArray lendata((const char *)&len, sizeof(quint32));
+ QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar));
+ strdata.prepend(lendata);
+ int rv = data.count();
+ data += strdata;
+
+ iter = registeredStrings.insert(string, qMakePair(registeredStrings.count(), rv));
+ }
+
+ Instr reg;
+ reg.common.type = Instr::InitString;
+ reg.initstring.offset = iter->first;
+ reg.initstring.dataIdx = iter->second;
+ bytecode << reg;
+ return reg.initstring.offset;
+}
+
+bool QmlBindingCompilerPrivate::subscription(const QStringList &sub, Result *result)
+{
+ QString str = sub.join(QLatin1String("."));
+ result->subscriptionSet.insert(str);
+
+ if (subscriptionSet.contains(str)) {
+ return false;
+ } else {
+ subscriptionSet.insert(str);
+ return true;
+ }
+}
+
+int QmlBindingCompilerPrivate::subscriptionIndex(const QStringList &sub)
+{
+ QString str = sub.join(QLatin1String("."));
+ QHash<QString, int>::ConstIterator iter = subscriptionIds.find(str);
+ if (iter == subscriptionIds.end())
+ iter = subscriptionIds.insert(str, subscriptionIds.count());
+ usedSubscriptionIds.insert(*iter);
+ return *iter;
+}
+
+/*
+ Returns true if lhs contains no subscriptions that aren't also in base or rhs AND
+ rhs contains no subscriptions that aren't also in base or lhs.
+*/
+bool QmlBindingCompilerPrivate::subscriptionNeutral(const QSet<QString> &base,
+ const QSet<QString> &lhs,
+ const QSet<QString> &rhs)
+{
+ QSet<QString> difflhs = lhs;
+ difflhs.subtract(rhs);
+ QSet<QString> diffrhs = rhs;
+ diffrhs.subtract(lhs);
+
+ difflhs.unite(diffrhs);
+ difflhs.subtract(base);
+
+ return difflhs.isEmpty();
+}
+
+quint8 QmlBindingCompilerPrivate::exceptionId(QmlJS::AST::ExpressionNode *n)
+{
+ quint8 rv = 0xFF;
+ if (n && exceptions.count() < 0xFF) {
+ rv = (quint8)exceptions.count();
+ QmlJS::AST::SourceLocation l = n->firstSourceLocation();
+ quint64 e = l.startLine;
+ e <<= 32;
+ e |= l.startColumn;
+ exceptions.append(e);
+ }
+ return rv;
+}
+
+QmlBindingCompiler::QmlBindingCompiler()
+: d(new QmlBindingCompilerPrivate)
+{
+}
+
+QmlBindingCompiler::~QmlBindingCompiler()
+{
+ delete d; d = 0;
+}
+
+/*
+Returns true if any bindings were compiled.
+*/
+bool QmlBindingCompiler::isValid() const
+{
+ return !d->committed.bytecode.isEmpty();
+}
+
+/*
+-1 on failure, otherwise the binding index to use.
+*/
+int QmlBindingCompiler::compile(const Expression &expression, QmlEnginePrivate *engine)
+{
+ if (!expression.expression.asAST()) return false;
+
+ d->context = expression.context;
+ d->component = expression.component;
+ d->destination = expression.property;
+ d->ids = expression.ids;
+ d->imports = expression.imports;
+ d->engine = engine;
+
+ if (d->compile(expression.expression.asAST())) {
+ return d->commitCompile();
+ } else {
+ return -1;
+ }
+}
+
+
+QByteArray QmlBindingCompilerPrivate::buildSignalTable() const
+{
+ QHash<int, QList<int> > table;
+
+ for (int ii = 0; ii < committed.count(); ++ii) {
+ const QSet<int> &deps = committed.dependencies.at(ii);
+ for (QSet<int>::ConstIterator iter = deps.begin(); iter != deps.end(); ++iter)
+ table[*iter].append(ii);
+ }
+
+ QVector<quint32> header;
+ QVector<quint32> data;
+ for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) {
+ header.append(committed.subscriptionIds.count() + data.count());
+ const QList<int> &bindings = table[ii];
+ data.append(bindings.count());
+ for (int jj = 0; jj < bindings.count(); ++jj)
+ data.append(bindings.at(jj));
+ }
+ header << data;
+
+ return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32));
+}
+
+QByteArray QmlBindingCompilerPrivate::buildExceptionData() const
+{
+ QByteArray rv;
+ rv.resize(committed.exceptions.count() * sizeof(quint64));
+ ::memcpy(rv.data(), committed.exceptions.constData(), rv.size());
+ return rv;
+}
+
+/*
+Returns the compiled program.
+*/
+QByteArray QmlBindingCompiler::program() const
+{
+ QByteArray programData;
+
+ if (isValid()) {
+ Program prog;
+ prog.bindings = d->committed.count();
+
+ QVector<Instr> bytecode;
+ Instr skip;
+ skip.common.type = Instr::Skip;
+ skip.skip.reg = -1;
+ for (int ii = 0; ii < d->committed.count(); ++ii) {
+ skip.skip.count = d->committed.count() - ii - 1;
+ skip.skip.count+= d->committed.offsets.at(ii);
+ bytecode << skip;
+ }
+ bytecode << d->committed.bytecode;
+
+ QByteArray data = d->committed.data;
+ while (data.count() % 4) data.append('\0');
+ prog.signalTableOffset = data.count();
+ data += d->buildSignalTable();
+ while (data.count() % 4) data.append('\0');
+ prog.exceptionDataOffset = data.count();
+ data += d->buildExceptionData();
+
+ prog.dataLength = 4 * ((data.size() + 3) / 4);
+ prog.subscriptions = d->committed.subscriptionIds.count();
+ prog.identifiers = d->committed.registeredStrings.count();
+ prog.instructionCount = bytecode.count();
+ int size = sizeof(Program) + bytecode.count() * sizeof(Instr);
+ size += prog.dataLength;
+
+ programData.resize(size);
+ memcpy(programData.data(), &prog, sizeof(Program));
+ if (prog.dataLength)
+ memcpy((char *)((Program *)programData.data())->data(), data.constData(),
+ data.size());
+ memcpy((char *)((Program *)programData.data())->instructions(), bytecode.constData(),
+ bytecode.count() * sizeof(Instr));
+ }
+
+ return programData;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiledbindings_p.h b/src/declarative/qml/qmlcompiledbindings_p.h
new file mode 100644
index 0000000..1d8fac4
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledbindings_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBINDINGOPTIMIZATIONS_P_H
+#define QMLBINDINGOPTIMIZATIONS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlexpression_p.h"
+#include "qmlbinding.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QmlBindingCompilerPrivate;
+class QmlBindingCompiler
+{
+public:
+ QmlBindingCompiler();
+ ~QmlBindingCompiler();
+
+ // Returns true if bindings were compiled
+ bool isValid() const;
+
+ struct Expression
+ {
+ QmlParser::Object *component;
+ QmlParser::Object *context;
+ QmlParser::Property *property;
+ QmlParser::Variant expression;
+ QHash<QString, QmlParser::Object *> ids;
+ QmlEnginePrivate::Imports imports;
+ };
+
+ // -1 on failure, otherwise the binding index to use
+ int compile(const Expression &, QmlEnginePrivate *);
+
+ // Returns the compiled program
+ QByteArray program() const;
+
+ static void dump(const QByteArray &);
+private:
+ QmlBindingCompilerPrivate *d;
+};
+
+class QmlCompiledBindingsPrivate;
+class QmlCompiledBindings : public QObject, public QmlAbstractExpression, public QmlRefCount
+{
+public:
+ QmlCompiledBindings(const char *program, QmlContext *context);
+ virtual ~QmlCompiledBindings();
+
+ QmlAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property);
+
+protected:
+ int qt_metacall(QMetaObject::Call, int, void **);
+
+private:
+ Q_DISABLE_COPY(QmlCompiledBindings);
+ Q_DECLARE_PRIVATE(QmlCompiledBindings);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLBINDINGOPTIMIZATIONS_P_H
+
diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp
new file mode 100644
index 0000000..48a0893
--- /dev/null
+++ b/src/declarative/qml/qmlcompileddata.cpp
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcompiler_p.h"
+#include "qmlengine.h"
+#include "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+#include "qmlcontext.h"
+#include "qmlcontext_p.h"
+
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+int QmlCompiledData::pack(const char *data, size_t size)
+{
+ const char *p = packData.constData();
+ unsigned int ps = packData.size();
+
+ for (unsigned int ii = 0; (ii + size) <= ps; ii += sizeof(int)) {
+ if (0 == ::memcmp(p + ii, data, size))
+ return ii;
+ }
+
+ int rv = packData.size();
+ packData.append(data, size);
+ return rv;
+}
+
+int QmlCompiledData::indexForString(const QString &data)
+{
+ int idx = primitives.indexOf(data);
+ if (idx == -1) {
+ idx = primitives.count();
+ primitives << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForByteArray(const QByteArray &data)
+{
+ int idx = datas.indexOf(data);
+ if (idx == -1) {
+ idx = datas.count();
+ datas << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForUrl(const QUrl &data)
+{
+ int idx = urls.indexOf(data);
+ if (idx == -1) {
+ idx = urls.count();
+ urls << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForFloat(float *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= floatData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (floatData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = floatData.count();
+ for (int ii = 0; ii < count; ++ii)
+ floatData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForInt(int *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= intData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (intData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = intData.count();
+ for (int ii = 0; ii < count; ++ii)
+ intData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::Location &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l;
+ return rv;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l.start << l.end;
+ return rv;
+}
+
+QmlCompiledData::QmlCompiledData(QmlEngine *engine)
+: QmlCleanup(engine), importCache(0), root(0), rootPropertyCache(0)
+{
+}
+
+QmlCompiledData::~QmlCompiledData()
+{
+ for (int ii = 0; ii < types.count(); ++ii) {
+ if (types.at(ii).ref)
+ types.at(ii).ref->release();
+ }
+
+ for (int ii = 0; ii < propertyCaches.count(); ++ii)
+ propertyCaches.at(ii)->release();
+
+ for (int ii = 0; ii < contextCaches.count(); ++ii)
+ contextCaches.at(ii)->release();
+
+ if (importCache)
+ importCache->release();
+
+ if (rootPropertyCache)
+ rootPropertyCache->release();
+
+ qDeleteAll(cachedPrograms);
+ qDeleteAll(cachedClosures);
+}
+
+void QmlCompiledData::clear()
+{
+ qDeleteAll(cachedPrograms);
+ qDeleteAll(cachedClosures);
+ for (int ii = 0; ii < cachedClosures.count(); ++ii)
+ cachedClosures[ii] = 0;
+ for (int ii = 0; ii < cachedPrograms.count(); ++ii)
+ cachedPrograms[ii] = 0;
+}
+
+
+QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt, const QBitField &bindings) const
+{
+ if (type) {
+ QObject *rv = type->create();
+ if (rv)
+ QmlEngine::setContextForObject(rv, ctxt);
+ return rv;
+ } else {
+ Q_ASSERT(component);
+ return QmlComponentPrivate::get(component)->create(ctxt, bindings);
+ }
+}
+
+const QMetaObject *QmlCompiledData::TypeReference::metaObject() const
+{
+ if (type) {
+ return type->metaObject();
+ } else {
+ Q_ASSERT(component);
+ return static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root;
+ }
+}
+
+void QmlCompiledData::dumpInstructions()
+{
+ if (!name.isEmpty())
+ qWarning() << name;
+ qWarning().nospace() << "Index\tLine\tOperation\t\tData1\tData2\tData3\tComments";
+ qWarning().nospace() << "-------------------------------------------------------------------------------";
+ for (int ii = 0; ii < bytecode.count(); ++ii) {
+ dump(&bytecode[ii], ii);
+ }
+ qWarning().nospace() << "-------------------------------------------------------------------------------";
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
new file mode 100644
index 0000000..10150de
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -0,0 +1,2815 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcompiler_p.h"
+
+#include "qmlcompositetypedata_p.h"
+#include "qmlparser_p.h"
+#include "qmlscriptparser_p.h"
+#include "qmlpropertyvaluesource.h"
+#include "qmlcomponent.h"
+#include "qmetaobjectbuilder_p.h"
+#include "qmlstringconverters_p.h"
+#include "qmlengine_p.h"
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qmlmetatype.h"
+#include "qmlcustomparser_p_p.h"
+#include "qmlcontext_p.h"
+#include "qmlcomponent_p.h"
+#include "parser/qmljsast_p.h"
+#include "qmlvmemetaobject_p.h"
+#include "qmlexpression_p.h"
+#include "qmlmetaproperty_p.h"
+#include "qmlrewrite_p.h"
+#include "qmlscriptstring.h"
+#include "qmlglobal_p.h"
+#include "qmlscriptparser_p.h"
+#include "qmlbinding.h"
+#include "qmlcompiledbindings_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QCoreApplication>
+#include <QColor>
+#include <QDebug>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <QAtomicInt>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
+DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATISTICS_DUMP);
+DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL);
+
+using namespace QmlParser;
+
+/*!
+ Instantiate a new QmlCompiler.
+*/
+QmlCompiler::QmlCompiler()
+: output(0), engine(0), unitRoot(0), unit(0)
+{
+}
+
+/*!
+ Returns true if the last call to compile() caused errors.
+
+ \sa errors()
+*/
+bool QmlCompiler::isError() const
+{
+ return !exceptions.isEmpty();
+}
+
+/*!
+ Return the list of errors from the last call to compile(), or an empty list
+ if there were no errors.
+*/
+QList<QmlError> QmlCompiler::errors() const
+{
+ return exceptions;
+}
+
+/*!
+ Returns true if \a val is a legal object id, false otherwise.
+
+ Legal ids must start with a lower-case letter or underscore, and contain only
+ letters, numbers and underscores.
+*/
+bool QmlCompiler::isValidId(const QString &val)
+{
+ if (val.isEmpty())
+ return false;
+
+ // TODO this will be enforced and return false
+ if (val.at(0).isLetter() && !val.at(0).isLower()) {
+ //return false;
+ qWarning().nospace() << "id '" << val << "' is invalid: ids cannot start with uppercase letters. This will be enforced in an upcoming version of QML.";
+ }
+
+ QChar u(QLatin1Char('_'));
+ for (int ii = 0; ii < val.count(); ++ii)
+ if (val.at(ii) != u &&
+ ((ii == 0 && !val.at(ii).isLetter()) ||
+ (ii != 0 && !val.at(ii).isLetterOrNumber())) )
+ return false;
+
+ return true;
+}
+
+/*!
+ Returns true if \a name refers to an attached property, false otherwise.
+
+ Attached property names are those that start with a capital letter.
+*/
+bool QmlCompiler::isAttachedPropertyName(const QByteArray &name)
+{
+ return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z';
+}
+
+/*!
+ Returns true if \a name refers to a signal property, false otherwise.
+
+ Signal property names are those that start with "on", followed by a capital
+ letter.
+*/
+bool QmlCompiler::isSignalPropertyName(const QByteArray &name)
+{
+ return name.length() >= 3 && name.startsWith("on") &&
+ 'A' <= name.at(2) && 'Z' >= name.at(2);
+}
+
+/*!
+ \macro COMPILE_EXCEPTION
+ \internal
+ Inserts an error into the QmlCompiler error list, and returns false
+ (failure).
+
+ \a token is used to source the error line and column, and \a desc is the
+ error itself. \a desc can be an expression that can be piped into QDebug.
+
+ For example:
+
+ \code
+ COMPILE_EXCEPTION(property, QCoreApplication::translate("QmlCompiler","Error for property \"%1\"").arg(QString::fromUtf8(property->name)));
+ \endcode
+*/
+#define COMPILE_EXCEPTION(token, desc) \
+ { \
+ QString exceptionDescription; \
+ QmlError error; \
+ error.setUrl(output->url); \
+ error.setLine((token)->location.start.line); \
+ error.setColumn((token)->location.start.column); \
+ error.setDescription(desc.trimmed()); \
+ exceptions << error; \
+ return false; \
+ }
+
+/*!
+ \macro COMPILE_CHECK
+ \internal
+ Returns false if \a is false, otherwise does nothing.
+*/
+#define COMPILE_CHECK(a) \
+ { \
+ if (!a) return false; \
+ }
+
+/*!
+ Returns true if literal \a v can be assigned to property \a prop, otherwise
+ false.
+
+ This test corresponds to action taken by genLiteralAssignment(). Any change
+ made here, must have a corresponding action in genLiteralAssigment().
+*/
+bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *v)
+{
+ QString string = v->value.asScript();
+
+ if (!prop.isWritable())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name())));
+
+ if (prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string.toUtf8().constData());
+ } else
+ value = prop.enumerator().keyToValue(string.toUtf8().constData());
+ if (value == -1)
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: unknown enumeration"));
+ return true;
+ }
+ int type = prop.userType();
+ switch(type) {
+ case -1:
+ break;
+ case QVariant::String:
+ if (!v->value.isString()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: string expected"));
+ break;
+ case QVariant::Url:
+ if (!v->value.isString()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: url expected"));
+ break;
+ case QVariant::UInt:
+ {
+ bool ok;
+ string.toUInt(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: unsigned int expected"));
+ }
+ break;
+ case QVariant::Int:
+ {
+ bool ok;
+ string.toInt(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: int expected"));
+ }
+ break;
+ case QMetaType::Float:
+ {
+ bool ok;
+ string.toFloat(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: float expected"));
+ }
+ break;
+ case QVariant::Double:
+ {
+ bool ok;
+ string.toDouble(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: double expected"));
+ }
+ break;
+ case QVariant::Color:
+ {
+ bool ok;
+ QmlStringConverters::colorFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: color expected"));
+ }
+ break;
+ case QVariant::Date:
+ {
+ bool ok;
+ QmlStringConverters::dateFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: date expected"));
+ }
+ break;
+ case QVariant::Time:
+ {
+ bool ok;
+ QmlStringConverters::timeFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: time expected"));
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ bool ok;
+ QmlStringConverters::dateTimeFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: datetime expected"));
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point = QmlStringConverters::pointFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: point expected"));
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: size expected"));
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: rect expected"));
+ }
+ break;
+ case QVariant::Bool:
+ {
+ if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: boolean expected"));
+ }
+ break;
+ case QVariant::Vector3D:
+ {
+ bool ok;
+ QmlStringConverters::vector3DFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: 3D vector expected"));
+ }
+ break;
+ default:
+ {
+ int t = prop.userType();
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(t);
+ if (!converter)
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type()))));
+ }
+ break;
+ }
+ return true;
+}
+
+/*!
+ Generate a store instruction for assigning literal \a v to property \a prop.
+
+ Any literal assignment that is approved in testLiteralAssignment() must have
+ a corresponding action in this method.
+*/
+void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *v)
+{
+ QString string = v->value.asScript();
+
+ QmlInstruction instr;
+ instr.line = v->location.start.line;
+ if (prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string.toUtf8().constData());
+ } else
+ value = prop.enumerator().keyToValue(string.toUtf8().constData());
+
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.value = value;
+ output->bytecode << instr;
+ return;
+ }
+
+ int type = prop.userType();
+ switch(type) {
+ case -1:
+ {
+ instr.type = QmlInstruction::StoreVariant;
+ instr.storeString.propertyIndex = prop.propertyIndex();
+ instr.storeString.value = output->indexForString(string);
+ }
+ break;
+ case QVariant::String:
+ {
+ instr.type = QmlInstruction::StoreString;
+ instr.storeString.propertyIndex = prop.propertyIndex();
+ instr.storeString.value = output->indexForString(string);
+ }
+ break;
+ case QVariant::Url:
+ {
+ instr.type = QmlInstruction::StoreUrl;
+ QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string));
+ instr.storeUrl.propertyIndex = prop.propertyIndex();
+ instr.storeUrl.value = output->indexForUrl(u);
+ }
+ break;
+ case QVariant::UInt:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.value = string.toUInt();
+ }
+ break;
+ case QVariant::Int:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.value = string.toInt();
+ }
+ break;
+ case QMetaType::Float:
+ {
+ instr.type = QmlInstruction::StoreFloat;
+ instr.storeFloat.propertyIndex = prop.propertyIndex();
+ instr.storeFloat.value = string.toFloat();
+ }
+ break;
+ case QVariant::Double:
+ {
+ instr.type = QmlInstruction::StoreDouble;
+ instr.storeDouble.propertyIndex = prop.propertyIndex();
+ instr.storeDouble.value = string.toDouble();
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor c = QmlStringConverters::colorFromString(string);
+ instr.type = QmlInstruction::StoreColor;
+ instr.storeColor.propertyIndex = prop.propertyIndex();
+ instr.storeColor.value = c.rgba();
+ }
+ break;
+ case QVariant::Date:
+ {
+ QDate d = QmlStringConverters::dateFromString(string);
+ instr.type = QmlInstruction::StoreDate;
+ instr.storeDate.propertyIndex = prop.propertyIndex();
+ instr.storeDate.value = d.toJulianDay();
+ }
+ break;
+ case QVariant::Time:
+ {
+ QTime time = QmlStringConverters::timeFromString(string);
+ int data[] = { time.hour(), time.minute(),
+ time.second(), time.msec() };
+ int index = output->indexForInt(data, 4);
+ instr.type = QmlInstruction::StoreTime;
+ instr.storeTime.propertyIndex = prop.propertyIndex();
+ instr.storeTime.valueIndex = index;
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ QDateTime dateTime = QmlStringConverters::dateTimeFromString(string);
+ int data[] = { dateTime.date().toJulianDay(),
+ dateTime.time().hour(),
+ dateTime.time().minute(),
+ dateTime.time().second(),
+ dateTime.time().msec() };
+ int index = output->indexForInt(data, 5);
+ instr.type = QmlInstruction::StoreDateTime;
+ instr.storeDateTime.propertyIndex = prop.propertyIndex();
+ instr.storeDateTime.valueIndex = index;
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point =
+ QmlStringConverters::pointFFromString(string, &ok);
+ float data[] = { point.x(), point.y() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::PointF)
+ instr.type = QmlInstruction::StorePointF;
+ else
+ instr.type = QmlInstruction::StorePoint;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
+ float data[] = { size.width(), size.height() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::SizeF)
+ instr.type = QmlInstruction::StoreSizeF;
+ else
+ instr.type = QmlInstruction::StoreSize;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
+ float data[] = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ int index = output->indexForFloat(data, 4);
+ if (type == QVariant::RectF)
+ instr.type = QmlInstruction::StoreRectF;
+ else
+ instr.type = QmlInstruction::StoreRect;
+ instr.storeRect.propertyIndex = prop.propertyIndex();
+ instr.storeRect.valueIndex = index;
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool b = v->value.asBoolean();
+ instr.type = QmlInstruction::StoreBool;
+ instr.storeBool.propertyIndex = prop.propertyIndex();
+ instr.storeBool.value = b;
+ }
+ break;
+ case QVariant::Vector3D:
+ {
+ bool ok;
+ QVector3D vector =
+ QmlStringConverters::vector3DFromString(string, &ok);
+ float data[] = { vector.x(), vector.y(), vector.z() };
+ int index = output->indexForFloat(data, 3);
+ instr.type = QmlInstruction::StoreVector3D;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ default:
+ {
+ int t = prop.userType();
+ int index = output->customTypeData.count();
+ instr.type = QmlInstruction::AssignCustomType;
+ instr.assignCustomType.propertyIndex = prop.propertyIndex();
+ instr.assignCustomType.valueIndex = index;
+
+ QmlCompiledData::CustomTypeData data;
+ data.index = output->indexForString(string);
+ data.type = t;
+ output->customTypeData << data;
+ }
+ break;
+ }
+ output->bytecode << instr;
+}
+
+/*!
+ Resets data by clearing the lists that the QmlCompiler modifies.
+*/
+void QmlCompiler::reset(QmlCompiledData *data)
+{
+ data->types.clear();
+ data->primitives.clear();
+ data->floatData.clear();
+ data->intData.clear();
+ data->customTypeData.clear();
+ data->datas.clear();
+ data->bytecode.clear();
+}
+
+/*!
+ Compile \a unit, and store the output in \a out. \a engine is the QmlEngine
+ with which the QmlCompiledData will be associated.
+
+ Returns true on success, false on failure. On failure, the compile errors
+ are available from errors().
+
+ If the environment variant QML_COMPILER_DUMP is set
+ (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr
+ on a successful compiler.
+*/
+bool QmlCompiler::compile(QmlEngine *engine,
+ QmlCompositeTypeData *unit,
+ QmlCompiledData *out)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::Compilation> pc;
+#endif
+ exceptions.clear();
+
+ Q_ASSERT(out);
+ reset(out);
+
+ output = out;
+
+ // Compile types
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData::TypeReference &tref = unit->types[ii];
+ QmlCompiledData::TypeReference ref;
+ QmlScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii);
+ if (tref.type)
+ ref.type = tref.type;
+ else if (tref.unit) {
+ ref.component = tref.unit->toComponent(engine);
+
+ if (ref.component->isError()) {
+ QmlError error;
+ error.setUrl(output->url);
+ error.setDescription(QLatin1String("Unable to create type ") +
+ parserRef->name);
+ if (!parserRef->refObjects.isEmpty()) {
+ QmlParser::Object *parserObject = parserRef->refObjects.first();
+ error.setLine(parserObject->location.start.line);
+ error.setColumn(parserObject->location.start.column);
+ }
+
+ exceptions << error;
+ exceptions << ref.component->errors();
+ reset(out);
+ return false;
+ }
+ ref.ref = tref.unit;
+ ref.ref->addref();
+ }
+ ref.className = parserRef->name.toUtf8();
+ out->types << ref;
+ }
+
+ Object *root = unit->data.tree();
+ Q_ASSERT(root);
+
+ this->engine = engine;
+ this->unit = unit;
+ this->unitRoot = root;
+ compileTree(root);
+
+ if (!isError()) {
+ if (compilerDump())
+ out->dumpInstructions();
+ if (compilerStatDump())
+ dumpStats();
+ } else {
+ reset(out);
+ }
+
+ compileState = ComponentCompileState();
+ savedCompileStates.clear();
+ output = 0;
+ this->engine = 0;
+ this->unit = 0;
+ this->unitRoot = 0;
+
+ return !isError();
+}
+
+void QmlCompiler::compileTree(Object *tree)
+{
+ compileState.root = tree;
+
+ if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
+ return;
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.line = 0;
+ init.init.bindingsSize = compileState.bindings.count();
+ init.init.parserStatusSize = compileState.parserStatusCount;
+ init.init.contextCache = genContextCache();
+ if (compileState.compiledBindingData.isEmpty())
+ init.init.compiledBinding = -1;
+ else
+ init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
+ output->bytecode << init;
+
+ genObject(tree);
+
+ QmlInstruction def;
+ init.line = 0;
+ def.type = QmlInstruction::SetDefault;
+ output->bytecode << def;
+
+ output->imports = unit->imports;
+ output->importCache = output->imports.cache(engine);
+
+ Q_ASSERT(tree->metatype);
+
+ if (tree->metadata.isEmpty()) {
+ output->root = tree->metatype;
+ } else {
+ static_cast<QMetaObject &>(output->rootData) = *tree->metaObject();
+ output->root = &output->rootData;
+ }
+ if (!tree->metadata.isEmpty())
+ QmlEnginePrivate::get(engine)->registerCompositeType(output);
+}
+
+static bool ValuePtrLessThan(const Value *t1, const Value *t2)
+{
+ return t1->location.start.line < t2->location.start.line ||
+ (t1->location.start.line == t2->location.start.line &&
+ t1->location.start.column < t2->location.start.column);
+}
+
+bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
+{
+ componentStat.objects++;
+
+ Q_ASSERT (obj->type != -1);
+ const QmlCompiledData::TypeReference &tr =
+ output->types.at(obj->type);
+ obj->metatype = tr.metaObject();
+
+ if (tr.component)
+ obj->url = tr.component->url();
+ if (tr.type)
+ obj->typeName = tr.type->qmlTypeName();
+ obj->className = tr.className;
+
+ // This object is a "Component" element
+ if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) {
+ COMPILE_CHECK(buildComponent(obj, ctxt));
+ return true;
+ }
+
+ // Build any script blocks for this type
+ for (int ii = 0; ii < obj->scriptBlockObjects.count(); ++ii)
+ COMPILE_CHECK(buildScript(obj, obj->scriptBlockObjects.at(ii)));
+
+ // Object instantiations reset the binding context
+ BindingContext objCtxt(obj);
+
+ // Create the synthesized meta object, ignoring aliases
+ COMPILE_CHECK(mergeDynamicMetaProperties(obj));
+ COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases));
+
+ // Find the native type and check for the QmlParserStatus interface
+ QmlType *type = toQmlType(obj);
+ Q_ASSERT(type);
+ obj->parserStatusCast = type->parserStatusCast();
+ if (obj->parserStatusCast != -1)
+ compileState.parserStatusCount++;
+
+ // Check if this is a custom parser type. Custom parser types allow
+ // assignments to non-existant properties. These assignments are then
+ // compiled by the type.
+ bool isCustomParser = output->types.at(obj->type).type &&
+ output->types.at(obj->type).type->customParser() != 0;
+ QList<QmlCustomParserProperty> customProps;
+
+ // Fetch the list of deferred properties
+ QStringList deferredList = deferredProperties(obj);
+
+ // Must do id property first. This is to ensure that the id given to any
+ // id reference created matches the order in which the objects are
+ // instantiated
+ foreach(Property *prop, obj->properties) {
+ if (prop->name == "id") {
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ break;
+ }
+ }
+
+ // Merge
+ Property *defaultProperty = 0;
+ Property *skipProperty = 0;
+ if (obj->defaultProperty) {
+ const QMetaObject *metaObject = obj->metaObject();
+ Q_ASSERT(metaObject);
+ QMetaProperty p = QmlMetaType::defaultProperty(metaObject);
+ if (p.name()) {
+ Property *explicitProperty = obj->getProperty(p.name(), false);
+ if (explicitProperty && !explicitProperty->value) {
+ skipProperty = explicitProperty;
+
+ defaultProperty = new Property;
+ defaultProperty->parent = obj;
+ defaultProperty->isDefault = true;
+ defaultProperty->location = obj->defaultProperty->location;
+ defaultProperty->listValueRange = obj->defaultProperty->listValueRange;
+ defaultProperty->listCommaPositions = obj->defaultProperty->listCommaPositions;
+
+ defaultProperty->values = obj->defaultProperty->values;
+ defaultProperty->values += explicitProperty->values;
+ foreach(Value *value, defaultProperty->values)
+ value->addref();
+ qSort(defaultProperty->values.begin(), defaultProperty->values.end(), ValuePtrLessThan);
+
+ } else {
+ defaultProperty = obj->defaultProperty;
+ defaultProperty->addref();
+ }
+ } else {
+ defaultProperty = obj->defaultProperty;
+ defaultProperty->addref();
+ }
+ }
+
+ // Build all explicit properties specified
+ foreach(Property *prop, obj->properties) {
+
+ if (prop == skipProperty)
+ continue;
+ if (prop->name == "id")
+ continue;
+
+ bool canDefer = false;
+ if (isCustomParser) {
+ if (doesPropertyExist(prop, obj)) {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ } else {
+ if (isSignalPropertyName(prop->name)) {
+ COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
+ } else {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ }
+ }
+
+ if (canDefer && !deferredList.isEmpty() &&
+ deferredList.contains(QString::fromUtf8(prop->name)))
+ prop->isDeferred = true;
+
+ }
+
+ // Build the default property
+ if (defaultProperty) {
+ Property *prop = defaultProperty;
+
+ bool canDefer = false;
+ if (isCustomParser) {
+ if (doesPropertyExist(prop, obj)) {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ } else {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ }
+
+ if (canDefer && !deferredList.isEmpty() &&
+ deferredList.contains(QString::fromUtf8(prop->name)))
+ prop->isDeferred = true;
+ }
+
+ if (defaultProperty)
+ defaultProperty->release();
+
+ // Compile custom parser parts
+ if (isCustomParser && !customProps.isEmpty()) {
+ QmlCustomParser *cp = output->types.at(obj->type).type->customParser();
+ cp->clearErrors();
+ obj->custom = cp->compile(customProps);
+ foreach (QmlError err, cp->errors()) {
+ err.setUrl(output->url);
+ exceptions << err;
+ }
+ }
+
+ return true;
+}
+
+void QmlCompiler::genObject(QmlParser::Object *obj)
+{
+ const QmlCompiledData::TypeReference &tr =
+ output->types.at(obj->type);
+ if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) {
+ genComponent(obj);
+ return;
+ }
+
+ // Create the object
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateObject;
+ create.line = obj->location.start.line;
+ create.create.column = obj->location.start.column;
+ create.create.data = -1;
+ if (!obj->custom.isEmpty())
+ create.create.data = output->indexForByteArray(obj->custom);
+ create.create.type = obj->type;
+ if (!output->types.at(create.create.type).type &&
+ !obj->bindingBitmask.isEmpty()) {
+ Q_ASSERT(obj->bindingBitmask.size() % 4 == 0);
+ create.create.bindingBits =
+ output->indexForByteArray(obj->bindingBitmask);
+ } else {
+ create.create.bindingBits = -1;
+ }
+ output->bytecode << create;
+
+ // Setup the synthesized meta object if necessary
+ if (!obj->metadata.isEmpty()) {
+ QmlInstruction meta;
+ meta.type = QmlInstruction::StoreMetaObject;
+ meta.line = 0;
+ meta.storeMeta.data = output->indexForByteArray(obj->metadata);
+ meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata);
+ meta.storeMeta.propertyCache = output->propertyCaches.count();
+ // ### Surely the creation of this property cache could be more efficient
+ QmlPropertyCache *propertyCache = 0;
+ if (tr.component && QmlComponentPrivate::get(tr.component)->cc->rootPropertyCache) {
+ propertyCache = QmlComponentPrivate::get(tr.component)->cc->rootPropertyCache->copy();
+ } else {
+ propertyCache = QmlPropertyCache::create(engine, obj->metaObject()->superClass());
+ }
+ propertyCache->append(engine, obj->metaObject(), QmlPropertyCache::Data::NoFlags,
+ QmlPropertyCache::Data::IsVMEFunction);
+ if (obj == unitRoot) {
+ propertyCache->addref();
+ output->rootPropertyCache = propertyCache;
+ }
+ output->propertyCaches << propertyCache;
+ output->bytecode << meta;
+ }
+
+ // Set the object id
+ if (!obj->id.isEmpty()) {
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = 0;
+ id.setId.value = output->indexForString(obj->id);
+ id.setId.index = obj->idIndex;
+ output->bytecode << id;
+ }
+
+ // Set any script blocks
+ for (int ii = 0; ii < obj->scripts.count(); ++ii) {
+ QmlInstruction script;
+ script.type = QmlInstruction::StoreScript;
+ script.line = 0; // ###
+ int idx = output->scripts.count();
+ output->scripts << obj->scripts.at(ii);
+ script.storeScript.value = idx;
+ output->bytecode << script;
+ }
+
+ // Begin the class
+ if (obj->parserStatusCast != -1) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::BeginObject;
+ begin.begin.castValue = obj->parserStatusCast;
+ begin.line = obj->location.start.line;
+ output->bytecode << begin;
+ }
+
+ genObjectBody(obj);
+}
+
+void QmlCompiler::genObjectBody(QmlParser::Object *obj)
+{
+ typedef QPair<Property *, int> PropPair;
+ foreach(const PropPair &prop, obj->scriptStringProperties) {
+ QmlInstruction ss;
+ ss.type = QmlInstruction::StoreScriptString;
+ ss.storeScriptString.propertyIndex = prop.first->index;
+ ss.storeScriptString.value =
+ output->indexForString(prop.first->values.at(0)->value.asScript());
+ ss.storeScriptString.scope = prop.second;
+ output->bytecode << ss;
+ }
+
+ bool seenDefer = false;
+ foreach(Property *prop, obj->valueProperties) {
+ if (prop->isDeferred) {
+ seenDefer = true;
+ continue;
+ }
+ genValueProperty(prop, obj);
+ }
+ if (seenDefer) {
+ QmlInstruction defer;
+ defer.type = QmlInstruction::Defer;
+ defer.line = 0;
+ defer.defer.deferCount = 0;
+ int deferIdx = output->bytecode.count();
+ output->bytecode << defer;
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.init.bindingsSize = compileState.bindings.count(); // XXX - bigger than necessary
+ init.init.parserStatusSize = compileState.parserStatusCount; // XXX - bigger than necessary
+ init.init.contextCache = -1;
+ init.init.compiledBinding = -1;
+ output->bytecode << init;
+
+ foreach(Property *prop, obj->valueProperties) {
+ if (!prop->isDeferred)
+ continue;
+ genValueProperty(prop, obj);
+ }
+
+ output->bytecode[deferIdx].defer.deferCount =
+ output->bytecode.count() - deferIdx - 1;
+ }
+
+ foreach(Property *prop, obj->signalProperties) {
+
+ QmlParser::Value *v = prop->values.at(0);
+
+ if (v->type == Value::SignalObject) {
+
+ genObject(v->object);
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignalObject;
+ assign.line = v->location.start.line;
+ assign.assignSignalObject.signal =
+ output->indexForByteArray(prop->name);
+ output->bytecode << assign;
+
+ } else if (v->type == Value::SignalExpression) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreSignal;
+ store.line = v->location.start.line;
+ store.storeSignal.signalIndex = prop->index;
+ store.storeSignal.value =
+ output->indexForString(v->value.asScript().trimmed());
+ output->bytecode << store;
+
+ }
+
+ }
+
+ foreach(Property *prop, obj->attachedProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchAttached;
+ fetch.line = prop->location.start.line;
+ fetch.fetchAttached.id = prop->index;
+ output->bytecode << fetch;
+
+ genObjectBody(prop->value);
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+
+ foreach(Property *prop, obj->groupedProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchObject;
+ fetch.fetch.property = prop->index;
+ fetch.line = prop->location.start.line;
+ output->bytecode << fetch;
+
+ genObjectBody(prop->value);
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+
+ foreach(Property *prop, obj->valueTypeProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchValueType;
+ fetch.fetchValue.property = prop->index;
+ fetch.fetchValue.type = prop->type;
+ fetch.line = prop->location.start.line;
+
+ output->bytecode << fetch;
+
+ foreach(Property *vprop, prop->value->valueProperties) {
+ genPropertyAssignment(vprop, prop->value, prop);
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopValueType;
+ pop.fetchValue.property = prop->index;
+ pop.fetchValue.type = prop->type;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+}
+
+void QmlCompiler::genComponent(QmlParser::Object *obj)
+{
+ QmlParser::Object *root = obj->defaultProperty->values.at(0)->object;
+ Q_ASSERT(root);
+
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateComponent;
+ create.line = root->location.start.line;
+ create.createComponent.column = root->location.start.column;
+ create.createComponent.endLine = root->location.end.line;
+ output->bytecode << create;
+ int count = output->bytecode.count();
+
+ ComponentCompileState oldCompileState = compileState;
+ compileState = componentState(root);
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.init.bindingsSize = compileState.bindings.count();
+ init.init.parserStatusSize = compileState.parserStatusCount;
+ init.init.contextCache = genContextCache();
+ if (compileState.compiledBindingData.isEmpty())
+ init.init.compiledBinding = -1;
+ else
+ init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
+ init.line = obj->location.start.line;
+ output->bytecode << init;
+
+ genObject(root);
+
+ QmlInstruction def;
+ init.line = 0;
+ def.type = QmlInstruction::SetDefault;
+ output->bytecode << def;
+
+ output->bytecode[count - 1].createComponent.count =
+ output->bytecode.count() - count;
+
+ compileState = oldCompileState;
+
+ if (!obj->id.isEmpty()) {
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = 0;
+ id.setId.value = output->indexForString(obj->id);
+ id.setId.index = obj->idIndex;
+ output->bytecode << id;
+ }
+}
+
+bool QmlCompiler::buildComponent(QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ // The special "Component" element can only have the id property and a
+ // default property, that actually defines the component's tree
+
+ // Find, check and set the "id" property (if any)
+ Property *idProp = 0;
+ if (obj->properties.count() > 1 ||
+ (obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
+ COMPILE_EXCEPTION(*obj->properties.begin(), QCoreApplication::translate("QmlCompiler","Invalid component specification"));
+
+ if (!obj->scriptBlockObjects.isEmpty())
+ COMPILE_EXCEPTION(obj->scriptBlockObjects.first(), QCoreApplication::translate("QmlCompiler","Invalid component specification"));
+
+ if (obj->properties.count())
+ idProp = *obj->properties.begin();
+
+ if (idProp && (idProp->value || idProp->values.count() > 1 || !isValidId(idProp->values.first()->primitive())))
+ COMPILE_EXCEPTION(idProp, QCoreApplication::translate("QmlCompiler","Invalid component id specification"));
+
+ if (idProp) {
+ QString idVal = idProp->values.first()->primitive();
+
+ if (compileState.ids.contains(idVal))
+ COMPILE_EXCEPTION(idProp, QCoreApplication::translate("QmlCompiler","id is not unique"));
+
+ obj->id = idVal;
+ addId(idVal, obj);
+ }
+
+ // Check the Component tree is well formed
+ if (obj->defaultProperty &&
+ (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 ||
+ (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object)))
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QmlCompiler","Invalid component body specification"));
+
+ Object *root = 0;
+ if (obj->defaultProperty && obj->defaultProperty->values.count())
+ root = obj->defaultProperty->values.first()->object;
+
+ if (!root)
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QmlCompiler","Cannot create empty component specification"));
+
+ // Build the component tree
+ COMPILE_CHECK(buildComponentFromRoot(root, ctxt));
+
+ return true;
+}
+
+bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
+{
+ Object::ScriptBlock scriptBlock;
+
+ if (script->properties.count() == 1 &&
+ script->properties.begin().key() == QByteArray("source")) {
+
+ Property *source = *script->properties.begin();
+ if (script->defaultProperty)
+ COMPILE_EXCEPTION(source, QCoreApplication::translate("QmlCompiler","Invalid Script block. Specify either the source property or inline script"));
+
+ if (source->value || source->values.count() != 1 ||
+ source->values.at(0)->object || !source->values.at(0)->value.isStringList())
+ COMPILE_EXCEPTION(source, QCoreApplication::translate("QmlCompiler","Invalid Script source value"));
+
+ QStringList sources = source->values.at(0)->value.asStringList();
+
+ for (int jj = 0; jj < sources.count(); ++jj) {
+ QString sourceUrl = output->url.resolved(QUrl(sources.at(jj))).toString();
+ QString scriptCode;
+ int lineNumber = 1;
+
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ if (unit->resources.at(ii)->url == sourceUrl) {
+ scriptCode = QString::fromUtf8(unit->resources.at(ii)->data);
+ break;
+ }
+ }
+
+ if (!scriptCode.isEmpty()) {
+ scriptBlock.codes.append(scriptCode);
+ scriptBlock.files.append(sourceUrl);
+ scriptBlock.lineNumbers.append(lineNumber);
+ }
+ }
+
+ } else if (!script->properties.isEmpty()) {
+ COMPILE_EXCEPTION(*script->properties.begin(), QCoreApplication::translate("QmlCompiler","Properties cannot be set on Script block"));
+ } else if (script->defaultProperty) {
+
+ QString scriptCode;
+ int lineNumber = 1;
+ QString sourceUrl = output->url.toString();
+
+ QmlParser::Location currentLocation;
+
+ for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) {
+ Value *v = script->defaultProperty->values.at(ii);
+ if (lineNumber == 1)
+ lineNumber = v->location.start.line;
+ if (v->object || !v->value.isString())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid Script block"));
+
+ if (ii == 0) {
+ currentLocation = v->location.start;
+ scriptCode.append(QString(currentLocation.column, QLatin1Char(' ')));
+ }
+
+ while (currentLocation.line < v->location.start.line) {
+ scriptCode.append(QLatin1Char('\n'));
+ currentLocation.line++;
+ currentLocation.column = 0;
+ }
+
+ scriptCode.append(QString(v->location.start.column - currentLocation.column, QLatin1Char(' ')));
+
+ scriptCode += v->value.asString();
+ currentLocation = v->location.end;
+ currentLocation.column++;
+ }
+
+ if (!scriptCode.isEmpty()) {
+ scriptBlock.codes.append(scriptCode);
+ scriptBlock.files.append(sourceUrl);
+ scriptBlock.lineNumbers.append(lineNumber);
+ }
+ }
+
+ if (!scriptBlock.codes.isEmpty())
+ obj->scripts << scriptBlock;
+
+ return true;
+}
+
+bool QmlCompiler::buildComponentFromRoot(QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ ComponentCompileState oldComponentCompileState = compileState;
+ ComponentStat oldComponentStat = componentStat;
+
+ compileState = ComponentCompileState();
+ compileState.root = obj;
+
+ componentStat = ComponentStat();
+ componentStat.lineNumber = obj->location.start.line;
+
+ if (obj)
+ COMPILE_CHECK(buildObject(obj, ctxt));
+
+ COMPILE_CHECK(completeComponentBuild());
+
+ compileState = oldComponentCompileState;
+ componentStat = oldComponentStat;
+
+ return true;
+}
+
+
+// Build a sub-object. A sub-object is one that was not created directly by
+// QML - such as a grouped property object, or an attached object. Sub-object's
+// can't have an id, involve a custom parser, have attached properties etc.
+bool QmlCompiler::buildSubObject(Object *obj, const BindingContext &ctxt)
+{
+ Q_ASSERT(obj->metatype);
+ Q_ASSERT(!obj->defaultProperty);
+ Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding
+ // sub-context
+
+ foreach(Property *prop, obj->properties) {
+ if (isSignalPropertyName(prop->name)) {
+ COMPILE_CHECK(buildSignal(prop, obj, ctxt));
+ } else {
+ COMPILE_CHECK(buildProperty(prop, obj, ctxt));
+ }
+ }
+
+ return true;
+}
+
+int QmlCompiler::componentTypeRef()
+{
+ QmlType *t = QmlMetaType::qmlType("Qt/Component",4,6);
+ for (int ii = output->types.count() - 1; ii >= 0; --ii) {
+ if (output->types.at(ii).type == t)
+ return ii;
+ }
+ QmlCompiledData::TypeReference ref;
+ ref.className = "Component";
+ ref.type = t;
+ output->types << ref;
+ return output->types.count() - 1;
+}
+
+int QmlCompiler::findSignalByName(const QMetaObject *mo, const QByteArray &name)
+{
+ int methods = mo->methodCount();
+ for (int ii = methods - 1; ii >= 0; --ii) {
+ QMetaMethod method = mo->method(ii);
+ QByteArray methodName = method.signature();
+ int idx = methodName.indexOf('(');
+ methodName = methodName.left(idx);
+
+ if (methodName == name)
+ return ii;
+ }
+ return -1;
+}
+
+bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(obj->metaObject());
+ Q_ASSERT(!prop->isEmpty());
+
+ QByteArray name = prop->name;
+ Q_ASSERT(name.startsWith("on"));
+ name = name.mid(2);
+ if(name[0] >= 'A' && name[0] <= 'Z')
+ name[0] = name[0] - 'A' + 'a';
+
+ int sigIdx = findSignalByName(obj->metaObject(), name);
+
+ if (sigIdx == -1) {
+
+ // If the "on<Signal>" name doesn't resolve into a signal, try it as a
+ // property.
+ COMPILE_CHECK(buildProperty(prop, obj, ctxt));
+
+ } else {
+
+ if (prop->value || prop->values.count() > 1)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Incorrectly specified signal"));
+
+ prop->index = sigIdx;
+ obj->addSignalProperty(prop);
+
+ if (prop->values.at(0)->object) {
+ COMPILE_CHECK(buildObject(prop->values.at(0)->object, ctxt));
+ prop->values.at(0)->type = Value::SignalObject;
+ } else {
+ prop->values.at(0)->type = Value::SignalExpression;
+
+ QString script = prop->values.at(0)->value.asScript().trimmed();
+ if (script.isEmpty())
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Empty signal assignment"));
+ }
+ }
+
+ return true;
+}
+
+
+/*!
+ Returns true if (value) property \a prop exists on obj, false otherwise.
+*/
+bool QmlCompiler::doesPropertyExist(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if(isAttachedPropertyName(prop->name) || prop->name == "id")
+ return true;
+
+ const QMetaObject *mo = obj->metaObject();
+ if (mo) {
+ if (prop->isDefault) {
+ QMetaProperty p = QmlMetaType::defaultProperty(mo);
+ return p.name() != 0;
+ } else {
+ int idx = mo->indexOfProperty(prop->name.constData());
+ return idx != -1;
+ }
+ }
+
+ return false;
+}
+
+bool QmlCompiler::buildProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ if (prop->isEmpty())
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Empty property assignment"));
+
+ const QMetaObject *metaObject = obj->metaObject();
+ Q_ASSERT(metaObject);
+
+ if (isAttachedPropertyName(prop->name)) {
+ // Setup attached property data
+
+ if (ctxt.isSubContext()) {
+ // Attached properties cannot be used on sub-objects. Sub-objects
+ // always exist in a binding sub-context, which is what we test
+ // for here.
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Attached properties cannot be used here"));
+ }
+
+ QmlType *type = 0;
+ QmlEnginePrivate::ImportedNamespace *typeNamespace = 0;
+ QmlEnginePrivate::get(engine)->resolveType(unit->imports, prop->name,
+ &type, 0, 0, 0, &typeNamespace);
+
+ if (typeNamespace) {
+ // ### We might need to indicate that this property is a namespace
+ // for the DOM API
+ COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj,
+ ctxt));
+ return true;
+ } else if (!type || !type->attachedPropertiesType()) {
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Non-existant attached object"));
+ }
+
+ if (!prop->value)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Invalid attached object assignment"));
+
+ Q_ASSERT(type->attachedPropertiesFunction());
+ prop->index = type->index();
+ prop->value->metatype = type->attachedPropertiesType();
+ } else {
+ // Setup regular property data
+ QMetaProperty p;
+
+ if (prop->isDefault) {
+ p = QmlMetaType::defaultProperty(metaObject);
+
+ if (p.name()) {
+ prop->index = p.propertyIndex();
+ prop->name = p.name();
+ }
+
+ } else {
+ prop->index = metaObject->indexOfProperty(prop->name.constData());
+
+ if (prop->index != -1) {
+ p = metaObject->property(prop->index);
+ Q_ASSERT(p.name());
+ }
+ }
+
+ // We can't error here as the "id" property does not require a
+ // successful index resolution
+ if (p.name()) {
+ prop->type = p.userType();
+ }
+ }
+
+ if (prop->index != -1)
+ prop->parent->setBindingBit(prop->index);
+
+ if (!prop->isDefault && prop->name == "id" && !ctxt.isSubContext()) {
+
+ // The magic "id" behavior doesn't apply when "id" is resolved as a
+ // default property or to sub-objects (which are always in binding
+ // sub-contexts)
+ COMPILE_CHECK(buildIdProperty(prop, obj));
+ if (prop->type == QVariant::String &&
+ prop->values.at(0)->value.isString())
+ COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
+
+ } else if (isAttachedPropertyName(prop->name)) {
+
+ COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
+
+ } else if (prop->index == -1) {
+
+ if (prop->isDefault) {
+ COMPILE_EXCEPTION(prop->values.first(), QCoreApplication::translate("QmlCompiler","Cannot assign to non-existant default property"));
+ } else {
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name)));
+ }
+
+ } else if (prop->value) {
+
+ COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt));
+
+ } else if (QmlEnginePrivate::get(engine)->isQmlList(prop->type) ||
+ QmlMetaType::isList(prop->type)) {
+
+ COMPILE_CHECK(buildListProperty(prop, obj, ctxt));
+
+ } else if (prop->type == qMetaTypeId<QmlScriptString>()) {
+
+ COMPILE_CHECK(buildScriptStringProperty(prop, obj, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
+
+ }
+
+ return true;
+}
+
+bool
+QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns,
+ QmlParser::Property *nsProp,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ if (!nsProp->value)
+ COMPILE_EXCEPTION(nsProp, QCoreApplication::translate("QmlCompiler","Invalid use of namespace"));
+
+ foreach (Property *prop, nsProp->value->properties) {
+
+ if (!isAttachedPropertyName(prop->name))
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Not an attached property name"));
+
+ // Setup attached property data
+
+ QmlType *type = 0;
+ QmlEnginePrivate::get(engine)->resolveTypeInNamespace(ns, prop->name,
+ &type, 0, 0, 0);
+
+ if (!type || !type->attachedPropertiesType())
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Non-existant attached object"));
+
+ if (!prop->value)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Invalid attached object assignment"));
+
+ Q_ASSERT(type->attachedPropertiesFunction());
+ prop->index = type->index();
+ prop->value->metatype = type->attachedPropertiesType();
+
+ COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
+ }
+
+ return true;
+}
+
+void QmlCompiler::genValueProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if (QmlEnginePrivate::get(engine)->isQmlList(prop->type) ||
+ QmlMetaType::isList(prop->type)) {
+ genListProperty(prop, obj);
+ } else {
+ genPropertyAssignment(prop, obj);
+ }
+}
+
+void QmlCompiler::genListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ QmlInstruction::Type fetchType;
+ QmlInstruction::Type storeType;
+ int listType;
+
+ if (QmlEnginePrivate::get(engine)->isQmlList(prop->type)) {
+ fetchType = QmlInstruction::FetchQmlList;
+ storeType = QmlInstruction::StoreObjectQmlList;
+ listType = QmlEnginePrivate::get(engine)->qmlListType(prop->type);
+ } else {
+ fetchType = QmlInstruction::FetchQList;
+ storeType = QmlInstruction::StoreObjectQList;
+ listType = QmlMetaType::listType(prop->type);
+ }
+
+ QmlInstruction fetch;
+ fetch.type = fetchType;
+ fetch.line = prop->location.start.line;
+ fetch.fetchQmlList.property = prop->index;
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+ fetch.fetchQmlList.type = listType;
+ output->bytecode << fetch;
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+
+ if (v->type == Value::CreatedObject) {
+
+ genObject(v->object);
+ if (listTypeIsInterface) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = prop->location.start.line;
+ output->bytecode << assign;
+ } else {
+ QmlInstruction store;
+ store.type = storeType;
+ store.line = prop->location.start.line;
+ output->bytecode << store;
+ }
+
+ } else if (v->type == Value::PropertyBinding) {
+
+ genBindingAssignment(v, prop, obj);
+
+ }
+
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopQList;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+}
+
+void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty)
+{
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ QmlParser::Value *v = prop->values.at(ii);
+
+ if (v->type == Value::CreatedObject) {
+
+ genObject(v->object);
+
+ if (QmlMetaType::isInterface(prop->type)) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreInterface;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ } else if (prop->type == -1) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreVariantObject;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ } else {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreObject;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ }
+ } else if (v->type == Value::ValueSource) {
+ genObject(v->object);
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreValueSource;
+ store.line = v->object->location.start.line;
+ if (valueTypeProperty) {
+ store.assignValueSource.property = genValueTypeData(prop, valueTypeProperty);
+ store.assignValueSource.owner = 1;
+ } else {
+ store.assignValueSource.property = genPropertyData(prop);
+ store.assignValueSource.owner = 0;
+ }
+ QmlType *valueType = toQmlType(v->object);
+ store.assignValueSource.castValue = valueType->propertyValueSourceCast();
+ output->bytecode << store;
+
+ } else if (v->type == Value::ValueInterceptor) {
+ genObject(v->object);
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreValueInterceptor;
+ store.line = v->object->location.start.line;
+ if (valueTypeProperty) {
+ store.assignValueInterceptor.property = genValueTypeData(prop, valueTypeProperty);
+ store.assignValueInterceptor.owner = 1;
+ } else {
+ store.assignValueInterceptor.property = genPropertyData(prop);
+ store.assignValueInterceptor.owner = 0;
+ }
+ QmlType *valueType = toQmlType(v->object);
+ store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast();
+ output->bytecode << store;
+
+ } else if (v->type == Value::PropertyBinding) {
+
+ genBindingAssignment(v, prop, obj, valueTypeProperty);
+
+ } else if (v->type == Value::Literal) {
+
+ QMetaProperty mp = obj->metaObject()->property(prop->index);
+ genLiteralAssignment(mp, v);
+
+ }
+
+ }
+}
+
+bool QmlCompiler::buildIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if (prop->value ||
+ prop->values.count() > 1 ||
+ prop->values.at(0)->object)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Invalid use of id property"));
+
+ QmlParser::Value *idValue = prop->values.at(0);
+ QString val = idValue->primitive();
+
+ if (!isValidId(val))
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","\"%1\" is not a valid object id").arg(val));
+
+ // We disallow id's that conflict with import prefixes and types
+ QmlEnginePrivate::ImportedNamespace *ns = 0;
+ QmlType *type = 0;
+ QmlEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(),
+ &type, 0, 0, 0, &ns);
+ if (type)
+ COMPILE_EXCEPTION(idValue, QCoreApplication::translate("QmlCompiler","id conflicts with type name"));
+ if (ns)
+ COMPILE_EXCEPTION(idValue, QCoreApplication::translate("QmlCompiler","id conflicts with namespace prefix"));
+
+ if (compileState.ids.contains(val))
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","id is not unique"));
+
+ prop->values.at(0)->type = Value::Id;
+
+ obj->id = val;
+ addId(val, obj);
+
+ return true;
+}
+
+void QmlCompiler::addId(const QString &id, QmlParser::Object *obj)
+{
+ Q_ASSERT(!compileState.ids.contains(id));
+ Q_ASSERT(obj->id == id);
+ obj->idIndex = compileState.ids.count();
+ compileState.ids.insert(id, obj);
+ compileState.idIndexes.insert(obj->idIndex, obj);
+}
+
+void QmlCompiler::addBindingReference(const BindingReference &ref)
+{
+ Q_ASSERT(ref.value && !compileState.bindings.contains(ref.value));
+ compileState.bindings.insert(ref.value, ref);
+}
+
+void QmlCompiler::saveComponentState()
+{
+ Q_ASSERT(compileState.root);
+ Q_ASSERT(!savedCompileStates.contains(compileState.root));
+
+ savedCompileStates.insert(compileState.root, compileState);
+ savedComponentStats.append(componentStat);
+}
+
+QmlCompiler::ComponentCompileState
+QmlCompiler::componentState(QmlParser::Object *obj)
+{
+ Q_ASSERT(savedCompileStates.contains(obj));
+ return savedCompileStates.value(obj);
+}
+
+// Build attached property object. In this example,
+// Text {
+// GridView.row: 10
+// }
+// GridView is an attached property object.
+bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->value);
+ Q_ASSERT(prop->index != -1); // This is set in buildProperty()
+
+ obj->addAttachedProperty(prop);
+
+ COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
+
+ return true;
+}
+
+
+// Build "grouped" properties. In this example:
+// Text {
+// font.pointSize: 12
+// font.family: "Helvetica"
+// }
+// font is a nested property. pointSize and family are not.
+bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->type != 0);
+ Q_ASSERT(prop->index != -1);
+
+ if (prop->values.count())
+ COMPILE_EXCEPTION(prop->values.first(), QCoreApplication::translate("QmlCompiler", "Invalid value in grouped property"));
+
+ if (prop->type < (int)QVariant::UserType) {
+ QmlEnginePrivate *ep =
+ static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
+ if (prop->type >= 0 /* QVariant == -1 */ && ep->valueTypes[prop->type]) {
+ COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type],
+ prop->value, obj, ctxt.incr()));
+ obj->addValueTypeProperty(prop);
+ } else {
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Invalid grouped property access"));
+ }
+
+ } else {
+ // Load the nested property's meta type
+ prop->value->metatype =
+ QmlEnginePrivate::get(engine)->metaObjectForType(prop->type);
+ if (!prop->value->metatype)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Invalid grouped property access"));
+
+ obj->addGroupedProperty(prop);
+
+ COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
+ }
+
+ return true;
+}
+
+bool QmlCompiler::buildValueTypeProperty(QObject *type,
+ QmlParser::Object *obj,
+ QmlParser::Object *baseObj,
+ const BindingContext &ctxt)
+{
+ if (obj->defaultProperty)
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QmlCompiler","Invalid property use"));
+ obj->metatype = type->metaObject();
+
+ foreach (Property *prop, obj->properties) {
+ int idx = type->metaObject()->indexOfProperty(prop->name.constData());
+ if (idx == -1)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name)));
+ QMetaProperty p = type->metaObject()->property(idx);
+ prop->index = idx;
+ prop->type = p.userType();
+
+ if (prop->value)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Property assignment expected"));
+
+ if (prop->values.count() != 1)
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Single property assignment expected"));
+
+ Value *value = prop->values.at(0);
+
+ if (value->object) {
+ bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1;
+ bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1;
+ if (!isPropertyValue && !isPropertyInterceptor) {
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Unexpected object assignment"));
+ } else {
+ COMPILE_CHECK(buildObject(value->object, ctxt));
+
+ if (isPropertyInterceptor && baseObj->synthdata.isEmpty())
+ buildDynamicMeta(baseObj, ForceCreation);
+ value->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ }
+ } else if (value->value.isScript()) {
+ // ### Check for writability
+ BindingReference reference;
+ reference.expression = value->value;
+ reference.property = prop;
+ reference.value = value;
+ reference.bindingContext = ctxt;
+ reference.bindingContext.owner++;
+ addBindingReference(reference);
+ value->type = Value::PropertyBinding;
+ } else {
+ COMPILE_CHECK(testLiteralAssignment(p, value));
+ value->type = Value::Literal;
+ }
+ obj->addValueProperty(prop);
+ }
+
+ return true;
+}
+
+// Build assignments to QML lists. QML lists are properties of type
+// QList<T *> * and QmlList<T *> *.
+//
+// QList<T *> * types can accept a list of objects, or a single binding
+// QmlList<T *> * types can accept a list of objects
+bool QmlCompiler::buildListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(QmlMetaType::isList(prop->type) ||
+ QmlEnginePrivate::get(engine)->isQmlList(prop->type));
+
+ int t = prop->type;
+
+ obj->addValueProperty(prop);
+
+ if (QmlEnginePrivate::get(engine)->isQmlList(t)) {
+ int listType = QmlEnginePrivate::get(engine)->qmlListType(t);
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ // We check object coercian here. We check interface assignment
+ // at runtime.
+ if (!listTypeIsInterface) {
+ if (!canCoerce(listType, v->object)) {
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign object to list"));
+ }
+ }
+
+ } else {
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign primitives to lists"));
+ }
+ }
+
+ } else {
+ int listType = QmlMetaType::listType(t);
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+
+ bool assignedBinding = false;
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ // We check object coercian here. We check interface assignment
+ // at runtime.
+ if (!listTypeIsInterface) {
+ if (!canCoerce(listType, v->object)) {
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign object to list"));
+ }
+ }
+
+ } else if (v->value.isScript()) {
+ if (assignedBinding)
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Can only assign one binding to lists"));
+
+ assignedBinding = true;
+ COMPILE_CHECK(buildBinding(v, prop, ctxt));
+ v->type = Value::PropertyBinding;
+ } else {
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign primitives to lists"));
+ }
+ }
+
+ }
+
+ return true;
+}
+
+// Compiles an assignment to a QmlScriptString property
+bool QmlCompiler::buildScriptStringProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ if (prop->values.count() > 1)
+ COMPILE_EXCEPTION(prop->values.at(1), QCoreApplication::translate("QmlCompiler", "Cannot assign multiple values to a script property"));
+
+ if (prop->values.at(0)->object || !prop->values.at(0)->value.isScript())
+ COMPILE_EXCEPTION(prop->values.at(0), QCoreApplication::translate("QmlCompiler", "Invalid property assignment: script expected"));
+
+ obj->addScriptStringProperty(prop, ctxt.stack);
+
+ return true;
+}
+
+// Compile regular property assignments of the form "property: <value>"
+//
+// ### The following problems exist
+//
+// There is no distinction between how "lists" of values are specified. This
+// Item {
+// children: Item {}
+// children: Item {}
+// }
+// is identical to
+// Item {
+// children: [ Item {}, Item {} ]
+// }
+//
+// We allow assignming multiple values to single value properties
+bool QmlCompiler::buildPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ obj->addValueProperty(prop);
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+
+ COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
+
+ }
+ }
+
+ return true;
+}
+
+// Compile assigning a single object instance to a regular property
+bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+ Q_ASSERT(v->object->type != -1);
+
+ if (!obj->metaObject()->property(prop->index).isWritable())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+
+ if (QmlMetaType::isInterface(prop->type)) {
+
+ // Assigning an object to an interface ptr property
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ v->type = Value::CreatedObject;
+
+ } else if (prop->type == -1) {
+
+ // Assigning an object to a QVariant
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ v->type = Value::CreatedObject;
+ } else {
+ // Normally buildObject() will set this up, but we need the static
+ // meta object earlier to test for assignability. It doesn't matter
+ // that there may still be outstanding synthesized meta object changes
+ // on this type, as they are not relevant for assignability testing
+ v->object->metatype = output->types.at(v->object->type).metaObject();
+ Q_ASSERT(v->object->metaObject());
+
+ // Will be true if the assigned type inherits QmlPropertyValueSource
+ bool isPropertyValue = false;
+ // Will be true if the assigned type inherits QmlPropertyValueInterceptor
+ bool isPropertyInterceptor = false;
+ if (QmlType *valueType = toQmlType(v->object)) {
+ isPropertyValue = valueType->propertyValueSourceCast() != -1;
+ isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1;
+ }
+
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions that might
+ // effect the properties on the type, but don't effect assignability
+ const QMetaObject *propertyMetaObject =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(prop->type);
+
+ // Will be true if the assgned type inherits propertyMetaObject
+ bool isAssignable = false;
+ // Determine isAssignable value
+ if (propertyMetaObject) {
+ const QMetaObject *c = v->object->metatype;
+ while(c) {
+ isAssignable |= (QmlMetaPropertyPrivate::equal(c, propertyMetaObject));
+ c = c->superClass();
+ }
+ }
+
+ if (isAssignable) {
+ // Simple assignment
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ v->type = Value::CreatedObject;
+ } else if (propertyMetaObject == &QmlComponent::staticMetaObject) {
+ // Automatic "Component" insertion
+ QmlParser::Object *root = v->object;
+ QmlParser::Object *component = new QmlParser::Object;
+ component->type = componentTypeRef();
+ component->typeName = "Qt/Component";
+ component->metatype = &QmlComponent::staticMetaObject;
+ component->location = root->location;
+ QmlParser::Value *componentValue = new QmlParser::Value;
+ componentValue->object = root;
+ component->getDefaultProperty()->addValue(componentValue);
+ v->object = component;
+ COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
+ } else if (isPropertyValue || isPropertyInterceptor) {
+ // Assign as a property value source
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
+ buildDynamicMeta(prop->parent, ForceCreation);
+ v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ } else {
+ COMPILE_EXCEPTION(v->object, QCoreApplication::translate("QmlCompiler","Cannot assign object to property"));
+ }
+ }
+
+ return true;
+}
+
+// Compile assigning a literal or binding to a regular property
+bool QmlCompiler::buildPropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+
+ if (v->value.isScript()) {
+
+ //optimization for <Type>.<EnumValue> enum assignments
+ bool isEnumAssignment = false;
+ COMPILE_CHECK(testQualifiedEnumAssignment(obj->metaObject()->property(prop->index), obj, v, &isEnumAssignment));
+ if (isEnumAssignment) {
+ v->type = Value::Literal;
+ return true;
+ }
+
+ COMPILE_CHECK(buildBinding(v, prop, ctxt));
+
+ v->type = Value::PropertyBinding;
+
+ } else {
+
+ COMPILE_CHECK(testLiteralAssignment(obj->metaObject()->property(prop->index), v));
+
+ v->type = Value::Literal;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ bool *isAssignment)
+{
+ *isAssignment = false;
+ if (!prop.isEnumType())
+ return true;
+
+ if (!prop.isWritable())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name())));
+
+ QString string = v->value.asString();
+ if (!string.at(0).isUpper())
+ return true;
+
+ QStringList parts = string.split(QLatin1Char('.'));
+ if (parts.count() != 2)
+ return true;
+
+ QString typeName = parts.at(0);
+ QmlType *type = 0;
+ QmlEnginePrivate::get(engine)->resolveType(unit->imports, typeName.toUtf8(),
+ &type, 0, 0, 0, 0);
+
+ if (!type || obj->typeName != type->qmlTypeName())
+ return true;
+
+ QString enumValue = parts.at(1);
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(enumValue.toUtf8().constData());
+ } else
+ value = prop.enumerator().keyToValue(enumValue.toUtf8().constData());
+ if (value == -1)
+ return true;
+
+ v->type = Value::Literal;
+ v->value = QmlParser::Variant(enumValue);
+ *isAssignment = true;
+
+ return true;
+}
+
+// Ensures that the dynamic meta specification on obj is valid
+bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj)
+{
+ QSet<QByteArray> propNames;
+ QSet<QByteArray> methodNames;
+ bool seenDefaultProperty = false;
+
+ // Check properties
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const QmlParser::Object::DynamicProperty &prop =
+ obj->dynamicProperties.at(ii);
+
+ if (prop.isDefaultProperty) {
+ if (seenDefaultProperty)
+ COMPILE_EXCEPTION(&prop, QCoreApplication::translate("QmlCompiler","Duplicate default property"));
+ seenDefaultProperty = true;
+ }
+
+ if (propNames.contains(prop.name))
+ COMPILE_EXCEPTION(&prop, QCoreApplication::translate("QmlCompiler","Duplicate property name"));
+
+ propNames.insert(prop.name);
+ }
+
+ for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ QByteArray name = obj->dynamicSignals.at(ii).name;
+ if (methodNames.contains(name))
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QmlCompiler","Duplicate signal name"));
+ methodNames.insert(name);
+ }
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ QByteArray name = obj->dynamicSlots.at(ii).name;
+ if (methodNames.contains(name))
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QmlCompiler","Duplicate method name"));
+ methodNames.insert(name);
+ }
+
+ return true;
+}
+
+bool QmlCompiler::mergeDynamicMetaProperties(QmlParser::Object *obj)
+{
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (!p.defaultValue || p.type == Object::DynamicProperty::Alias)
+ continue;
+
+ Property *property = 0;
+ if (p.isDefaultProperty)
+ property = obj->getDefaultProperty();
+ else
+ property = obj->getProperty(p.name);
+
+ if (property->value)
+ COMPILE_EXCEPTION(property, QCoreApplication::translate("QmlCompiler","Invalid property nesting"));
+
+ for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) {
+ Value *v = p.defaultValue->values.at(ii);
+ v->addref();
+ property->values.append(v);
+ }
+ }
+ return true;
+}
+
+Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter)
+
+bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode)
+{
+ Q_ASSERT(obj);
+ Q_ASSERT(obj->metatype);
+
+ if (mode != ForceCreation &&
+ obj->dynamicProperties.isEmpty() &&
+ obj->dynamicSignals.isEmpty() &&
+ obj->dynamicSlots.isEmpty())
+ return true;
+
+ COMPILE_CHECK(checkDynamicMeta(obj));
+
+ QByteArray dynamicData(sizeof(QmlVMEMetaData), (char)0);
+
+ QByteArray newClassName = obj->metatype->className();
+ newClassName.append("_QML_");
+ int idx = classIndexCounter()->fetchAndAddRelaxed(1);
+ newClassName.append(QByteArray::number(idx));
+ if (compileState.root == obj) {
+ QString path = output->url.path();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash > -1) {
+ QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
+ if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
+ newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(idx);
+ }
+ }
+
+ QMetaObjectBuilder builder;
+ builder.setClassName(newClassName);
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+
+ bool hasAlias = false;
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ int propIdx =
+ obj->metaObject()->indexOfProperty(p.name.constData());
+ if (-1 != propIdx) {
+ QMetaProperty prop = obj->metaObject()->property(propIdx);
+ if (prop.isFinal())
+ COMPILE_EXCEPTION(&p, QCoreApplication::translate("QmlCompiler","Cannot override FINAL property"));
+ }
+
+ if (p.isDefaultProperty &&
+ (p.type != Object::DynamicProperty::Alias ||
+ mode == ResolveAliases))
+ builder.addClassInfo("DefaultProperty", p.name);
+
+ QByteArray type;
+ int propertyType = 0;
+ bool readonly = false;
+ switch(p.type) {
+ case Object::DynamicProperty::Alias:
+ hasAlias = true;
+ continue;
+ break;
+ case Object::DynamicProperty::CustomList:
+ case Object::DynamicProperty::Custom:
+ {
+ QByteArray customTypeName;
+ QmlType *qmltype = 0;
+ QUrl url;
+ QmlEnginePrivate *priv = QmlEnginePrivate::get(engine);
+ if (!priv->resolveType(unit->imports, p.customType, &qmltype,
+ &url, 0, 0, 0))
+ COMPILE_EXCEPTION(&p, QCoreApplication::translate("QmlCompiler","Invalid property type"));
+
+ if (!qmltype) {
+ QmlCompositeTypeData *tdata = priv->typeManager.get(url);
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->status == QmlCompositeTypeData::Complete);
+
+ QmlCompiledData *data = tdata->toCompiledComponent(engine);
+ customTypeName = data->root->className();
+ } else {
+ customTypeName = qmltype->typeName();
+ }
+
+ if (p.type == Object::DynamicProperty::Custom) {
+ type = customTypeName + '*';
+ propertyType = QMetaType::QObjectStar;
+ } else {
+ readonly = true;
+ type = "QmlList<";
+ type.append(customTypeName);
+ type.append("*>*");
+ propertyType = qMetaTypeId<QmlList<QObject*>* >();
+ }
+ }
+ break;
+ case Object::DynamicProperty::Variant:
+ propertyType = -1;
+ type = "QVariant";
+ break;
+ case Object::DynamicProperty::Int:
+ propertyType = QVariant::Int;
+ type = "int";
+ break;
+ case Object::DynamicProperty::Bool:
+ propertyType = QVariant::Bool;
+ type = "bool";
+ break;
+ case Object::DynamicProperty::Real:
+ propertyType = QVariant::Double;
+ type = "double";
+ break;
+ case Object::DynamicProperty::String:
+ propertyType = QVariant::String;
+ type = "QString";
+ break;
+ case Object::DynamicProperty::Url:
+ propertyType = QVariant::Url;
+ type = "QUrl";
+ break;
+ case Object::DynamicProperty::Color:
+ propertyType = QVariant::Color;
+ type = "QColor";
+ break;
+ case Object::DynamicProperty::Date:
+ propertyType = QVariant::Date;
+ type = "QDate";
+ break;
+ }
+
+ ((QmlVMEMetaData *)dynamicData.data())->propertyCount++;
+ QmlVMEMetaData::PropertyData propertyData = { propertyType };
+ dynamicData.append((char *)&propertyData, sizeof(propertyData));
+
+ builder.addSignal(p.name + "Changed()");
+ QMetaPropertyBuilder propBuilder =
+ builder.addProperty(p.name, type, builder.methodCount() - 1);
+ propBuilder.setScriptable(true);
+ propBuilder.setWritable(!readonly);
+ }
+
+ if (mode == ResolveAliases) {
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (p.type == Object::DynamicProperty::Alias) {
+ ((QmlVMEMetaData *)dynamicData.data())->aliasCount++;
+ compileAlias(builder, dynamicData, obj, p);
+ }
+ }
+ }
+
+ for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ const Object::DynamicSignal &s = obj->dynamicSignals.at(ii);
+ QByteArray sig(s.name + '(');
+ for (int jj = 0; jj < s.parameterTypes.count(); ++jj) {
+ if (jj) sig.append(',');
+ sig.append(s.parameterTypes.at(jj));
+ }
+ sig.append(')');
+ QMetaMethodBuilder b = builder.addSignal(sig);
+ b.setParameterNames(s.parameterNames);
+ ((QmlVMEMetaData *)dynamicData.data())->signalCount++;
+ }
+
+ QStringList funcScripts;
+
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ Object::DynamicSlot &s = obj->dynamicSlots[ii];
+ QByteArray sig(s.name + '(');
+ QString funcScript(QLatin1String("(function("));
+
+ for (int jj = 0; jj < s.parameterNames.count(); ++jj) {
+ if (jj) {
+ sig.append(',');
+ funcScript.append(QLatin1Char(','));
+ }
+ funcScript.append(QLatin1String(s.parameterNames.at(jj)));
+ sig.append("QVariant");
+ }
+ sig.append(')');
+ funcScript.append(QLatin1Char(')'));
+ funcScript.append(s.body);
+ funcScript.append(QLatin1Char(')'));
+ funcScripts << funcScript;
+
+ QMetaMethodBuilder b = builder.addSlot(sig);
+ b.setReturnType("QVariant");
+ b.setParameterNames(s.parameterNames);
+
+ ((QmlVMEMetaData *)dynamicData.data())->methodCount++;
+ QmlVMEMetaData::MethodData methodData =
+ { s.parameterNames.count(), 0, funcScript.length(), 0 };
+
+ dynamicData.append((char *)&methodData, sizeof(methodData));
+ }
+
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ const QString &funcScript = funcScripts.at(ii);
+ QmlVMEMetaData::MethodData *data =
+ ((QmlVMEMetaData *)dynamicData.data())->methodData() + ii;
+
+ data->bodyOffset = dynamicData.size();
+
+ dynamicData.append((const char *)funcScript.constData(),
+ (funcScript.length() * sizeof(QChar)));
+ }
+
+ obj->metadata = builder.toRelocatableData();
+ builder.fromRelocatableData(&obj->extObject, obj->metatype, obj->metadata);
+
+ if (mode == IgnoreAliases && hasAlias)
+ compileState.aliasingObjects << obj;
+
+ obj->synthdata = dynamicData;
+
+ return true;
+}
+
+#include <qmljsparser_p.h>
+
+static QStringList astNodeToStringList(QmlJS::AST::Node *node)
+{
+ if (node->kind == QmlJS::AST::Node::Kind_IdentifierExpression) {
+ QString name =
+ static_cast<QmlJS::AST::IdentifierExpression *>(node)->name->asString();
+ return QStringList() << name;
+ } else if (node->kind == QmlJS::AST::Node::Kind_FieldMemberExpression) {
+ QmlJS::AST::FieldMemberExpression *expr = static_cast<QmlJS::AST::FieldMemberExpression *>(node);
+
+ QStringList rv = astNodeToStringList(expr->base);
+ if (rv.isEmpty())
+ return rv;
+ rv.append(expr->name->asString());
+ return rv;
+ }
+ return QStringList();
+}
+
+bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder,
+ QByteArray &data,
+ Object *obj,
+ const Object::DynamicProperty &prop)
+{
+ if (!prop.defaultValue)
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QmlCompiler","No property alias location"));
+
+ if (prop.defaultValue->values.count() != 1 ||
+ prop.defaultValue->values.at(0)->object ||
+ !prop.defaultValue->values.at(0)->value.isScript())
+ COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias location"));
+
+ QmlJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST();
+ if (!node)
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QmlCompiler","No property alias location")); // ### Can this happen?
+
+ QStringList alias = astNodeToStringList(node);
+
+ if (alias.count() != 1 && alias.count() != 2)
+ COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias reference. An alias reference must be specified as <id> or <id>.<property>"));
+
+ if (!compileState.ids.contains(alias.at(0)))
+ COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
+
+ Object *idObject = compileState.ids[alias.at(0)];
+
+ QByteArray typeName;
+
+ int propIdx = -1;
+ int flags = 0;
+ bool writable = false;
+ if (alias.count() == 2) {
+ propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData());
+
+ if (-1 == propIdx)
+ COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias location"));
+
+ QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx);
+ writable = aliasProperty.isWritable();
+
+ if (aliasProperty.isEnumType())
+ typeName = "int"; // Avoid introducing a dependency on the aliased metaobject
+ else
+ typeName = aliasProperty.typeName();
+ } else {
+ typeName = idObject->metaObject()->className();
+
+ //use the base type since it has been registered with metatype system
+ int index = typeName.indexOf("_QML_");
+ if (index != -1) {
+ typeName = typeName.left(index);
+ } else {
+ index = typeName.indexOf("_QMLTYPE_");
+ const QMetaObject *mo = idObject->metaObject();
+ while (index != -1 && mo) {
+ typeName = mo->superClass()->className();
+ index = typeName.indexOf("_QMLTYPE_");
+ mo = mo->superClass();
+ }
+ }
+
+ typeName += '*';
+ }
+
+ if (typeName.endsWith('*'))
+ flags |= QML_ALIAS_FLAG_PTR;
+
+ data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex));
+ data.append((const char *)&propIdx, sizeof(propIdx));
+ data.append((const char *)&flags, sizeof(flags));
+
+ builder.addSignal(prop.name + "Changed()");
+ QMetaPropertyBuilder propBuilder =
+ builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1);
+ propBuilder.setScriptable(true);
+ propBuilder.setWritable(writable);
+ return true;
+}
+
+bool QmlCompiler::buildBinding(QmlParser::Value *value,
+ QmlParser::Property *prop,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+ Q_ASSERT(prop->parent);
+ Q_ASSERT(prop->parent->metaObject());
+
+ QMetaProperty mp = prop->parent->metaObject()->property(prop->index);
+ if (!mp.isWritable() && !QmlMetaType::isList(prop->type))
+ COMPILE_EXCEPTION(prop, QCoreApplication::translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+
+ BindingReference reference;
+ reference.expression = value->value;
+ reference.property = prop;
+ reference.value = value;
+ reference.bindingContext = ctxt;
+ addBindingReference(reference);
+
+ return true;
+}
+
+void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty)
+{
+ Q_UNUSED(obj);
+ Q_ASSERT(compileState.bindings.contains(binding));
+
+ const BindingReference &ref = compileState.bindings.value(binding);
+ if (ref.dataType == BindingReference::Experimental) {
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreCompiledBinding;
+ store.assignBinding.value = ref.compiledIndex;
+ store.assignBinding.context = ref.bindingContext.stack;
+ store.assignBinding.owner = ref.bindingContext.owner;
+ if (valueTypeProperty)
+ store.assignBinding.property = (valueTypeProperty->index & 0xFFFF) |
+ ((valueTypeProperty->type & 0xFF)) << 16 |
+ ((prop->index & 0xFF) << 24);
+ else
+ store.assignBinding.property = prop->index;
+ store.line = binding->location.start.line;
+ output->bytecode << store;
+ return;
+ }
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreBinding;
+ store.assignBinding.value = output->indexForByteArray(ref.compiledData);
+ store.assignBinding.context = ref.bindingContext.stack;
+ store.assignBinding.owner = ref.bindingContext.owner;
+ store.line = binding->location.start.line;
+
+ Q_ASSERT(ref.bindingContext.owner == 0 ||
+ (ref.bindingContext.owner != 0 && valueTypeProperty));
+ if (ref.bindingContext.owner) {
+ store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
+ } else {
+ store.assignBinding.property = genPropertyData(prop);
+ }
+
+ output->bytecode << store;
+}
+
+int QmlCompiler::genContextCache()
+{
+ if (compileState.ids.count() == 0)
+ return -1;
+
+ QmlIntegerCache *cache = new QmlIntegerCache(engine);
+
+ for (QHash<QString, QmlParser::Object *>::ConstIterator iter = compileState.ids.begin();
+ iter != compileState.ids.end();
+ ++iter)
+ cache->add(iter.key(), (*iter)->idIndex);
+
+ output->contextCaches.append(cache);
+ return output->contextCaches.count() - 1;
+}
+
+int QmlCompiler::genValueTypeData(QmlParser::Property *valueTypeProp,
+ QmlParser::Property *prop)
+{
+ return output->indexForByteArray(QmlMetaPropertyPrivate::saveValueType(prop->parent->metaObject(), prop->index, valueTypeProp->index, valueTypeProp->type));
+}
+
+int QmlCompiler::genPropertyData(QmlParser::Property *prop)
+{
+ return output->indexForByteArray(QmlMetaPropertyPrivate::saveProperty(prop->parent->metaObject(), prop->index));
+}
+
+bool QmlCompiler::completeComponentBuild()
+{
+ componentStat.ids = compileState.ids.count();
+
+ for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) {
+ Object *aliasObject = compileState.aliasingObjects.at(ii);
+ COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
+ }
+
+ QmlBindingCompiler::Expression expr;
+ expr.component = compileState.root;
+ expr.ids = compileState.ids;
+
+ QmlBindingCompiler bindingCompiler;
+
+ for (QHash<QmlParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) {
+ BindingReference &binding = *iter;
+
+ expr.context = binding.bindingContext.object;
+ expr.property = binding.property;
+ expr.expression = binding.expression;
+ expr.imports = unit->imports;
+
+ if (qmlExperimental()) {
+ int index = bindingCompiler.compile(expr, QmlEnginePrivate::get(engine));
+ if (index != -1) {
+ qWarning() << "Accepted for optimization:" << qPrintable(expr.expression.asScript());
+ binding.dataType = BindingReference::Experimental;
+ binding.compiledIndex = index;
+ componentStat.optimizedBindings++;
+ continue;
+ } else {
+ qWarning() << "Rejected for optimization:" << qPrintable(expr.expression.asScript());
+ }
+ }
+
+ binding.dataType = BindingReference::QtScript;
+
+ // Pre-rewrite the expression
+ QString expression = binding.expression.asScript();
+
+ // ### Optimize
+ QmlRewrite::SharedBindingTester sharableTest;
+ bool isSharable = sharableTest.isSharable(expression);
+
+ QmlRewrite::RewriteBinding rewriteBinding;
+ expression = rewriteBinding(expression);
+
+ quint32 length = expression.length();
+ quint32 pc;
+
+ if (isSharable) {
+ pc = output->cachedClosures.count();
+ pc |= 0x80000000;
+ output->cachedClosures.append(0);
+ } else {
+ pc = output->cachedPrograms.length();
+ output->cachedPrograms.append(0);
+ }
+
+ binding.compiledData =
+ QByteArray((const char *)&pc, sizeof(quint32)) +
+ QByteArray((const char *)&length, sizeof(quint32)) +
+ QByteArray((const char *)expression.constData(),
+ expression.length() * sizeof(QChar));
+
+ componentStat.scriptBindings++;
+ }
+
+ if (bindingCompiler.isValid()) {
+ compileState.compiledBindingData = bindingCompiler.program();
+ QmlBindingCompiler::dump(compileState.compiledBindingData);
+ }
+
+ saveComponentState();
+
+ return true;
+}
+
+void QmlCompiler::dumpStats()
+{
+ qWarning().nospace() << "QML Document: " << output->url.toString();
+ for (int ii = 0; ii < savedComponentStats.count(); ++ii) {
+ const ComponentStat &stat = savedComponentStats.at(ii);
+ qWarning().nospace() << " Component Line " << stat.lineNumber;
+ qWarning().nospace() << " Total Objects: " << stat.objects;
+ qWarning().nospace() << " IDs Used: " << stat.ids;
+ qWarning().nospace() << " Optimized Bindings: " << stat.optimizedBindings;
+ qWarning().nospace() << " QScript Bindings: " << stat.scriptBindings;
+ }
+}
+
+/*!
+ Returns true if from can be assigned to a (QObject) property of type
+ to.
+*/
+bool QmlCompiler::canCoerce(int to, QmlParser::Object *from)
+{
+ const QMetaObject *toMo =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(to);
+ const QMetaObject *fromMo = from->metaObject();
+
+ while (fromMo) {
+ if (QmlMetaPropertyPrivate::equal(fromMo, toMo))
+ return true;
+ fromMo = fromMo->superClass();
+ }
+ return false;
+}
+
+/*!
+ Returns true if from can be assigned to a (QObject) property of type
+ to.
+*/
+bool QmlCompiler::canCoerce(int to, int from)
+{
+ const QMetaObject *toMo =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(to);
+ const QMetaObject *fromMo =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(from);
+
+ while (fromMo) {
+ if (QmlMetaPropertyPrivate::equal(fromMo, toMo))
+ return true;
+ fromMo = fromMo->superClass();
+ }
+ return false;
+}
+
+QmlType *QmlCompiler::toQmlType(QmlParser::Object *from)
+{
+ // ### Optimize
+ const QMetaObject *mo = from->metatype;
+ QmlType *type = 0;
+ while (!type && mo) {
+ type = QmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ return type;
+}
+
+QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj)
+{
+ const QMetaObject *mo = obj->metatype;
+
+ int idx = mo->indexOfClassInfo("DeferredPropertyNames");
+ if (idx == -1)
+ return QStringList();
+
+ QMetaClassInfo classInfo = mo->classInfo(idx);
+ QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
+ return rv;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
new file mode 100644
index 0000000..f3f266b
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPILER_P_H
+#define QMLCOMPILER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qml.h"
+#include "qmlerror.h"
+#include "qmlinstruction_p.h"
+#include "qmlcompositetypemanager_p.h"
+#include "qmlparser_p.h"
+#include "qmlengine_p.h"
+#include "qbitfield_p.h"
+#include "qmlpropertycache_p.h"
+#include "qmlintegercache_p.h"
+#include "qmltypenamecache_p.h"
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlComponent;
+class QmlContext;
+
+class QScriptProgram;
+class Q_AUTOTEST_EXPORT QmlCompiledData : public QmlRefCount, public QmlCleanup
+{
+public:
+ QmlCompiledData(QmlEngine *engine);
+ virtual ~QmlCompiledData();
+
+ QString name;
+ QUrl url;
+ QmlEnginePrivate::Imports imports;
+ QmlTypeNameCache *importCache;
+
+ struct TypeReference
+ {
+ TypeReference()
+ : type(0), component(0), ref(0) {}
+
+ QByteArray className;
+ QmlType *type;
+ QmlComponent *component;
+
+ QmlRefCount *ref;
+ QObject *createInstance(QmlContext *, const QBitField &) const;
+ const QMetaObject *metaObject() const;
+ };
+ QList<TypeReference> types;
+ struct CustomTypeData
+ {
+ int index;
+ int type;
+ };
+
+ const QMetaObject *root;
+ QAbstractDynamicMetaObject rootData;
+ QmlPropertyCache *rootPropertyCache;
+ QList<QString> primitives;
+ QList<float> floatData;
+ QList<int> intData;
+ QList<CustomTypeData> customTypeData;
+ QList<QByteArray> datas;
+ QList<QmlParser::Location> locations;
+ QList<QmlInstruction> bytecode;
+ QList<QScriptProgram *> cachedPrograms;
+ QList<QScriptValue *> cachedClosures;
+ QList<QmlPropertyCache *> propertyCaches;
+ QList<QmlIntegerCache *> contextCaches;
+ QList<QmlParser::Object::ScriptBlock> scripts;
+ QList<QUrl> urls;
+
+ void dumpInstructions();
+
+protected:
+ virtual void clear(); // From QmlCleanup
+
+private:
+ void dump(QmlInstruction *, int idx = -1);
+ QmlCompiledData(const QmlCompiledData &other);
+ QmlCompiledData &operator=(const QmlCompiledData &other);
+ QByteArray packData;
+ friend class QmlCompiler;
+ int pack(const char *, size_t);
+
+ int indexForString(const QString &);
+ int indexForByteArray(const QByteArray &);
+ int indexForFloat(float *, int);
+ int indexForInt(int *, int);
+ int indexForLocation(const QmlParser::Location &);
+ int indexForLocation(const QmlParser::LocationSpan &);
+ int indexForUrl(const QUrl &);
+};
+
+class QMetaObjectBuilder;
+class Q_DECLARATIVE_EXPORT QmlCompiler
+{
+public:
+ QmlCompiler();
+
+ bool compile(QmlEngine *, QmlCompositeTypeData *, QmlCompiledData *);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+ static bool isValidId(const QString &);
+ static bool isAttachedPropertyName(const QByteArray &);
+ static bool isSignalPropertyName(const QByteArray &);
+
+private:
+ static void reset(QmlCompiledData *);
+
+ struct BindingContext {
+ BindingContext()
+ : stack(0), owner(0), object(0) {}
+ BindingContext(QmlParser::Object *o)
+ : stack(0), owner(0), object(o) {}
+ BindingContext incr() const {
+ BindingContext rv(object);
+ rv.stack = stack + 1;
+ return rv;
+ }
+ bool isSubContext() const { return stack != 0; }
+ int stack;
+ int owner;
+ QmlParser::Object *object;
+ };
+
+ void compileTree(QmlParser::Object *tree);
+
+
+ bool buildObject(QmlParser::Object *obj, const BindingContext &);
+ bool buildScript(QmlParser::Object *obj, QmlParser::Object *script);
+ bool buildComponent(QmlParser::Object *obj, const BindingContext &);
+ bool buildSubObject(QmlParser::Object *obj, const BindingContext &);
+ bool buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &);
+ bool buildProperty(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &);
+ bool buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &);
+ bool buildIdProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool buildAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildGroupedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildValueTypeProperty(QObject *type,
+ QmlParser::Object *obj,
+ QmlParser::Object *baseObj,
+ const BindingContext &ctxt);
+ bool buildListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildScriptStringProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildPropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ const BindingContext &ctxt);
+ bool buildPropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ const BindingContext &ctxt);
+ bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool testLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *value);
+ bool testQualifiedEnumAssignment(const QMetaProperty &prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ bool *isAssignment);
+ enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
+ bool mergeDynamicMetaProperties(QmlParser::Object *obj);
+ bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode);
+ bool checkDynamicMeta(QmlParser::Object *obj);
+ bool buildBinding(QmlParser::Value *, QmlParser::Property *prop,
+ const BindingContext &ctxt);
+ bool buildComponentFromRoot(QmlParser::Object *obj, const BindingContext &);
+ bool compileAlias(QMetaObjectBuilder &,
+ QByteArray &data,
+ QmlParser::Object *obj,
+ const QmlParser::Object::DynamicProperty &);
+ bool completeComponentBuild();
+
+
+ void genObject(QmlParser::Object *obj);
+ void genObjectBody(QmlParser::Object *obj);
+ void genComponent(QmlParser::Object *obj);
+ void genValueProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ void genListProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ void genPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty = 0);
+ void genLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *value);
+ void genBindingAssignment(QmlParser::Value *binding,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty = 0);
+ int genContextCache();
+
+ int genValueTypeData(QmlParser::Property *prop, QmlParser::Property *valueTypeProp);
+ int genPropertyData(QmlParser::Property *prop);
+
+ int componentTypeRef();
+
+ static int findSignalByName(const QMetaObject *, const QByteArray &name);
+ static QmlType *toQmlType(QmlParser::Object *from);
+ bool canCoerce(int to, QmlParser::Object *from);
+ bool canCoerce(int to, int from);
+
+ QStringList deferredProperties(QmlParser::Object *);
+
+ void addId(const QString &, QmlParser::Object *);
+
+ void dumpStats();
+
+ struct BindingReference {
+ QmlParser::Variant expression;
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+
+ enum DataType { QtScript, Experimental };
+ DataType dataType;
+
+ int compiledIndex;
+
+ QByteArray compiledData;
+ BindingContext bindingContext;
+ };
+ void addBindingReference(const BindingReference &);
+
+ struct ComponentCompileState
+ {
+ ComponentCompileState()
+ : parserStatusCount(0), pushedProperties(0), root(0) {}
+ QHash<QString, QmlParser::Object *> ids;
+ QHash<int, QmlParser::Object *> idIndexes;
+ int parserStatusCount;
+ int pushedProperties;
+
+ QByteArray compiledBindingData;
+
+ QHash<QmlParser::Value *, BindingReference> bindings;
+ QList<QmlParser::Object *> aliasingObjects;
+ QmlParser::Object *root;
+ };
+ ComponentCompileState compileState;
+
+ struct ComponentStat
+ {
+ ComponentStat()
+ : ids(0), scriptBindings(0), optimizedBindings(0), objects(0) {}
+
+ int lineNumber;
+
+ int ids;
+ int scriptBindings;
+ int optimizedBindings;
+ int objects;
+ };
+ ComponentStat componentStat;
+
+ void saveComponentState();
+
+ ComponentCompileState componentState(QmlParser::Object *);
+ QHash<QmlParser::Object *, ComponentCompileState> savedCompileStates;
+ QList<ComponentStat> savedComponentStats;
+
+ QList<QmlError> exceptions;
+ QmlCompiledData *output;
+ QmlEngine *engine;
+ QmlParser::Object *unitRoot;
+ QmlCompositeTypeData *unit;
+};
+QT_END_NAMESPACE
+
+#endif // QMLCOMPILER_P_H
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
new file mode 100644
index 0000000..9e06016
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -0,0 +1,798 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+
+#include "qmlcompiler_p.h"
+#include "qmlcontext_p.h"
+#include "qmlcompositetypedata_p.h"
+#include "qmlengine_p.h"
+#include "qmlvme_p.h"
+#include "qml.h"
+#include "qmlengine.h"
+#include "qmlbinding.h"
+#include "qmlbinding_p.h"
+#include "qmlglobal_p.h"
+#include "qmlscriptparser_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QStack>
+#include <QStringList>
+#include <QFileInfo>
+#include <QtCore/qdebug.h>
+#include <QApplication>
+
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+int statusId = qRegisterMetaType<QmlComponent::Status>("QmlComponent::Status");
+
+/*!
+ \class QmlComponent
+ \brief The QmlComponent class encapsulates a QML component description.
+ \mainclass
+*/
+
+/*!
+ \qmlclass Component QmlComponent
+ \brief The Component element encapsulates a QML component description.
+
+ Components are reusable, encapsulated Qml element with a well-defined interface.
+ They are often defined in \l {qmldocuments.html}{Component Files}.
+
+ The \e Component element allows defining components within a QML file.
+ This can be useful for reusing a small component within a single QML
+ file, or for defining a component that logically belongs with the
+ file containing it.
+
+ \qml
+Item {
+ Component {
+ id: redSquare
+ Rectangle {
+ color: "red"
+ width: 10
+ height: 10
+ }
+ }
+ Loader { sourceComponent: redSquare }
+ Loader { sourceComponent: redSquare; x: 20 }
+}
+ \endqml
+
+ \section1 Attached Properties
+
+ \e onCompleted
+
+ Emitted after component "startup" has completed. This can be used to
+ execute script code at startup, once the full QML environment has been
+ established.
+
+ The \c {Component::onCompleted} attached property can be applied to
+ any element. The order of running the \c onCompleted scripts is
+ undefined.
+
+ \qml
+ Rectangle {
+ Component.onCompleted: console.log("Completed Running!")
+ Rectangle {
+ Component.onCompleted: console.log("Nested Completed Running!")
+ }
+ }
+ \endqml
+*/
+QML_DEFINE_TYPE(Qt,4,6,Component,QmlComponent);
+
+/*!
+ \enum QmlComponent::Status
+
+ Specifies the loading status of the QmlComponent.
+
+ \value Null This QmlComponent has no data. Call loadUrl() or setData() to add QML content.
+ \value Ready This QmlComponent is ready and create() may be called.
+ \value Loading This QmlComponent is loading network data.
+ \value Error An error has occured. Calling errorDescription() to retrieve a description.
+*/
+
+void QmlComponentPrivate::typeDataReady()
+{
+ Q_Q(QmlComponent);
+
+ Q_ASSERT(typeData);
+
+ fromTypeData(typeData);
+ typeData = 0;
+
+ emit q->statusChanged(q->status());
+}
+
+void QmlComponentPrivate::updateProgress(qreal p)
+{
+ Q_Q(QmlComponent);
+
+ progress = p;
+ emit q->progressChanged(p);
+}
+
+void QmlComponentPrivate::fromTypeData(QmlCompositeTypeData *data)
+{
+ url = data->imports.baseUrl();
+ QmlCompiledData *c = data->toCompiledComponent(engine);
+
+ if (!c) {
+ Q_ASSERT(data->status == QmlCompositeTypeData::Error);
+
+ state.errors = data->errors;
+
+ } else {
+
+ cc = c;
+
+ }
+
+ data->release();
+}
+
+void QmlComponentPrivate::clear()
+{
+ if (typeData) {
+ typeData->remWaiter(this);
+ typeData->release();
+ typeData = 0;
+ }
+
+ if (cc) {
+ cc->release();
+ cc = 0;
+ }
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+}
+
+/*!
+ Destruct the QmlComponent.
+*/
+QmlComponent::~QmlComponent()
+{
+ Q_D(QmlComponent);
+
+ if (d->state.completePending) {
+ qWarning("QmlComponent: Component destroyed while completion pending");
+ d->completeCreate();
+ }
+
+ if (d->typeData) {
+ d->typeData->remWaiter(d);
+ d->typeData->release();
+ }
+ if (d->cc)
+ d->cc->release();
+}
+
+/*!
+ \property QmlComponent::status
+ The component's current \l{QmlComponent::Status} {status}.
+ */
+QmlComponent::Status QmlComponent::status() const
+{
+ Q_D(const QmlComponent);
+
+ if (d->typeData)
+ return Loading;
+ else if (!d->state.errors.isEmpty())
+ return Error;
+ else if (d->engine && d->cc)
+ return Ready;
+ else
+ return Null;
+}
+
+/*!
+ \property QmlComponent::isNull
+
+ Is true if the component is in the Null state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Null.
+*/
+bool QmlComponent::isNull() const
+{
+ return status() == Null;
+}
+
+/*!
+ \property QmlComponent::isReady
+
+ Is true if the component is in the Ready state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Ready.
+*/
+bool QmlComponent::isReady() const
+{
+ return status() == Ready;
+}
+
+/*!
+ \property QmlComponent::isError
+
+ Is true if the component is in the Error state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Error.
+*/
+bool QmlComponent::isError() const
+{
+ return status() == Error;
+}
+
+/*!
+ \property QmlComponent::isLoading
+
+ Is true if the component is in the Loading state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Loading.
+*/
+bool QmlComponent::isLoading() const
+{
+ return status() == Loading;
+}
+
+/*!
+ \property QmlComponent::progress
+ The progress of loading the component, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+*/
+qreal QmlComponent::progress() const
+{
+ Q_D(const QmlComponent);
+ return d->progress;
+}
+
+/*!
+ \fn void QmlComponent::progressChanged(qreal progress)
+
+ Emitted whenever the component's loading progress changes. \a progress will be the
+ current progress between 0.0 (nothing loaded) and 1.0 (finished).
+*/
+
+/*!
+ \fn void QmlComponent::statusChanged(QmlComponent::Status status)
+
+ Emitted whenever the component's status changes. \a status will be the
+ new status.
+*/
+
+/*!
+ Create a QmlComponent with no data and give it the specified
+ \a engine and \a parent. Set the data with setData().
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+}
+
+/*!
+ Create a QmlComponent from the given \a url and give it the
+ specified \a parent and \a engine.
+
+ \sa loadUrl()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QUrl &url, QObject *parent)
+: QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ loadUrl(url);
+}
+
+/*!
+ Create a QmlComponent from the given \a fileName and give it the specified
+ \a parent and \a engine.
+
+ \sa loadUrl()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QString &fileName,
+ QObject *parent)
+: QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ loadUrl(QUrl::fromLocalFile(fileName));
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QmlCompiledData *cc, int start, int count, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ d->cc = cc;
+ cc->addref();
+ d->start = start;
+ d->count = count;
+ d->url = cc->url;
+ d->progress = 1.0;
+}
+
+/*!
+ Sets the QmlComponent to use the given QML \a data. If \a url
+ is provided, it is used to set the component name and to provide
+ a base path for items resolved by this component.
+*/
+void QmlComponent::setData(const QByteArray &data, const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ d->url = url;
+
+ QmlCompositeTypeData *typeData =
+ QmlEnginePrivate::get(d->engine)->typeManager.getImmediate(data, url);
+
+ if (typeData->status == QmlCompositeTypeData::Waiting
+ || typeData->status == QmlCompositeTypeData::WaitingResources)
+ {
+ d->typeData = typeData;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(typeData);
+
+ }
+
+ d->progress = 1.0;
+ emit statusChanged(status());
+ emit progressChanged(d->progress);
+}
+
+/*!
+Returns the QmlContext the component was created in. This is only
+valid for components created directly from QML.
+*/
+QmlContext *QmlComponent::creationContext() const
+{
+ Q_D(const QmlComponent);
+ if(d->creationContext)
+ return d->creationContext;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(this);
+ if (ddata)
+ return ddata->context;
+ else
+ return 0;
+}
+
+/*!
+ \internal
+ Sets the QmlContext the component was created in. This is only
+ desirable for components created in QML script.
+*/
+void QmlComponent::setCreationContext(QmlContext* c)
+{
+ Q_D(QmlComponent);
+ d->creationContext = c;
+}
+
+/*!
+ Load the QmlComponent from the provided \a url.
+*/
+void QmlComponent::loadUrl(const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ if (url.isRelative() && !url.isEmpty())
+ d->url = d->engine->baseUrl().resolved(url);
+ else
+ d->url = url;
+
+ QmlCompositeTypeData *data =
+ QmlEnginePrivate::get(d->engine)->typeManager.get(d->url);
+
+ if (data->status == QmlCompositeTypeData::Waiting
+ || data->status == QmlCompositeTypeData::WaitingResources)
+ {
+ d->typeData = data;
+ d->typeData->addWaiter(d);
+ d->progress = data->progress;
+ } else {
+ d->fromTypeData(data);
+ d->progress = 1.0;
+ }
+
+ emit statusChanged(status());
+ emit progressChanged(d->progress);
+}
+
+/*!
+ Return the list of errors that occured during the last compile or create
+ operation. An empty list is returned if isError() is not set.
+*/
+QList<QmlError> QmlComponent::errors() const
+{
+ Q_D(const QmlComponent);
+ if (isError())
+ return d->state.errors;
+ else
+ return QList<QmlError>();
+}
+
+/*!
+ \internal
+ errorsString is only meant as a way to get the errors in script
+*/
+QString QmlComponent::errorsString() const
+{
+ Q_D(const QmlComponent);
+ QString ret;
+ if(!isError())
+ return ret;
+ foreach(const QmlError &e, d->state.errors) {
+ ret += e.url().toString() + QLatin1Char(':') +
+ QString::number(e.line()) + QLatin1Char(' ') +
+ e.description() + QLatin1Char('\n');
+ }
+ return ret;
+}
+
+/*!
+ \property QmlComponent::url
+ The component URL. This is the URL passed to either the constructor,
+ or the loadUrl() or setData() methods.
+*/
+QUrl QmlComponent::url() const
+{
+ Q_D(const QmlComponent);
+ return d->url;
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlComponentPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+
+/*!
+ \internal
+ A version of create which returns a scriptObject, for use in script
+*/
+QScriptValue QmlComponent::createObject()
+{
+ Q_D(QmlComponent);
+ QmlContext* ctxt = creationContext();
+ if(!ctxt){
+ qWarning() << QLatin1String("createObject can only be used in QML");
+ return QScriptValue();
+ }
+ QObject* ret = create(ctxt);
+ return QmlEnginePrivate::qmlScriptObject(ret, d->engine);
+}
+
+/*!
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ If \a context is 0 (the default), it will create the instance in the
+ engine' s \l {QmlEngine::rootContext()}{root context}.
+*/
+QObject *QmlComponent::create(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ return d->create(context, QBitField());
+}
+
+QObject *QmlComponentPrivate::create(QmlContext *context,
+ const QBitField &bindings)
+{
+ QObject *create(QmlContext *context, const QBitField &);
+ if (!context)
+ context = engine->rootContext();
+
+ if (context->engine() != engine) {
+ qWarning("QmlComponent::create(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ QObject *rv = beginCreate(context, bindings);
+ completeCreate();
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ When QmlComponent constructs an instance, it occurs in three steps:
+ \list 1
+ \i The object hierarchy is created, and constant values are assigned.
+ \i Property bindings are evaluated for the the first time.
+ \i If applicable, QmlParserStatus::componentComplete() is called on objects.
+ \endlist
+ QmlComponent::beginCreate() differs from QmlComponent::create() in that it
+ only performs step 1. QmlComponent::completeCreate() must be called to
+ complete steps 2 and 3.
+
+ This breaking point is sometimes useful when using attached properties to
+ communicate information to an instantiated component, as it allows their
+ initial values to be configured before property bindings take effect.
+*/
+QObject *QmlComponent::beginCreate(QmlContext *context)
+{
+ Q_D(QmlComponent);
+ return d->beginCreate(context, QBitField());
+}
+
+QObject *
+QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings)
+{
+ Q_Q(QmlComponent);
+ if (!context) {
+ qWarning("QmlComponent::beginCreate(): Cannot create a component in a null context");
+ return 0;
+ }
+
+ if (context->engine() != engine) {
+ qWarning("QmlComponent::beginCreate(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ if (state.completePending) {
+ qWarning("QmlComponent: Cannot create new component instance before completing the previous");
+ return 0;
+ }
+
+ if (!q->isReady()) {
+ qWarning("QmlComponent: Component is not ready");
+ return 0;
+ }
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ QmlContextPrivate *contextPriv =
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+ QmlContext *ctxt = new QmlContext(context, 0, true);
+ static_cast<QmlContextPrivate*>(ctxt->d_func())->url = cc->url;
+ static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->importCache;
+ cc->importCache->addref();
+
+ QObject *rv = begin(ctxt, ep, cc, start, count, &state, bindings);
+
+ if (rv) {
+ QmlGraphics_setParent_noEvent(ctxt, rv);
+ } else {
+ delete ctxt;
+ }
+
+ if (rv && !contextPriv->isInternal && ep->isDebugging)
+ contextPriv->instances.append(rv);
+ return rv;
+}
+
+QObject * QmlComponentPrivate::begin(QmlContext *ctxt, QmlEnginePrivate *enginePriv,
+ QmlCompiledData *component, int start, int count,
+ ConstructionState *state, const QBitField &bindings)
+{
+ bool isRoot = !enginePriv->inBeginCreate;
+ enginePriv->inBeginCreate = true;
+
+ QmlVME vme;
+ QObject *rv = vme.run(ctxt, component, start, count, bindings);
+
+ if (vme.isError())
+ state->errors = vme.errors();
+
+ if (isRoot) {
+ enginePriv->inBeginCreate = false;
+
+ state->bindValues = enginePriv->bindValues;
+ state->parserStatus = enginePriv->parserStatus;
+ state->componentAttacheds = enginePriv->componentAttacheds;
+ if (state->componentAttacheds)
+ state->componentAttacheds->prev = &state->componentAttacheds;
+
+ enginePriv->componentAttacheds = 0;
+ enginePriv->bindValues.clear();
+ enginePriv->parserStatus.clear();
+ state->completePending = true;
+ enginePriv->inProgressCreations++;
+ }
+
+ return rv;
+}
+
+void QmlComponentPrivate::beginDeferred(QmlContext *, QmlEnginePrivate *enginePriv,
+ QObject *object, ConstructionState *state)
+{
+ bool isRoot = !enginePriv->inBeginCreate;
+ enginePriv->inBeginCreate = true;
+
+ QmlVME vme;
+ vme.runDeferred(object);
+
+ if (vme.isError())
+ state->errors = vme.errors();
+
+ if (isRoot) {
+ enginePriv->inBeginCreate = false;
+
+ state->bindValues = enginePriv->bindValues;
+ state->parserStatus = enginePriv->parserStatus;
+ state->componentAttacheds = enginePriv->componentAttacheds;
+ if (state->componentAttacheds)
+ state->componentAttacheds->prev = &state->componentAttacheds;
+
+ enginePriv->componentAttacheds = 0;
+ enginePriv->bindValues.clear();
+ enginePriv->parserStatus.clear();
+ state->completePending = true;
+ enginePriv->inProgressCreations++;
+ }
+}
+
+void QmlComponentPrivate::complete(QmlEnginePrivate *enginePriv, ConstructionState *state)
+{
+ if (state->completePending) {
+
+ for (int ii = 0; ii < state->bindValues.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlAbstractBinding> bv =
+ state->bindValues.at(ii);
+ for (int jj = 0; jj < bv.count; ++jj) {
+ if(bv.at(jj))
+ bv.at(jj)->setEnabled(true, QmlMetaProperty::BypassInterceptor |
+ QmlMetaProperty::DontRemoveBinding);
+ }
+ QmlEnginePrivate::clear(bv);
+ }
+
+ for (int ii = 0; ii < state->parserStatus.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlParserStatus> ps =
+ state->parserStatus.at(ii);
+
+ for (int jj = ps.count - 1; jj >= 0; --jj) {
+ QmlParserStatus *status = ps.at(jj);
+ if (status && status->d) {
+ status->d = 0;
+ status->componentComplete();
+ }
+ }
+ QmlEnginePrivate::clear(ps);
+ }
+
+ while (state->componentAttacheds) {
+ QmlComponentAttached *a = state->componentAttacheds;
+ if (a->next) a->next->prev = &state->componentAttacheds;
+ state->componentAttacheds = a->next;
+ a->prev = 0; a->next = 0;
+ emit a->completed();
+ }
+
+ state->bindValues.clear();
+ state->parserStatus.clear();
+ state->completePending = false;
+
+ enginePriv->inProgressCreations--;
+ if (0 == enginePriv->inProgressCreations) {
+ while (enginePriv->erroredBindings) {
+ qWarning().nospace() << qPrintable(enginePriv->erroredBindings->error.toString());
+ enginePriv->erroredBindings->removeError();
+ }
+ }
+ }
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Complete a component creation begin with QmlComponent::beginCreate().
+*/
+void QmlComponent::completeCreate()
+{
+ Q_D(QmlComponent);
+ d->completeCreate();
+}
+
+void QmlComponentPrivate::completeCreate()
+{
+ if (state.completePending) {
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ complete(ep, &state);
+ }
+}
+
+QmlComponentAttached::QmlComponentAttached(QObject *parent)
+: QObject(parent), prev(0), next(0)
+{
+}
+
+QmlComponentAttached::~QmlComponentAttached()
+{
+ if (prev) *prev = next;
+ if (next) next->prev = prev;
+ prev = 0;
+ next = 0;
+}
+
+/*!
+ \internal
+*/
+QmlComponentAttached *QmlComponent::qmlAttachedProperties(QObject *obj)
+{
+ QmlComponentAttached *a = new QmlComponentAttached(obj);
+
+ QmlEngine *engine = qmlEngine(obj);
+ if (!engine || !QmlEnginePrivate::get(engine)->inBeginCreate)
+ return a;
+
+ QmlEnginePrivate *p = QmlEnginePrivate::get(engine);
+
+ a->next = p->componentAttacheds;
+ a->prev = &p->componentAttacheds;
+ if (a->next) a->next->prev = &a->next;
+ p->componentAttacheds = a;
+
+ return a;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
new file mode 100644
index 0000000..342f503
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPONENT_H
+#define QMLCOMPONENT_H
+
+#include "qml.h"
+#include "qmlerror.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlCompiledData;
+class QByteArray;
+class QmlComponentPrivate;
+class QmlEngine;
+class QmlComponentAttached;
+class Q_DECLARATIVE_EXPORT QmlComponent : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlComponent)
+ Q_PROPERTY(bool isNull READ isNull NOTIFY statusChanged)
+ Q_PROPERTY(bool isReady READ isReady NOTIFY statusChanged)
+ Q_PROPERTY(bool isError READ isError NOTIFY statusChanged)
+ Q_PROPERTY(bool isLoading READ isLoading NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl url READ url CONSTANT)
+
+public:
+ QmlComponent(QObject *parent = 0);
+ QmlComponent(QmlEngine *, QObject *parent=0);
+ QmlComponent(QmlEngine *, const QString &fileName, QObject *parent = 0);
+ QmlComponent(QmlEngine *, const QUrl &url, QObject *parent = 0);
+ virtual ~QmlComponent();
+
+ Q_ENUMS(Status)
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ bool isNull() const;
+ bool isReady() const;
+ bool isError() const;
+ bool isLoading() const;
+
+ QList<QmlError> errors() const;
+ Q_INVOKABLE QString errorsString() const;
+
+ qreal progress() const;
+
+ QUrl url() const;
+
+ virtual QObject *create(QmlContext *context = 0);
+ virtual QObject *beginCreate(QmlContext *);
+ virtual void completeCreate();
+
+ Q_INVOKABLE QScriptValue createObject();
+
+ void loadUrl(const QUrl &url);
+ void setData(const QByteArray &, const QUrl &baseUrl);
+
+ void setCreationContext(QmlContext*);
+ QmlContext *creationContext() const;
+
+ static QmlComponentAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void statusChanged(QmlComponent::Status);
+ void progressChanged(qreal);
+
+protected:
+ QmlComponent(QmlComponentPrivate &dd, QObject* parent);
+
+private:
+ QmlComponent(QmlEngine *, QmlCompiledData *, int, int, QObject *parent);
+
+ friend class QmlVME;
+ friend class QmlCompositeTypeData;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QmlComponent::Status)
+QML_DECLARE_TYPE(QmlComponent)
+QML_DECLARE_TYPEINFO(QmlComponent, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QMLCOMPONENT_H
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
new file mode 100644
index 0000000..4039a61
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPONENT_P_H
+#define QMLCOMPONENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlcomponent.h"
+
+#include "qmlengine_p.h"
+#include "qmlcompositetypemanager_p.h"
+#include "qbitfield_p.h"
+#include "qmlerror.h"
+#include "qml.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QList>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlComponent;
+class QmlEngine;
+class QmlCompiledData;
+
+class QmlComponentAttached;
+class QmlComponentPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlComponent)
+
+public:
+ QmlComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), engine(0), creationContext(0) {}
+
+ QObject *create(QmlContext *context, const QBitField &);
+ QObject *beginCreate(QmlContext *, const QBitField &);
+ void completeCreate();
+
+ QmlCompositeTypeData *typeData;
+ void typeDataReady();
+ void updateProgress(qreal);
+
+ void fromTypeData(QmlCompositeTypeData *data);
+
+ QUrl url;
+ qreal progress;
+
+ int start;
+ int count;
+ QmlCompiledData *cc;
+
+ struct ConstructionState {
+ ConstructionState() : componentAttacheds(0), completePending(false) {}
+ QList<QmlEnginePrivate::SimpleList<QmlAbstractBinding> > bindValues;
+ QList<QmlEnginePrivate::SimpleList<QmlParserStatus> > parserStatus;
+ QmlComponentAttached *componentAttacheds;
+ QList<QmlError> errors;
+ bool completePending;
+ };
+ ConstructionState state;
+
+ static QObject *begin(QmlContext *ctxt, QmlEnginePrivate *enginePriv,
+ QmlCompiledData *component, int start, int count,
+ ConstructionState *state, const QBitField &bindings = QBitField());
+ static void beginDeferred(QmlContext *ctxt, QmlEnginePrivate *enginePriv,
+ QObject *object, ConstructionState *state);
+ static void complete(QmlEnginePrivate *enginePriv, ConstructionState *state);
+
+ QmlEngine *engine;
+ QmlContext *creationContext;
+
+ void clear();
+
+ static QmlComponentPrivate *get(QmlComponent *c) {
+ return static_cast<QmlComponentPrivate *>(QObjectPrivate::get(c));
+ }
+};
+
+class QmlComponentAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QmlComponentAttached(QObject *parent = 0);
+ ~QmlComponentAttached();
+
+ QmlComponentAttached **prev;
+ QmlComponentAttached *next;
+
+Q_SIGNALS:
+ void completed();
+
+private:
+ friend class QmlComponentPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCOMPONENT_P_H
diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h
new file mode 100644
index 0000000..c8b9f25
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypedata_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPOSITETYPEDATA_P_H
+#define QMLCOMPOSITETYPEDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlengine_p.h"
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompositeTypeResource;
+class QmlCompositeTypeData : public QmlRefCount
+{
+public:
+ QmlCompositeTypeData();
+ virtual ~QmlCompositeTypeData();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting,
+ WaitingResources
+ };
+ Status status;
+ enum ErrorType {
+ NoError,
+ AccessError,
+ GeneralError
+ };
+ ErrorType errorType;
+
+ QList<QmlError> errors;
+
+ QmlEnginePrivate::Imports imports;
+
+ QList<QmlCompositeTypeData *> dependants;
+
+ // Return a QmlComponent if the QmlCompositeTypeData is not in the Waiting
+ // state. The QmlComponent is owned by the QmlCompositeTypeData, so a
+ // reference should be kept to keep the QmlComponent alive.
+ QmlComponent *toComponent(QmlEngine *);
+ // Return a QmlCompiledData if possible, or 0 if an error
+ // occurs
+ QmlCompiledData *toCompiledComponent(QmlEngine *);
+
+ struct TypeReference
+ {
+ TypeReference();
+
+ QmlType *type;
+ QmlCompositeTypeData *unit;
+ };
+
+ QList<TypeReference> types;
+ QList<QmlCompositeTypeResource *> resources;
+
+ // Add or remove p as a waiter. When the QmlCompositeTypeData becomes
+ // ready, the QmlComponentPrivate::typeDataReady() method will be invoked on
+ // p. The waiter is automatically removed when the typeDataReady() method
+ // is invoked, so there is no need to call remWaiter() in this case.
+ void addWaiter(QmlComponentPrivate *p);
+ void remWaiter(QmlComponentPrivate *p);
+
+ qreal progress;
+
+private:
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+ friend class QmlDomDocument;
+
+ QmlScriptParser data;
+ QList<QmlComponentPrivate *> waiters;
+ QmlComponent *component;
+ QmlCompiledData *compiledComponent;
+};
+
+class QmlCompositeTypeResource : public QmlRefCount
+{
+public:
+ QmlCompositeTypeResource();
+ virtual ~QmlCompositeTypeResource();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+
+ QList<QmlCompositeTypeData *> dependants;
+
+ QString url;
+ QByteArray data;
+};
+
+#endif // QMLCOMPOSITETYPEDATA_P_H
+
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
new file mode 100644
index 0000000..3504fe9
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -0,0 +1,670 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcompositetypemanager_p.h"
+
+#include "qmlcompositetypedata_p.h"
+#include "qmlscriptparser_p.h"
+#include "qmlengine.h"
+#include "qmlengine_p.h"
+#include "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+#include "qmlcompiler_p.h"
+
+#include <QtNetwork/qnetworkreply.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+
+QT_BEGIN_NAMESPACE
+
+#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0))
+inline uint qHash(const QUrl &uri)
+{
+ return qHash(uri.toEncoded(QUrl::FormattingOption(0x100)));
+}
+#endif
+
+QmlCompositeTypeData::QmlCompositeTypeData()
+: status(Invalid), errorType(NoError), component(0), compiledComponent(0)
+{
+}
+
+QmlCompositeTypeData::~QmlCompositeTypeData()
+{
+ for (int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+
+ for (int ii = 0; ii < resources.count(); ++ii)
+ resources.at(ii)->release();
+
+ if (compiledComponent)
+ compiledComponent->release();
+
+ if (component)
+ delete component;
+}
+
+QmlCompositeTypeResource::QmlCompositeTypeResource()
+{
+}
+
+QmlCompositeTypeResource::~QmlCompositeTypeResource()
+{
+ for (int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+}
+
+void QmlCompositeTypeData::addWaiter(QmlComponentPrivate *p)
+{
+ waiters << p;
+}
+
+void QmlCompositeTypeData::remWaiter(QmlComponentPrivate *p)
+{
+ waiters.removeAll(p);
+}
+
+QmlComponent *QmlCompositeTypeData::toComponent(QmlEngine *engine)
+{
+ if (!component) {
+
+ QmlCompiledData *cc = toCompiledComponent(engine);
+ if (cc) {
+ component = new QmlComponent(engine, cc, -1, -1, 0);
+ cc->release();
+ } else {
+ component = new QmlComponent(engine, 0);
+ component->d_func()->url = imports.baseUrl();
+ component->d_func()->state.errors = errors;
+ }
+
+ }
+
+ return component;
+}
+
+QmlCompiledData *
+QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine)
+{
+ if (status == Complete && !compiledComponent) {
+
+ compiledComponent = new QmlCompiledData(engine);
+ compiledComponent->url = imports.baseUrl();
+ compiledComponent->name = compiledComponent->url.toString();
+
+ QmlCompiler compiler;
+ if (!compiler.compile(engine, this, compiledComponent)) {
+ status = Error;
+ errors = compiler.errors();
+ compiledComponent->release();
+ compiledComponent = 0;
+ }
+
+ // Data is no longer needed once we have a compiled component
+ data.clear();
+ }
+
+ if (compiledComponent)
+ compiledComponent->addref();
+
+ return compiledComponent;
+}
+
+QmlCompositeTypeData::TypeReference::TypeReference()
+: type(0), unit(0)
+{
+}
+
+QmlCompositeTypeManager::QmlCompositeTypeManager(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlCompositeTypeManager::~QmlCompositeTypeManager()
+{
+ for (Components::Iterator iter = components.begin(); iter != components.end();) {
+ (*iter)->release();
+ iter = components.erase(iter);
+ }
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ }
+}
+
+QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url)
+{
+ QmlCompositeTypeData *unit = components.value(url);
+
+ if (!unit) {
+ unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->progress = 0.0;
+ unit->imports.setBaseUrl(url);
+ components.insert(url, unit);
+
+ loadSource(unit);
+ }
+
+ unit->addref();
+ return unit;
+}
+
+QmlCompositeTypeData *
+QmlCompositeTypeManager::getImmediate(const QByteArray &data, const QUrl &url)
+{
+ QmlCompositeTypeData *unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->imports.setBaseUrl(url);
+ setData(unit, data, url);
+ return unit;
+}
+
+void QmlCompositeTypeManager::clearCache()
+{
+ for (Components::Iterator iter = components.begin(); iter != components.end();) {
+ if ((*iter)->status != QmlCompositeTypeData::Waiting) {
+ (*iter)->release();
+ iter = components.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ if ((*iter)->status != QmlCompositeTypeResource::Waiting) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+void QmlCompositeTypeManager::replyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeData *unit = components.value(reply->url());
+ Q_ASSERT(unit);
+
+ if (reply->error() != QNetworkReply::NoError) {
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("Network error for URL ") +
+ reply->url().toString();
+
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+
+ } else {
+ QByteArray data = reply->readAll();
+
+ setData(unit, data, reply->url());
+ }
+
+ reply->deleteLater();
+}
+
+void QmlCompositeTypeManager::resourceReplyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeResource *resource = resources.value(reply->url());
+ Q_ASSERT(resource);
+
+ if (reply->error() != QNetworkReply::NoError) {
+
+ resource->status = QmlCompositeTypeResource::Error;
+
+ } else {
+
+ resource->status = QmlCompositeTypeResource::Complete;
+ resource->data = reply->readAll();
+
+ }
+
+ doComplete(resource);
+ reply->deleteLater();
+}
+
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+void QmlCompositeTypeManager::loadResource(QmlCompositeTypeResource *resource)
+{
+ QUrl url(resource->url);
+
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+
+ QFile file(lf);
+ if (file.open(QFile::ReadOnly)) {
+ resource->data = file.readAll();
+ resource->status = QmlCompositeTypeResource::Complete;
+ } else {
+ resource->status = QmlCompositeTypeResource::Error;
+ }
+
+ } else {
+
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(resourceReplyFinished()));
+
+ }
+}
+
+void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
+{
+ QUrl url(unit->imports.baseUrl());
+
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+
+ QFile file(lf);
+ if (file.open(QFile::ReadOnly)) {
+ QByteArray data = file.readAll();
+ setData(unit, data, url);
+ } else {
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("File error for URL ") + url.toString();
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+ }
+
+ } else {
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(replyFinished()));
+ QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ }
+}
+
+void QmlCompositeTypeManager::requestProgress(qint64 received, qint64 total)
+{
+ if (total <= 0)
+ return;
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeData *unit = components.value(reply->url());
+ Q_ASSERT(unit);
+
+ unit->progress = qreal(received)/total;
+
+ foreach (QmlComponentPrivate *comp, unit->waiters)
+ comp->updateProgress(unit->progress);
+}
+
+void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit,
+ const QByteArray &data,
+ const QUrl &url)
+{
+ bool ok = true;
+ if (!unit->data.parse(data, url)) {
+ ok = false;
+ unit->errors << unit->data.errors();
+ }
+
+ if (ok) {
+ compile(unit);
+ } else {
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ doComplete(unit);
+ }
+}
+
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit)
+{
+ for (int ii = 0; ii < unit->dependants.count(); ++ii) {
+ checkComplete(unit->dependants.at(ii));
+ unit->dependants.at(ii)->release();
+ }
+ unit->dependants.clear();
+
+ while(!unit->waiters.isEmpty()) {
+ QmlComponentPrivate *p = unit->waiters.takeFirst();
+ p->typeDataReady();
+ }
+}
+
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeResource *resource)
+{
+ for (int ii = 0; ii < resource->dependants.count(); ++ii) {
+ checkComplete(resource->dependants.at(ii));
+ resource->dependants.at(ii)->release();
+ }
+ resource->dependants.clear();
+}
+
+void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
+{
+ if (unit->status != QmlCompositeTypeData::Waiting
+ && unit->status != QmlCompositeTypeData::WaitingResources)
+ return;
+
+ int waiting = 0;
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ QmlCompositeTypeResource *r = unit->resources.at(ii);
+
+ if (!r)
+ continue;
+
+ if (r->status == QmlCompositeTypeResource::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(tr("Resource %1 unavailable").arg(r->url));
+ unit->errors << error;
+ doComplete(unit);
+ return;
+ } else if (r->status == QmlCompositeTypeResource::Waiting) {
+ waiting++;
+ }
+ }
+
+ if (waiting == 0) {
+ if (unit->status == QmlCompositeTypeData::WaitingResources) {
+ waiting += resolveTypes(unit);
+ if (unit->status != QmlCompositeTypeData::Error) {
+ if (waiting)
+ unit->status = QmlCompositeTypeData::Waiting;
+ } else {
+ return;
+ }
+ } else {
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData *u = unit->types.at(ii).unit;
+
+ if (!u)
+ continue;
+
+ if (u->status == QmlCompositeTypeData::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errors = u->errors;
+ doComplete(unit);
+ return;
+ } else if (u->status == QmlCompositeTypeData::Waiting) {
+ waiting++;
+ }
+ }
+ }
+ }
+
+ if (!waiting) {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ }
+}
+
+int QmlCompositeTypeManager::resolveTypes(QmlCompositeTypeData *unit)
+{
+ // not called until all resources are loaded (they include import URLs)
+
+ int waiting = 0;
+
+ foreach (QmlScriptParser::Import imp, unit->data.imports()) {
+ QString qmldir;
+ if (imp.type == QmlScriptParser::Import::File && imp.qualifier.isEmpty()) {
+ QString importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))).toString();
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ if (unit->resources.at(ii)->url == importUrl) {
+ qmldir = QString::fromUtf8(unit->resources.at(ii)->data);
+ break;
+ }
+ }
+ }
+
+ int vmaj = -1;
+ int vmin = -1;
+ if (!imp.version.isEmpty()) {
+ int dot = imp.version.indexOf(QLatin1Char('.'));
+ if (dot < 0) {
+ vmaj = imp.version.toInt();
+ vmin = 0;
+ } else {
+ vmaj = imp.version.left(dot).toInt();
+ vmin = imp.version.mid(dot+1).toInt();
+ }
+ }
+
+ if (!QmlEnginePrivate::get(engine)->
+ addToImport(&unit->imports, qmldir, imp.uri, imp.qualifier, vmaj, vmin, imp.type))
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(tr("Import %1 unavailable").arg(imp.uri));
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ unit->errors << error;
+ doComplete(unit);
+ return 0;
+ }
+ }
+
+ QList<QmlScriptParser::TypeReference*> types = unit->data.referencedTypes();
+
+ for (int ii = 0; ii < types.count(); ++ii) {
+ QmlScriptParser::TypeReference *parserRef = types.at(ii);
+ QByteArray typeName = parserRef->name.toUtf8();
+
+ QmlCompositeTypeData::TypeReference ref;
+
+ QUrl url;
+ int majorVersion;
+ int minorVersion;
+ QmlEnginePrivate::ImportedNamespace *typeNamespace = 0;
+ if (!QmlEnginePrivate::get(engine)->resolveType(unit->imports, typeName, &ref.type, &url, &majorVersion, &minorVersion, &typeNamespace)
+ || typeNamespace)
+ {
+ // Known to not be a type:
+ // - known to be a namespace (Namespace {})
+ // - type with unknown namespace (UnknownNamespace.SomeType {})
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ if (typeNamespace)
+ error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QString::fromUtf8(typeName)));
+ else
+ error.setDescription(tr("%1 is not a type").arg(QString::fromUtf8(typeName)));
+ if (!parserRef->refObjects.isEmpty()) {
+ QmlParser::Object *obj = parserRef->refObjects.first();
+ error.setLine(obj->location.start.line);
+ error.setColumn(obj->location.start.column);
+ }
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ unit->errors << error;
+ doComplete(unit);
+ return 0;
+ }
+
+ if (ref.type) {
+ foreach (QmlParser::Object *obj, parserRef->refObjects) {
+ // store namespace for DOM
+ obj->majorVersion = majorVersion;
+ obj->minorVersion = minorVersion;
+ }
+ unit->types << ref;
+ continue;
+ }
+
+ QmlCompositeTypeData *urlUnit = components.value(url);
+
+ if (!urlUnit) {
+ urlUnit = new QmlCompositeTypeData;
+ urlUnit->status = QmlCompositeTypeData::Waiting;
+ urlUnit->imports.setBaseUrl(url);
+ components.insert(url, urlUnit);
+
+ loadSource(urlUnit);
+ }
+
+ ref.unit = urlUnit;
+ switch(urlUnit->status) {
+ case QmlCompositeTypeData::Invalid:
+ case QmlCompositeTypeData::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(tr("Type %1 unavailable").arg(QString::fromUtf8(typeName)));
+ if (!parserRef->refObjects.isEmpty()) {
+ QmlParser::Object *obj = parserRef->refObjects.first();
+ error.setLine(obj->location.start.line);
+ error.setColumn(obj->location.start.column);
+ }
+ unit->errors << error;
+ }
+ if (urlUnit->errorType != QmlCompositeTypeData::AccessError)
+ unit->errors << urlUnit->errors;
+ doComplete(unit);
+ return 0;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ case QmlCompositeTypeData::WaitingResources:
+ unit->addref();
+ ref.unit->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ unit->types << ref;
+ }
+ return waiting;
+}
+
+// ### Check ref counting in here
+void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
+{
+ int waiting = 0;
+
+ QList<QUrl> resourceList = unit->data.referencedResources();
+
+ foreach (QmlScriptParser::Import imp, unit->data.imports()) {
+ if (imp.type == QmlScriptParser::Import::File && imp.qualifier.isEmpty()) {
+ QUrl importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir")));
+ if (toLocalFileOrQrc(importUrl).isEmpty()) {
+ // Import requires remote qmldir
+ resourceList.prepend(importUrl);
+ }
+ }
+ }
+
+ for (int ii = 0; ii < resourceList.count(); ++ii) {
+ QUrl url = unit->imports.baseUrl().resolved(resourceList.at(ii));
+
+ QmlCompositeTypeResource *resource = resources.value(url);
+
+ if (!resource) {
+ resource = new QmlCompositeTypeResource;
+ resource->status = QmlCompositeTypeResource::Waiting;
+ resource->url = url.toString();
+ resources.insert(url, resource);
+
+ loadResource(resource);
+ }
+
+ switch(resource->status) {
+ case QmlCompositeTypeResource::Invalid:
+ case QmlCompositeTypeResource::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(tr("Resource %1 unavailable").arg(resource->url));
+ unit->errors << error;
+ }
+ doComplete(unit);
+ return;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ unit->addref();
+ resource->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ resource->addref();
+ unit->resources << resource;
+ }
+
+ if (waiting == 0) {
+ waiting += resolveTypes(unit);
+ if (unit->status != QmlCompositeTypeData::Error) {
+ if (!waiting) {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ } else {
+ unit->status = QmlCompositeTypeData::Waiting;
+ }
+ }
+ } else {
+ unit->status = QmlCompositeTypeData::WaitingResources;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
new file mode 100644
index 0000000..89e2353
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPOSITETYPEMANAGER_P_H
+#define QMLCOMPOSITETYPEMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlscriptparser_p.h"
+#include "qmlrefcount_p.h"
+#include "qmlerror.h"
+#include "qmlengine.h"
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompiledData;
+class QmlComponentPrivate;
+class QmlComponent;
+class QmlDomDocument;
+
+class QmlCompositeTypeData;
+class QmlCompositeTypeResource;
+
+class QmlCompositeTypeManager : public QObject
+{
+ Q_OBJECT
+public:
+ QmlCompositeTypeManager(QmlEngine *);
+ ~QmlCompositeTypeManager();
+
+ // Return a QmlCompositeTypeData for url. The QmlCompositeTypeData may be
+ // cached.
+ QmlCompositeTypeData *get(const QUrl &url);
+ // Return a QmlCompositeTypeData for data, with the provided base url. The
+ // QmlCompositeTypeData will not be cached.
+ QmlCompositeTypeData *getImmediate(const QByteArray &data, const QUrl &url);
+
+ // Clear cached types. Only types that aren't in the Waiting state will
+ // be cleared.
+ void clearCache();
+
+private Q_SLOTS:
+ void replyFinished();
+ void resourceReplyFinished();
+ void requestProgress(qint64 received, qint64 total);
+
+private:
+ void loadSource(QmlCompositeTypeData *);
+ void loadResource(QmlCompositeTypeResource *);
+ void compile(QmlCompositeTypeData *);
+ void setData(QmlCompositeTypeData *, const QByteArray &, const QUrl &);
+
+ void doComplete(QmlCompositeTypeData *);
+ void doComplete(QmlCompositeTypeResource *);
+ void checkComplete(QmlCompositeTypeData *);
+ int resolveTypes(QmlCompositeTypeData *);
+
+ QmlEngine *engine;
+ typedef QHash<QUrl, QmlCompositeTypeData *> Components;
+ Components components;
+ typedef QHash<QUrl, QmlCompositeTypeResource *> Resources;
+ Resources resources;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCOMPOSITETYPEMANAGER_P_H
+
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
new file mode 100644
index 0000000..d9fc76b
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -0,0 +1,544 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcontext.h"
+#include "qmlcontext_p.h"
+
+#include "qmlexpression_p.h"
+#include "qmlengine_p.h"
+#include "qmlengine.h"
+#include "qmlcompiledbindings_p.h"
+#include "qmlinfo.h"
+
+#include <qscriptengine.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qdebug.h>
+
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlContextPrivate::QmlContextPrivate()
+: parent(0), engine(0), isInternal(false), propertyNames(0),
+ notifyIndex(-1), highPriorityCount(0), imports(0), expressions(0), contextObjects(0),
+ idValues(0), idValueCount(0), optimizedBindings(0)
+{
+}
+
+void QmlContextPrivate::addScript(const QmlParser::Object::ScriptBlock &script, QObject *scopeObject)
+{
+ Q_Q(QmlContext);
+
+ if (!engine)
+ return;
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+ scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject));
+
+ QScriptValue scope = scriptEngine->newObject();
+ scriptContext->setActivationObject(scope);
+
+ for (int ii = 0; ii < script.codes.count(); ++ii) {
+ scriptEngine->evaluate(script.codes.at(ii), script.files.at(ii), script.lineNumbers.at(ii));
+
+ if (scriptEngine->hasUncaughtException()) {
+ QmlError error;
+ QmlExpressionPrivate::exceptionToError(scriptEngine, error);
+ qWarning().nospace() << qPrintable(error.toString());
+ }
+ }
+
+ scriptEngine->popContext();
+
+ scripts.append(scope);
+}
+
+void QmlContextPrivate::destroyed(ContextGuard *guard)
+{
+ Q_Q(QmlContext);
+
+ // process of being deleted (which is *probably* why obj has been destroyed
+ // anyway), as we're about to get deleted which will invalidate all the
+ // expressions that could depend on us
+ QObject *parent = q->parent();
+ if (parent && QObjectPrivate::get(parent)->wasDeleted)
+ return;
+
+ while(guard->bindings) {
+ QObject *o = guard->bindings->target;
+ int mi = guard->bindings->methodIndex;
+ guard->bindings->clear();
+ if (o) o->qt_metacall(QMetaObject::InvokeMetaMethod, mi, 0);
+ }
+
+ for (int ii = 0; ii < idValueCount; ++ii) {
+ if (&idValues[ii] == guard) {
+ QMetaObject::activate(q, ii + notifyIndex, 0);
+ return;
+ }
+ }
+}
+
+void QmlContextPrivate::init()
+{
+ Q_Q(QmlContext);
+
+ if (parent)
+ parent->d_func()->childContexts.insert(q);
+}
+
+/*!
+ \class QmlContext
+ \brief The QmlContext class defines a context within a QML engine.
+ \mainclass
+
+ Contexts allow data to be exposed to the QML components instantiated by the
+ QML engine.
+
+ Each QmlContext contains a set of properties, distinct from
+ its QObject properties, that allow data to be
+ explicitly bound to a context by name. The context properties are defined or
+ updated by calling QmlContext::setContextProperty(). The following example shows
+ a Qt model being bound to a context and then accessed from a QML file.
+
+ \code
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("myModel", modelData);
+
+ QmlComponent component(&engine, "ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ To simplify binding and maintaining larger data sets, QObject's can be
+ added to a QmlContext. These objects are known as the context's default
+ objects. In this case all the properties of the QObject are
+ made available by name in the context, as though they were all individually
+ added by calling QmlContext::setContextProperty(). Changes to the property's
+ values are detected through the property's notify signal. This method is
+ also slightly more faster than manually adding property values.
+
+ The following example has the same effect as the one above, but it is
+ achieved using a default object.
+
+ \code
+ class MyDataSet : ... {
+ ...
+ Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged)
+ ...
+ };
+
+ MyDataSet myDataSet;
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.addDefaultObject(&myDataSet);
+
+ QmlComponent component(&engine, "ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ Default objects added first take precedence over those added later. All properties
+ added explicitly by QmlContext::setContextProperty() take precedence over default
+ object properties.
+
+ Contexts are hierarchal, with the \l {QmlEngine::rootContext()}{root context}
+ being created by the QmlEngine. A component instantiated in a given context
+ has access to that context's data, as well as the data defined by its
+ ancestor contexts. Data values (including those added implicitly by the
+ default objects) in a context override those in ancestor contexts. Data
+ that should be available to all components instantiated by the QmlEngine
+ should be added to the \l {QmlEngine::rootContext()}{root context}.
+
+ In the following example,
+
+ \code
+ QmlEngine engine;
+ QmlContext context1(engine.rootContext());
+ QmlContext context2(&context1);
+ QmlContext context3(&context2);
+
+ context1.setContextProperty("a", 12);
+ context2.setContextProperty("b", 13);
+ context3.setContextProperty("a", 14);
+ context3.setContextProperty("c", 14);
+ \endcode
+
+ a QML component instantiated in context1 would have access to the "a" data,
+ a QML component instantiated in context2 would have access to the "a" and
+ "b" data, and a QML component instantiated in context3 would have access to
+ the "a", "b" and "c" data - although its "a" data would return 14, unlike
+ that in context1 or context2.
+*/
+
+/*! \internal */
+QmlContext::QmlContext(QmlEngine *e, bool)
+: QObject(*(new QmlContextPrivate))
+{
+ Q_D(QmlContext);
+ d->engine = e;
+ d->init();
+}
+
+/*!
+ Create a new QmlContext as a child of \a engine's root context, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlEngine *engine, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ QmlContext *parentContext = engine?engine->rootContext():0;
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
+ Create a new QmlContext with the given \a parentContext, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
+ \internal
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent, bool)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->isInternal = true;
+ d->init();
+}
+
+/*!
+ Destroys the QmlContext.
+
+ Any expressions, or sub-contexts dependent on this context will be
+ invalidated, but not destroyed (unless they are parented to the QmlContext
+ object).
+ */
+QmlContext::~QmlContext()
+{
+ Q_D(QmlContext);
+ if (d->parent)
+ d->parent->d_func()->childContexts.remove(this);
+
+ for (QSet<QmlContext *>::ConstIterator iter = d->childContexts.begin();
+ iter != d->childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ (*iter)->d_func()->parent = 0;
+ }
+
+ QmlAbstractExpression *expression = d->expressions;
+ while (expression) {
+ QmlAbstractExpression *nextExpression = expression->m_nextExpression;
+
+ expression->m_context = 0;
+ expression->m_prevExpression = 0;
+ expression->m_nextExpression = 0;
+
+ expression = nextExpression;
+ }
+
+ while (d->contextObjects) {
+ QmlDeclarativeData *co = d->contextObjects;
+ d->contextObjects = d->contextObjects->nextContextObject;
+
+ co->context = 0;
+ co->nextContextObject = 0;
+ co->prevContextObject = 0;
+ }
+
+ delete [] d->idValues;
+
+ if (d->propertyNames)
+ d->propertyNames->release();
+
+ if (d->imports)
+ d->imports->release();
+
+ if (d->optimizedBindings)
+ d->optimizedBindings->release();
+}
+
+void QmlContextPrivate::invalidateEngines()
+{
+ if (!engine)
+ return;
+ engine = 0;
+ for (QSet<QmlContext *>::ConstIterator iter = childContexts.begin();
+ iter != childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ }
+}
+
+/*
+Refreshes all expressions that could possibly depend on this context.
+Refreshing flushes all context-tree dependent caches in the expressions, and should occur every
+time the context tree *structure* (not values) changes.
+*/
+void QmlContextPrivate::refreshExpressions()
+{
+ for (QSet<QmlContext *>::ConstIterator iter = childContexts.begin();
+ iter != childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->refreshExpressions();
+ }
+
+ QmlAbstractExpression *expression = expressions;
+ while (expression) {
+ expression->refresh();
+ expression = expression->m_nextExpression;
+ }
+}
+
+/*!
+ Return the context's QmlEngine, or 0 if the context has no QmlEngine or the
+ QmlEngine was destroyed.
+*/
+QmlEngine *QmlContext::engine() const
+{
+ Q_D(const QmlContext);
+ return d->engine;
+}
+
+/*!
+ Return the context's parent QmlContext, or 0 if this context has no
+ parent or if the parent has been destroyed.
+*/
+QmlContext *QmlContext::parentContext() const
+{
+ Q_D(const QmlContext);
+ return d->parent;
+}
+
+/*!
+ Add \a defaultObject to this context. The object will be added after
+ any existing default objects.
+*/
+void QmlContext::addDefaultObject(QObject *defaultObject)
+{
+ Q_D(QmlContext);
+ d->defaultObjects.prepend(defaultObject);
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+*/
+void QmlContext::setContextProperty(const QString &name, const QVariant &value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ if (d->engine) {
+ bool ok;
+ QObject *o = QmlEnginePrivate::get(d->engine)->toQObject(value, &ok);
+ if (ok) {
+ setContextProperty(name, o);
+ return;
+ }
+ }
+
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+
+ int idx = d->propertyNames->value(name);
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
+ d->propertyValues.append(value);
+
+ d->refreshExpressions();
+ } else {
+ d->propertyValues[idx] = value;
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
+ }
+}
+
+void QmlContextPrivate::setIdProperty(int idx, QObject *obj)
+{
+ if (notifyIndex == -1) {
+ Q_Q(QmlContext);
+ notifyIndex = q->metaObject()->methodCount();
+ }
+
+ idValues[idx].priv = this;
+ idValues[idx] = obj;
+}
+
+void QmlContextPrivate::setIdPropertyData(QmlIntegerCache *data)
+{
+ Q_ASSERT(!propertyNames);
+ propertyNames = data;
+ propertyNames->addref();
+
+ idValueCount = data->count();
+ idValues = new ContextGuard[idValueCount];
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+
+ QmlContext does \bold not take ownership of \a value.
+*/
+void QmlContext::setContextProperty(const QString &name, QObject *value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+ int idx = d->propertyNames->value(name);
+
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
+ d->propertyValues.append(QVariant::fromValue(value));
+
+ d->refreshExpressions();
+ } else {
+ d->propertyValues[idx] = QVariant::fromValue(value);
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
+ }
+}
+
+QVariant QmlContext::contextProperty(const QString &name) const
+{
+ Q_D(const QmlContext);
+ QVariant value;
+ int idx = -1;
+ if (d->propertyNames)
+ idx = d->propertyNames->value(name);
+
+ if (idx == -1) {
+ QByteArray utf8Name = name.toUtf8();
+ for (int ii = d->defaultObjects.count() - 1; ii >= 0; --ii) {
+ QObject *obj = d->defaultObjects.at(ii);
+ QmlPropertyCache::Data local;
+ QmlPropertyCache::Data *property = QmlPropertyCache::property(d->engine, obj, name, local);
+
+ if (property) {
+ value = obj->metaObject()->property(property->coreIndex).read(obj);
+ break;
+ }
+ }
+ if (!value.isValid() && parentContext())
+ value = parentContext()->contextProperty(name);
+ } else {
+ value = d->propertyValues[idx];
+ }
+
+ return value;
+}
+
+/*!
+ Resolves the URL \a src relative to the URL of the
+ containing component.
+
+ \sa QmlEngine::baseUrl(), setBaseUrl()
+*/
+QUrl QmlContext::resolvedUrl(const QUrl &src)
+{
+ Q_D(QmlContext);
+ QmlContext *ctxt = this;
+ if (src.isRelative() && !src.isEmpty()) {
+ if (ctxt) {
+ while(ctxt) {
+ if(ctxt->d_func()->url.isValid())
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if (ctxt)
+ return ctxt->d_func()->url.resolved(src);
+ else if (d->engine)
+ return d->engine->baseUrl().resolved(src);
+ }
+ return QUrl();
+ } else {
+ return src;
+ }
+}
+
+/*!
+ Explicitly sets the url resolvedUrl() will use for relative references to \a baseUrl.
+
+ Calling this function will override the url of the containing
+ component used by default.
+
+ \sa resolvedUrl()
+*/
+void QmlContext::setBaseUrl(const QUrl &baseUrl)
+{
+ d_func()->url = baseUrl;
+}
+
+/*!
+ Returns the base url of the component, or the containing component
+ if none is set.
+*/
+QUrl QmlContext::baseUrl() const
+{
+ const QmlContext* p = this;
+ while (p && p->d_func()->url.isEmpty()) {
+ p = p->parentContext();
+ }
+ if (p)
+ return p->d_func()->url;
+ else
+ return QUrl();
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
new file mode 100644
index 0000000..bf389a0
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXT_H
+#define QMLCONTEXT_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlEngine;
+class QmlRefCount;
+class QmlContextPrivate;
+class QmlCompositeTypeData;
+
+class Q_DECLARATIVE_EXPORT QmlContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlContext)
+
+public:
+ QmlContext(QmlEngine *parent, QObject *objParent=0);
+ QmlContext(QmlContext *parent, QObject *objParent=0);
+ virtual ~QmlContext();
+
+ QmlEngine *engine() const;
+ QmlContext *parentContext() const;
+
+ void addDefaultObject(QObject *);
+ void setContextProperty(const QString &, QObject *);
+ void setContextProperty(const QString &, const QVariant &);
+
+ QVariant contextProperty(const QString &) const;
+
+ QUrl resolvedUrl(const QUrl &);
+
+ void setBaseUrl(const QUrl &);
+ QUrl baseUrl() const;
+
+private:
+ friend class QmlVME;
+ friend class QmlEngine;
+ friend class QmlEnginePrivate;
+ friend class QmlExpression;
+ friend class QmlExpressionPrivate;
+ friend class QmlContextScriptClass;
+ friend class QmlObjectScriptClass;
+ friend class QmlComponent;
+ friend class QmlComponentPrivate;
+ friend class QmlScriptPrivate;
+ friend class QmlBoundSignalProxy;
+ QmlContext(QmlContext *parent, QObject *objParent, bool);
+ QmlContext(QmlEngine *, bool);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCONTEXT_H
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
new file mode 100644
index 0000000..cd7e1b6
--- /dev/null
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXT_P_H
+#define QMLCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlcontext.h"
+
+#include "qmldeclarativedata_p.h"
+#include "qmlengine_p.h"
+#include "qmlintegercache_p.h"
+#include "qmltypenamecache_p.h"
+
+#include <QtCore/qhash.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/qset.h>
+
+#include <private/qobject_p.h>
+#include "qmlguard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QmlExpression;
+class QmlEngine;
+class QmlExpression;
+class QmlExpressionPrivate;
+class QmlAbstractExpression;
+class QmlBinding_Id;
+class QmlCompiledBindings;
+
+class Q_DECLARATIVE_EXPORT QmlContextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlContext)
+public:
+ QmlContextPrivate();
+
+ QmlContext *parent;
+ QmlEngine *engine;
+
+ bool isInternal;
+
+ QmlIntegerCache *propertyNames;
+ QList<QVariant> propertyValues;
+ int notifyIndex;
+
+ QObjectList defaultObjects;
+ int highPriorityCount;
+
+ QList<QScriptValue> scripts;
+ void addScript(const QmlParser::Object::ScriptBlock &, QObject *);
+
+ QUrl url;
+
+ QmlTypeNameCache *imports;
+
+ void init();
+
+ void invalidateEngines();
+ void refreshExpressions();
+ QSet<QmlContext *> childContexts;
+
+ QmlAbstractExpression *expressions;
+
+ QmlDeclarativeData *contextObjects;
+
+ struct IdNotifier
+ {
+ inline IdNotifier();
+ inline ~IdNotifier();
+
+ inline void clear();
+
+ IdNotifier *next;
+ IdNotifier**prev;
+ QObject *target;
+ int methodIndex;
+ };
+
+ struct ContextGuard : public QmlGuard<QObject>
+ {
+ inline ContextGuard();
+ inline ContextGuard &operator=(QObject *obj);
+ inline virtual void objectDestroyed(QObject *);
+
+ QmlContextPrivate *priv;
+ IdNotifier *bindings;
+ };
+ ContextGuard *idValues;
+ int idValueCount;
+ void setIdProperty(int, QObject *);
+ void setIdPropertyData(QmlIntegerCache *);
+ void destroyed(ContextGuard *);
+
+ static QmlContextPrivate *get(QmlContext *context) {
+ return static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+ }
+ static QmlContext *get(QmlContextPrivate *context) {
+ return static_cast<QmlContext *>(context->q_func());
+ }
+
+ QmlCompiledBindings *optimizedBindings;
+
+ // Only used for debugging
+ QList<QPointer<QObject> > instances;
+};
+
+QmlContextPrivate::IdNotifier::IdNotifier()
+: next(0), prev(0), target(0), methodIndex(-1)
+{
+}
+
+QmlContextPrivate::IdNotifier::~IdNotifier()
+{
+ clear();
+}
+
+void QmlContextPrivate::IdNotifier::clear()
+{
+ if (next) next->prev = prev;
+ if (prev) *prev = next;
+ next = 0; prev = 0; target = 0;
+ methodIndex = -1;
+}
+
+QmlContextPrivate::ContextGuard::ContextGuard()
+: priv(0), bindings(0)
+{
+}
+
+QmlContextPrivate::ContextGuard &QmlContextPrivate::ContextGuard::operator=(QObject *obj)
+{
+ (QmlGuard<QObject>&)*this = obj; return *this;
+}
+
+void QmlContextPrivate::ContextGuard::objectDestroyed(QObject *)
+{
+ priv->destroyed(this);
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXT_P_H
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
new file mode 100644
index 0000000..80d52ad
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcontextscriptclass_p.h"
+
+#include "qmlengine_p.h"
+#include "qmlcontext_p.h"
+#include "qmltypenamescriptclass_p.h"
+#include "qmlguard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct ContextData : public QScriptDeclarativeClass::Object {
+ ContextData() : isSharedContext(true) {}
+ ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o), isSharedContext(false) {}
+ QmlGuard<QmlContext> context;
+ QmlGuard<QObject> scopeObject;
+ bool isSharedContext;
+
+ QmlContext *getContext(QmlEngine *engine) {
+ if (isSharedContext) {
+ return QmlEnginePrivate::get(engine)->sharedContext;
+ } else {
+ return context.data();
+ }
+ }
+
+ QObject *getScope(QmlEngine *engine) {
+ if (isSharedContext) {
+ return QmlEnginePrivate::get(engine)->sharedScope;
+ } else {
+ return scopeObject.data();
+ }
+ }
+};
+
+/*
+ The QmlContextScriptClass handles property access for a QmlContext
+ via QtScript.
+ */
+QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
+: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
+ lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1)
+{
+}
+
+QmlContextScriptClass::~QmlContextScriptClass()
+{
+}
+
+QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new ContextData(context, scopeObject));
+}
+
+QScriptValue QmlContextScriptClass::newSharedContext()
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new ContextData());
+}
+
+QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
+{
+ if (scriptClass(v) != this)
+ return 0;
+
+ ContextData *data = (ContextData *)object(v);
+ return data->getContext(engine);
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+
+ lastScopeObject = 0;
+ lastContext = 0;
+ lastData = 0;
+ lastPropertyIndex = -1;
+ lastDefaultObject = -1;
+
+ QmlContext *bindContext = ((ContextData *)object)->getContext(engine);
+ QObject *scopeObject = ((ContextData *)object)->getScope(engine);
+ if (!bindContext)
+ return 0;
+
+ bool includeTypes = true;
+ while (bindContext) {
+ QScriptClass::QueryFlags rv =
+ queryProperty(bindContext, scopeObject, name, flags, includeTypes);
+ scopeObject = 0; // Only applies to the first context
+ includeTypes = false; // Only applies to the first context
+ if (rv) return rv;
+ bindContext = bindContext->parentContext();
+ }
+
+ return 0;
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject,
+ const Identifier &name,
+ QScriptClass::QueryFlags flags,
+ bool includeTypes)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1;
+ if (lastPropertyIndex != -1) {
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+
+ if (includeTypes && cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+
+ if (data) {
+ lastData = data;
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+
+ for (int ii = 0; ii < cp->scripts.count(); ++ii) {
+ lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name);
+ if (lastFunction.isValid()) {
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+
+ if (scopeObject) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(scopeObject, name, flags, bindContext,
+ QmlObjectScriptClass::ImplicitObject | QmlObjectScriptClass::SkipAttachedProperties);
+ if (rv) {
+ lastScopeObject = scopeObject;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
+ for (int ii = cp->defaultObjects.count() - 1; ii >= 0; --ii) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, bindContext,
+ QmlObjectScriptClass::ImplicitObject | QmlObjectScriptClass::SkipAttachedProperties);
+
+ if (rv) {
+ lastDefaultObject = ii;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
+ return 0;
+}
+
+QmlContextScriptClass::ScriptValue
+QmlContextScriptClass::property(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+
+ QmlContext *bindContext = lastContext;
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (lastScopeObject) {
+
+ return ep->objectClass->property(lastScopeObject, name);
+
+ } else if (lastData) {
+
+ if (lastData->type)
+ return Value(scriptEngine, ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type));
+ else
+ return Value(scriptEngine, ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace));
+
+ } else if (lastPropertyIndex != -1) {
+
+ QScriptValue rv;
+ if (lastPropertyIndex < cp->idValueCount) {
+ rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data());
+ } else {
+ QVariant value = cp->propertyValues.at(lastPropertyIndex);
+ rv = ep->scriptValueFromVariant(value);
+ }
+
+ ep->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex);
+
+ return Value(scriptEngine, rv);
+ } else if(lastDefaultObject != -1) {
+
+ // Default object property
+ return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name);
+
+ } else {
+
+ return Value(scriptEngine, lastFunction);
+
+ }
+}
+
+void QmlContextScriptClass::setProperty(Object *object, const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_UNUSED(object);
+ Q_ASSERT(lastScopeObject || lastDefaultObject != -1);
+
+ QmlContext *bindContext = lastContext;
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ if (lastScopeObject) {
+ ep->objectClass->setProperty(lastScopeObject, name, value, bindContext);
+ } else {
+ ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value,
+ bindContext);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h
new file mode 100644
index 0000000..f98d44f
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXTSCRIPTCLASS_P_H
+#define QMLCONTEXTSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmltypenamecache_p.h"
+#include "qmlscriptclass_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlContext;
+class QmlContextScriptClass : public QmlScriptClass
+{
+public:
+ QmlContextScriptClass(QmlEngine *);
+ ~QmlContextScriptClass();
+
+ QScriptValue newContext(QmlContext *, QObject * = 0);
+ QScriptValue newSharedContext();
+
+ QmlContext *contextFromValue(const QScriptValue &);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ virtual ScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+
+private:
+ QScriptClass::QueryFlags queryProperty(QmlContext *, QObject *scopeObject,
+ const Identifier &,
+ QScriptClass::QueryFlags flags,
+ bool includeTypes);
+
+ QmlEngine *engine;
+
+ QObject *lastScopeObject;
+ QmlContext *lastContext;
+ QmlTypeNameCache::Data *lastData;
+ int lastPropertyIndex;
+ int lastDefaultObject;
+ QScriptValue lastFunction;
+
+ uint m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp
new file mode 100644
index 0000000..116644a
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcustomparser_p.h"
+#include "qmlcustomparser_p_p.h"
+
+#include "qmlparser_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+/*!
+ \class QmlCustomParser
+ \brief The QmlCustomParser class allows you to add new arbitrary types to QML.
+ \internal
+
+ By subclassing QmlCustomParser, you can add a parser for
+ building a particular type.
+
+ The subclass must implement compile() and setCustomData(), and define
+ itself in the meta type system with the macro:
+
+ \code
+ QML_DEFINE_CUSTOM_TYPE(Module, MajorVersion, MinorVersion, Name, TypeClass, ParserClass)
+ \endcode
+*/
+
+/*
+ \fn QByteArray QmlCustomParser::compile(const QList<QmlCustomParserProperty> & properties)
+
+ The custom parser processes \a properties, and returns
+ a QByteArray containing data meaningful only to the
+ custom parser; the type engine will pass this same data to
+ setCustomData() when making an instance of the data.
+
+ Errors must be reported via the error() functions.
+
+ The QByteArray may be cached between executions of the system, so
+ it must contain correctly-serialized data (not, for example,
+ pointers to stack objects).
+*/
+
+/*
+ \fn void QmlCustomParser::setCustomData(QObject *object, const QByteArray &data)
+
+ This function sets \a object to have the properties defined
+ by \a data, which is a block of data previously returned by a call
+ to compile().
+
+ The \a object will be an instance of the TypeClass specified by QML_DEFINE_CUSTOM_TYPE.
+*/
+
+QmlCustomParserNode
+QmlCustomParserNodePrivate::fromObject(QmlParser::Object *root)
+{
+ QmlCustomParserNode rootNode;
+ rootNode.d->name = root->typeName;
+ rootNode.d->location = root->location.start;
+
+ for(QHash<QByteArray, Property *>::Iterator iter = root->properties.begin();
+ iter != root->properties.end();
+ ++iter) {
+
+ Property *p = *iter;
+
+ rootNode.d->properties << fromProperty(p);
+ }
+
+ return rootNode;
+}
+
+QmlCustomParserProperty
+QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p)
+{
+ QmlCustomParserProperty prop;
+ prop.d->name = p->name;
+ prop.d->isList = (p->values.count() > 1);
+ prop.d->location = p->location.start;
+
+ if (p->value) {
+ QmlCustomParserNode node = fromObject(p->value);
+ QList<QmlCustomParserProperty> props = node.properties();
+ for (int ii = 0; ii < props.count(); ++ii)
+ prop.d->values << QVariant::fromValue(props.at(ii));
+ } else {
+ for(int ii = 0; ii < p->values.count(); ++ii) {
+ Value *v = p->values.at(ii);
+ v->type = QmlParser::Value::Literal;
+
+ if(v->object) {
+ QmlCustomParserNode node = fromObject(v->object);
+ prop.d->values << QVariant::fromValue(node);
+ } else {
+ prop.d->values << QVariant::fromValue(v->value);
+ }
+
+ }
+ }
+
+ return prop;
+}
+
+QmlCustomParserNode::QmlCustomParserNode()
+: d(new QmlCustomParserNodePrivate)
+{
+}
+
+QmlCustomParserNode::QmlCustomParserNode(const QmlCustomParserNode &other)
+: d(new QmlCustomParserNodePrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserNode &QmlCustomParserNode::operator=(const QmlCustomParserNode &other)
+{
+ d->name = other.d->name;
+ d->properties = other.d->properties;
+ d->location = other.d->location;
+ return *this;
+}
+
+QmlCustomParserNode::~QmlCustomParserNode()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserNode::name() const
+{
+ return d->name;
+}
+
+QList<QmlCustomParserProperty> QmlCustomParserNode::properties() const
+{
+ return d->properties;
+}
+
+QmlParser::Location QmlCustomParserNode::location() const
+{
+ return d->location;
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty()
+: d(new QmlCustomParserPropertyPrivate)
+{
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty(const QmlCustomParserProperty &other)
+: d(new QmlCustomParserPropertyPrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserProperty &QmlCustomParserProperty::operator=(const QmlCustomParserProperty &other)
+{
+ d->name = other.d->name;
+ d->isList = other.d->isList;
+ d->values = other.d->values;
+ d->location = other.d->location;
+ return *this;
+}
+
+QmlCustomParserProperty::~QmlCustomParserProperty()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserProperty::name() const
+{
+ return d->name;
+}
+
+bool QmlCustomParserProperty::isList() const
+{
+ return d->isList;
+}
+
+QmlParser::Location QmlCustomParserProperty::location() const
+{
+ return d->location;
+}
+
+QList<QVariant> QmlCustomParserProperty::assignedValues() const
+{
+ return d->values;
+}
+
+void QmlCustomParser::clearErrors()
+{
+ exceptions.clear();
+}
+
+/*!
+ Reports an error in parsing \a prop, with the given \a description.
+
+ An error is generated referring to the position of \a node in the source file.
+*/
+void QmlCustomParser::error(const QmlCustomParserProperty& prop, const QString& description)
+{
+ QmlError error;
+ QString exceptionDescription;
+ error.setLine(prop.location().line);
+ error.setColumn(prop.location().column);
+ error.setDescription(description);
+ exceptions << error;
+}
+
+/*!
+ Reports an error in parsing \a node, with the given \a description.
+
+ An error is generated referring to the position of \a node in the source file.
+*/
+void QmlCustomParser::error(const QmlCustomParserNode& node, const QString& description)
+{
+ QmlError error;
+ QString exceptionDescription;
+ error.setLine(node.location().line);
+ error.setColumn(node.location().column);
+ error.setDescription(description);
+ exceptions << error;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h
new file mode 100644
index 0000000..9502b08
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCUSTOMPARSER_H
+#define QMLCUSTOMPARSER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlmetatype.h"
+#include "qmlerror.h"
+#include "qmlparser_p.h"
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qxmlstream.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlCustomParserPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserProperty
+{
+public:
+ QmlCustomParserProperty();
+ QmlCustomParserProperty(const QmlCustomParserProperty &);
+ QmlCustomParserProperty &operator=(const QmlCustomParserProperty &);
+ ~QmlCustomParserProperty();
+
+ QByteArray name() const;
+ QmlParser::Location location() const;
+
+ bool isList() const;
+ // Will be one of QmlParser::Variant, QmlCustomParserProperty or
+ // QmlCustomParserNode
+ QList<QVariant> assignedValues() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ friend class QmlCustomParserPropertyPrivate;
+ QmlCustomParserPropertyPrivate *d;
+};
+
+class QmlCustomParserNodePrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserNode
+{
+public:
+ QmlCustomParserNode();
+ QmlCustomParserNode(const QmlCustomParserNode &);
+ QmlCustomParserNode &operator=(const QmlCustomParserNode &);
+ ~QmlCustomParserNode();
+
+ QByteArray name() const;
+ QmlParser::Location location() const;
+
+ QList<QmlCustomParserProperty> properties() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ QmlCustomParserNodePrivate *d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlCustomParser
+{
+public:
+ virtual ~QmlCustomParser() {}
+
+ void clearErrors();
+
+ virtual QByteArray compile(const QList<QmlCustomParserProperty> &)=0;
+ virtual void setCustomData(QObject *, const QByteArray &)=0;
+
+ QList<QmlError> errors() const { return exceptions; }
+
+protected:
+ void error(const QmlCustomParserProperty&, const QString& description);
+ void error(const QmlCustomParserNode&, const QString& description);
+
+private:
+ QList<QmlError> exceptions;
+};
+
+#if defined(Q_OS_SYMBIAN)
+# define QML_DEFINE_CUSTOM_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE, CUSTOMTYPE) \
+ static int defineCustomType##NAME = qmlRegisterCustomType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE, new CUSTOMTYPE);
+#else
+# define QML_DEFINE_CUSTOM_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE, CUSTOMTYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,(VERSION_MAJ), (VERSION_MIN)>::instance(qmlRegisterCustomType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE, new CUSTOMTYPE));
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QmlCustomParserProperty)
+Q_DECLARE_METATYPE(QmlCustomParserNode)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/qml/qmlcustomparser_p_p.h b/src/declarative/qml/qmlcustomparser_p_p.h
new file mode 100644
index 0000000..c27a5bc
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCUSTOMPARSER_P_H
+#define QMLCUSTOMPARSER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlcustomparser_p.h"
+
+#include "qmlparser_p.h"
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCustomParserNodePrivate
+{
+public:
+ QByteArray name;
+ QList<QmlCustomParserProperty> properties;
+ QmlParser::Location location;
+
+ static QmlCustomParserNode fromObject(QmlParser::Object *);
+ static QmlCustomParserProperty fromProperty(QmlParser::Property *);
+};
+
+class QmlCustomParserPropertyPrivate
+{
+public:
+ QmlCustomParserPropertyPrivate()
+ : isList(false) {}
+
+ QByteArray name;
+ bool isList;
+ QmlParser::Location location;
+ QList<QVariant> values;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCUSTOMPARSER_P_H
diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h
new file mode 100644
index 0000000..e2717e0
--- /dev/null
+++ b/src/declarative/qml/qmldeclarativedata_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDECLARATIVEDATA_P_H
+#define QMLDECLARATIVEDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptvalue.h>
+#include <private/qobject_p.h>
+#include "qmlguard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompiledData;
+class QmlAbstractBinding;
+class QmlContext;
+class QmlPropertyCache;
+class Q_AUTOTEST_EXPORT QmlDeclarativeData : public QDeclarativeData
+{
+public:
+ QmlDeclarativeData(QmlContext *ctxt = 0)
+ : context(ctxt), bindings(0), nextContextObject(0), prevContextObject(0),
+ bindingBitsSize(0), bindingBits(0), outerContext(0), lineNumber(0),
+ columnNumber(0), deferredComponent(0), deferredIdx(0), attachedProperties(0),
+ propertyCache(0), guards(0) {}
+
+ virtual void destroyed(QObject *);
+
+ QmlContext *context;
+ QmlAbstractBinding *bindings;
+
+ // Linked list for QmlContext::contextObjects
+ QmlDeclarativeData *nextContextObject;
+ QmlDeclarativeData**prevContextObject;
+
+ int bindingBitsSize;
+ quint32 *bindingBits;
+ bool hasBindingBit(int) const;
+ void clearBindingBit(int);
+ void setBindingBit(QObject *obj, int);
+
+ QmlContext *outerContext; // Can't this be found from context?
+ ushort lineNumber;
+ ushort columnNumber;
+
+ QmlCompiledData *deferredComponent; // Can't this be found from the context?
+ unsigned int deferredIdx;
+
+ QHash<int, QObject *> *attachedProperties;
+
+ QScriptValue scriptValue;
+ QmlPropertyCache *propertyCache;
+
+ QmlGuard<QObject> *guards;
+
+ static QmlDeclarativeData *get(const QObject *object, bool create = false) {
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+ if (priv->declarativeData) {
+ return static_cast<QmlDeclarativeData *>(priv->declarativeData);
+ } else if (create) {
+ priv->declarativeData = new QmlDeclarativeData;
+ return static_cast<QmlDeclarativeData *>(priv->declarativeData);
+ } else {
+ return 0;
+ }
+ }
+};
+
+template<class T>
+void QmlGuard<T>::addGuard()
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(o, true);
+ next = data->guards;
+ if (next) reinterpret_cast<QmlGuard<T> *>(next)->prev = &next;
+ data->guards = reinterpret_cast<QmlGuard<QObject> *>(this);
+ prev = &data->guards;
+}
+
+template<class T>
+void QmlGuard<T>::remGuard()
+{
+ if (next) reinterpret_cast<QmlGuard<T> *>(next)->prev = prev;
+ *prev = next;
+ next = 0;
+ prev = 0;
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLDECLARATIVEDATA_P_H
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
new file mode 100644
index 0000000..52530db
--- /dev/null
+++ b/src/declarative/qml/qmldom.cpp
@@ -0,0 +1,1837 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldom.h"
+#include "qmldom_p.h"
+
+#include "qmlcompositetypedata_p.h"
+#include "qmlcompiler_p.h"
+#include "qmlengine_p.h"
+#include "qmlscriptparser_p.h"
+#include "qmlglobal_p.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate()
+: root(0)
+{
+}
+
+QmlDomDocumentPrivate::~QmlDomDocumentPrivate()
+{
+ if (root) root->release();
+}
+
+/*!
+ \class QmlDomDocument
+ \internal
+ \brief The QmlDomDocument class represents the root of a QML document
+
+ A QML document is a self-contained snippet of QML, usually contained in a
+ single file. Each document has a root object, accessible through
+ QmlDomDocument::rootObject().
+
+ The QmlDomDocument class allows the programmer to inspect a QML document by
+ calling QmlDomDocument::load().
+
+ The following example loads a QML file from disk, and prints out its root
+ object type and the properties assigned in the root object.
+ \code
+ QFile file(inputFileName);
+ file.open(QIODevice::ReadOnly);
+ QByteArray xmlData = file.readAll();
+
+ QmlDomDocument document;
+ document.load(qmlengine, xmlData);
+
+ QmlDomObject rootObject = document.rootObject();
+ qDebug() << rootObject.objectType();
+ foreach(QmlDomProperty property, rootObject.properties())
+ qDebug() << property.propertyName();
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument()
+: d(new QmlDomDocumentPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument(const QmlDomDocument &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomDocument
+*/
+QmlDomDocument::~QmlDomDocument()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomDocument.
+*/
+QmlDomDocument &QmlDomDocument::operator=(const QmlDomDocument &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns all import statements in qml.
+*/
+QList<QmlDomImport> QmlDomDocument::imports() const
+{
+ return d->imports;
+}
+
+/*!
+ Loads a QmlDomDocument from \a data. \a data should be valid QML
+ data. On success, true is returned. If the \a data is malformed, false
+ is returned and QmlDomDocument::errors() contains an error description.
+
+ \sa QmlDomDocument::loadError()
+*/
+bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data, const QUrl &url)
+{
+ d->errors.clear();
+ d->imports.clear();
+
+ QmlCompiledData *component = new QmlCompiledData(engine);
+ QmlCompiler compiler;
+
+ QmlCompositeTypeData *td = ((QmlEnginePrivate *)QmlEnginePrivate::get(engine))->typeManager.getImmediate(data, url);
+
+ if(td->status == QmlCompositeTypeData::Error) {
+ d->errors = td->errors;
+ td->release();
+ component->release();
+ return false;
+ } else if(td->status == QmlCompositeTypeData::Waiting ||
+ td->status == QmlCompositeTypeData::WaitingResources) {
+ QmlError error;
+ error.setDescription(QLatin1String("QmlDomDocument supports local types only"));
+ d->errors << error;
+ td->release();
+ component->release();
+ return false;
+ }
+
+ compiler.compile(engine, td, component);
+
+ if (compiler.isError()) {
+ d->errors = compiler.errors();
+ td->release();
+ component->release();
+ return false;
+ }
+
+ for (int i = 0; i < td->data.imports().size(); ++i) {
+ QmlScriptParser::Import parserImport = td->data.imports().at(i);
+ QmlDomImport domImport;
+ domImport.d->type = static_cast<QmlDomImportPrivate::Type>(parserImport.type);
+ domImport.d->uri = parserImport.uri;
+ domImport.d->qualifier = parserImport.qualifier;
+ domImport.d->version = parserImport.version;
+ d->imports += domImport;
+ }
+
+ if (td->data.tree()) {
+ d->root = td->data.tree();
+ d->root->addref();
+ }
+
+ component->release();
+ return true;
+}
+
+/*!
+ Returns the last load errors. The load errors will be reset after a
+ successful call to load().
+
+ \sa load()
+*/
+QList<QmlError> QmlDomDocument::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Returns the document's root object, or an invalid QmlDomObject if the
+ document has no root.
+
+ In the sample QML below, the root object will be the QmlGraphicsItem type.
+ \qml
+Item {
+ Text {
+ text: "Hello World"
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomDocument::rootObject() const
+{
+ QmlDomObject rv;
+ rv.d->object = d->root;
+ if (rv.d->object) rv.d->object->addref();
+ return rv;
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate()
+: property(0)
+{
+}
+
+QmlDomPropertyPrivate::~QmlDomPropertyPrivate()
+{
+ if (property) property->release();
+}
+
+QmlDomDynamicPropertyPrivate::QmlDomDynamicPropertyPrivate():
+ valid(false)
+{
+}
+
+QmlDomDynamicPropertyPrivate::~QmlDomDynamicPropertyPrivate()
+{
+ if (valid && property.defaultValue) property.defaultValue->release();
+}
+
+/*!
+ \class QmlDomProperty
+ \internal
+ \brief The QmlDomProperty class represents one property assignment in the
+ QML DOM tree
+
+ Properties in QML can be assigned QML \l {QmlDomValue}{values}.
+
+ \sa QmlDomObject
+*/
+
+/*!
+ Construct an invalid QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty()
+: d(new QmlDomPropertyPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty(const QmlDomProperty &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomProperty.
+*/
+QmlDomProperty::~QmlDomProperty()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomProperty.
+*/
+QmlDomProperty &QmlDomProperty::operator=(const QmlDomProperty &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if this is a valid QmlDomProperty, false otherwise.
+*/
+bool QmlDomProperty::isValid() const
+{
+ return d->property != 0;
+}
+
+
+/*!
+ Return the name of this property.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ As illustrated above, a property name can be a simple string, such as "x" or
+ "y", or a more complex "dot property", such as "font.bold". In both cases
+ the full name is returned ("x", "y" and "font.bold") by this method.
+
+ For dot properties, a split version of the name can be accessed by calling
+ QmlDomProperty::propertyNameParts().
+
+ \sa QmlDomProperty::propertyNameParts()
+*/
+QByteArray QmlDomProperty::propertyName() const
+{
+ return d->propertyName;
+}
+
+/*!
+ Return the name of this property, split into multiple parts in the case
+ of dot properties.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ For each of the properties shown above, this method would return ("x"),
+ ("y") and ("font", "bold").
+
+ \sa QmlDomProperty::propertyName()
+*/
+QList<QByteArray> QmlDomProperty::propertyNameParts() const
+{
+ if (d->propertyName.isEmpty()) return QList<QByteArray>();
+ else return d->propertyName.split('.');
+}
+
+/*!
+ Return true if this property is used as a default property in the QML
+ document.
+
+ \qml
+<Text text="hello"/>
+<Text>hello</Text>
+ \endqml
+
+ The above two examples return the same DOM tree, except that the second has
+ the default property flag set on the text property. Observe that whether
+ or not a property has isDefaultProperty set is determined by how the
+ property is used, and not only by whether the property is the types default
+ property.
+*/
+bool QmlDomProperty::isDefaultProperty() const
+{
+ return d->property && d->property->isDefault;
+}
+
+/*!
+ Returns the QmlDomValue that is assigned to this property, or an invalid
+ QmlDomValue if no value is assigned.
+*/
+QmlDomValue QmlDomProperty::value() const
+{
+ QmlDomValue rv;
+ if (d->property) {
+ rv.d->property = d->property;
+ rv.d->value = d->property->values.at(0);
+ rv.d->property->addref();
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property ID startd, or -1 if
+ the property is invalid.
+*/
+int QmlDomProperty::position() const
+{
+ if (d && d->property) {
+ return d->property->location.range.offset;
+ } else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the property ID started upto
+ the end of it, or -1 if the property is invalid.
+*/
+int QmlDomProperty::length() const
+{
+ if (d && d->property)
+ return d->property->location.range.length;
+ else
+ return -1;
+}
+
+/*!
+ Construct an invalid QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty::QmlDomDynamicProperty():
+ d(new QmlDomDynamicPropertyPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty::QmlDomDynamicProperty(const QmlDomDynamicProperty &other):
+ d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty::~QmlDomDynamicProperty()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty &QmlDomDynamicProperty::operator=(const QmlDomDynamicProperty &other)
+{
+ d = other.d;
+ return *this;
+}
+
+bool QmlDomDynamicProperty::isValid() const
+{
+ return d && d->valid;
+}
+
+/*!
+ Return the name of this dynamic property.
+
+ \qml
+Item {
+ property int count: 10;
+}
+ \endqml
+
+ As illustrated above, a dynamic property name can have a name and a
+ default value ("10").
+*/
+QByteArray QmlDomDynamicProperty::propertyName() const
+{
+ if (isValid())
+ return d->property.name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the type of the dynamic property. Note that when the property is an
+ alias property, this will return -1. Use QmlDomProperty::isAlias() to check
+ if the property is an alias.
+*/
+int QmlDomDynamicProperty::propertyType() const
+{
+ if (isValid()) {
+ switch (d->property.type) {
+ case QmlParser::Object::DynamicProperty::Bool:
+ return QMetaType::type("bool");
+
+ case QmlParser::Object::DynamicProperty::Color:
+ return QMetaType::type("QColor");
+
+ case QmlParser::Object::DynamicProperty::Date:
+ return QMetaType::type("QDate");
+
+ case QmlParser::Object::DynamicProperty::Int:
+ return QMetaType::type("int");
+
+ case QmlParser::Object::DynamicProperty::Real:
+ return QMetaType::type("double");
+
+ case QmlParser::Object::DynamicProperty::String:
+ return QMetaType::type("QString");
+
+ case QmlParser::Object::DynamicProperty::Url:
+ return QMetaType::type("QUrl");
+
+ case QmlParser::Object::DynamicProperty::Variant:
+ return QMetaType::type("QVariant");
+
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
+
+QByteArray QmlDomDynamicProperty::propertyTypeName() const
+{
+ if (isValid())
+ return d->property.customType;
+
+ return QByteArray();
+}
+
+/*!
+ Return true if this property is used as a default property in the QML
+ document.
+
+ \qml
+<Text text="hello"/>
+<Text>hello</Text>
+ \endqml
+
+ The above two examples return the same DOM tree, except that the second has
+ the default property flag set on the text property. Observe that whether
+ or not a property has isDefaultProperty set is determined by how the
+ property is used, and not only by whether the property is the types default
+ property.
+*/
+bool QmlDomDynamicProperty::isDefaultProperty() const
+{
+ if (isValid())
+ return d->property.isDefaultProperty;
+ else
+ return false;
+}
+
+/*!
+ Returns the default value as a QmlDomProperty.
+*/
+QmlDomProperty QmlDomDynamicProperty::defaultValue() const
+{
+ QmlDomProperty rp;
+
+ if (isValid() && d->property.defaultValue) {
+ rp.d->property = d->property.defaultValue;
+ rp.d->propertyName = propertyName();
+ rp.d->property->addref();
+ }
+
+ return rp;
+}
+
+/*!
+ Returns true if this dynamic property is an alias for another property,
+ false otherwise.
+*/
+bool QmlDomDynamicProperty::isAlias() const
+{
+ if (isValid())
+ return d->property.type == QmlParser::Object::DynamicProperty::Alias;
+ else
+ return false;
+}
+
+/*!
+ Returns the position in the input data where the property ID startd, or 0 if
+ the property is invalid.
+*/
+int QmlDomDynamicProperty::position() const
+{
+ if (isValid()) {
+ return d->property.location.range.offset;
+ } else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the property ID started upto
+ the end of it, or 0 if the property is invalid.
+*/
+int QmlDomDynamicProperty::length() const
+{
+ if (isValid())
+ return d->property.location.range.length;
+ else
+ return -1;
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate()
+: object(0)
+{
+}
+
+QmlDomObjectPrivate::~QmlDomObjectPrivate()
+{
+ if (object) object->release();
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties() const
+{
+ Properties rv;
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ object->properties.begin();
+ iter != object->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+ return rv;
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties(QmlParser::Property *property) const
+{
+ Properties rv;
+
+ if (property->value) {
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ property->value->properties.begin();
+ iter != property->value->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+
+ QByteArray name(property->name + '.');
+ for (Properties::Iterator iter = rv.begin(); iter != rv.end(); ++iter)
+ iter->second.prepend(name);
+
+ } else {
+ rv << qMakePair(property, property->name);
+ }
+
+ return rv;
+}
+
+/*!
+ \class QmlDomObject
+ \internal
+ \brief The QmlDomObject class represents an object instantiation.
+
+ Each object instantiated in a QML file has a corresponding QmlDomObject
+ node in the QML DOM.
+
+ In addition to the type information that determines the object to
+ instantiate, QmlDomObject's also have a set of associated QmlDomProperty's.
+ Each QmlDomProperty represents a QML property assignment on the instantiated
+ object. For example,
+
+ \qml
+QGraphicsWidget {
+ opacity: 0.5
+ size: "100x100"
+}
+ \endqml
+
+ describes a single QmlDomObject - "QGraphicsWidget" - with two properties,
+ "opacity" and "size". Obviously QGraphicsWidget has many more properties than just
+ these two, but the QML DOM representation only contains those assigned
+ values (or bindings) in the QML file.
+*/
+
+/*!
+ Construct an invalid QmlDomObject.
+*/
+QmlDomObject::QmlDomObject()
+: d(new QmlDomObjectPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomObject.
+*/
+QmlDomObject::QmlDomObject(const QmlDomObject &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomObject.
+*/
+QmlDomObject::~QmlDomObject()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomObject.
+*/
+QmlDomObject &QmlDomObject::operator=(const QmlDomObject &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if this is a valid QmlDomObject, false otherwise.
+*/
+bool QmlDomObject::isValid() const
+{
+ return d->object != 0;
+}
+
+/*!
+ Returns the fully-qualified type name of this object.
+
+ For example, the type of this object would be "Qt/4.6/Rectangle".
+ \qml
+Rectangle { }
+ \endqml
+*/
+QByteArray QmlDomObject::objectType() const
+{
+ if (d->object) return d->object->typeName;
+ else return QByteArray();
+}
+
+/*!
+ Returns the type name as referenced in the qml file.
+
+ For example, the type of this object would be "Rectangle".
+ \qml
+Rectangle { }
+ \endqml
+*/
+QByteArray QmlDomObject::objectClassName() const
+{
+ if (d->object)
+ return d->object->className;
+ else
+ return QByteArray();
+}
+
+int QmlDomObject::objectTypeMajorVersion() const
+{
+ if (d->object)
+ return d->object->majorVersion;
+ else
+ return -1;
+}
+
+int QmlDomObject::objectTypeMinorVersion() const
+{
+ if (d->object)
+ return d->object->minorVersion;
+ else
+ return -1;
+}
+
+/*!
+ Returns the QML id assigned to this object, or an empty QByteArray if no id
+ has been assigned.
+
+ For example, the object id of this object would be "MyText".
+ \qml
+Text { id: myText }
+ \endqml
+*/
+QString QmlDomObject::objectId() const
+{
+ if (d->object) {
+ return d->object->id;
+ } else {
+ return QString();
+ }
+}
+
+/*!
+ Returns the list of assigned properties on this object.
+
+ In the following example, "text" and "x" properties would be returned.
+ \qml
+Text {
+ text: "Hello world!"
+ x: 100
+}
+ \endqml
+*/
+QList<QmlDomProperty> QmlDomObject::properties() const
+{
+ QList<QmlDomProperty> rv;
+
+ if (!d->object || isComponent())
+ return rv;
+
+ QmlDomObjectPrivate::Properties properties = d->properties();
+ for (int ii = 0; ii < properties.count(); ++ii) {
+
+ QmlDomProperty domProperty;
+ domProperty.d->property = properties.at(ii).first;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = properties.at(ii).second;
+ rv << domProperty;
+
+ }
+
+ if (d->object->defaultProperty) {
+ QmlDomProperty domProperty;
+ domProperty.d->property = d->object->defaultProperty;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = d->object->defaultProperty->name;
+ rv << domProperty;
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the object's \a name property if a value has been assigned to
+ it, or an invalid QmlDomProperty otherwise.
+
+ In the example below, \c {object.property("source")} would return a valid
+ QmlDomProperty, and \c {object.property("tile")} an invalid QmlDomProperty.
+
+ \qml
+Image { source: "sample.jpg" }
+ \endqml
+*/
+QmlDomProperty QmlDomObject::property(const QByteArray &name) const
+{
+ QList<QmlDomProperty> props = properties();
+ for (int ii = 0; ii < props.count(); ++ii)
+ if (props.at(ii).propertyName() == name)
+ return props.at(ii);
+ return QmlDomProperty();
+}
+
+QList<QmlDomDynamicProperty> QmlDomObject::dynamicProperties() const
+{
+ QList<QmlDomDynamicProperty> properties;
+
+ for (int i = 0; i < d->object->dynamicProperties.size(); ++i) {
+ QmlDomDynamicProperty p;
+ p.d = new QmlDomDynamicPropertyPrivate;
+ p.d->property = d->object->dynamicProperties.at(i);
+ p.d->valid = true;
+
+ if (p.d->property.defaultValue)
+ p.d->property.defaultValue->addref();
+
+ properties.append(p);
+ }
+
+ return properties;
+}
+
+QmlDomDynamicProperty QmlDomObject::dynamicProperty(const QByteArray &name) const
+{
+ QmlDomDynamicProperty p;
+
+ if (!isValid())
+ return p;
+
+ for (int i = 0; i < d->object->dynamicProperties.size(); ++i) {
+ if (d->object->dynamicProperties.at(i).name == name) {
+ p.d = new QmlDomDynamicPropertyPrivate;
+ p.d->property = d->object->dynamicProperties.at(i);
+ if (p.d->property.defaultValue) p.d->property.defaultValue->addref();
+ p.d->valid = true;
+ }
+ }
+
+ return p;
+}
+
+/*!
+ Returns true if this object is a custom type. Custom types are special
+ types that allow embeddeding non-QML data, such as SVG or HTML data,
+ directly into QML files.
+
+ \note Currently this method will always return false, and is a placekeeper
+ for future functionality.
+
+ \sa QmlDomObject::customTypeData()
+*/
+bool QmlDomObject::isCustomType() const
+{
+ return false;
+}
+
+/*!
+ If this object represents a custom type, returns the data associated with
+ the custom type, otherwise returns an empty QByteArray().
+ QmlDomObject::isCustomType() can be used to check if this object represents
+ a custom type.
+*/
+QByteArray QmlDomObject::customTypeData() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns true if this object is a sub-component object. Sub-component
+ objects can be converted into QmlDomComponent instances by calling
+ QmlDomObject::toComponent().
+
+ \sa QmlDomObject::toComponent()
+*/
+bool QmlDomObject::isComponent() const
+{
+ return (d->object && d->object->typeName == "Qt/Component");
+}
+
+/*!
+ Returns a QmlDomComponent for this object if it is a sub-component, or
+ an invalid QmlDomComponent if not. QmlDomObject::isComponent() can be used
+ to check if this object represents a sub-component.
+
+ \sa QmlDomObject::isComponent()
+*/
+QmlDomComponent QmlDomObject::toComponent() const
+{
+ QmlDomComponent rv;
+ if (isComponent())
+ rv.d = d;
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property assignment started
+, or -1 if the property is invalid.
+*/
+int QmlDomObject::position() const
+{
+ if (d && d->object)
+ return d->object->location.range.offset;
+ else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the property assignment star
+ted upto the end of it, or -1 if the property is invalid.
+*/
+int QmlDomObject::length() const
+{
+ if (d && d->object)
+ return d->object->location.range.length;
+ else
+ return -1;
+}
+
+// Returns the URL of the type, if it is an external type, or an empty URL if
+// not
+QUrl QmlDomObject::url() const
+{
+ if (d && d->object)
+ return d->object->url;
+ else
+ return QUrl();
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate()
+: value(0)
+{
+}
+
+QmlDomBasicValuePrivate::~QmlDomBasicValuePrivate()
+{
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValueLiteral
+ \internal
+ \brief The QmlDomValueLiteral class represents a literal value.
+
+ A literal value is a simple value, written inline with the QML. In the
+ example below, the "x", "y" and "color" properties are being assigned
+ literal values.
+
+ \qml
+Rectangle {
+ x: 10
+ y: 10
+ color: "red"
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral(const QmlDomValueLiteral &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::~QmlDomValueLiteral()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueLiteral.
+*/
+QmlDomValueLiteral &QmlDomValueLiteral::operator=(const QmlDomValueLiteral &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the literal value.
+
+ In the example below, the literal value will be the string "10".
+ \qml
+Rectangle { x: 10 }
+ \endqml
+*/
+QString QmlDomValueLiteral::literal() const
+{
+ if (d->value) return d->value->primitive();
+ else return QString();
+}
+
+/*!
+ \class QmlDomValueBinding
+ \internal
+ \brief The QmlDomValueBinding class represents a property binding.
+
+ A property binding is an ECMAScript expression assigned to a property. In
+ the example below, the "x" property is being assigned a property binding.
+
+ \qml
+Rectangle { x: Other.x }
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding(const QmlDomValueBinding &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueBinding.
+*/
+QmlDomValueBinding::~QmlDomValueBinding()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueBinding.
+*/
+QmlDomValueBinding &QmlDomValueBinding::operator=(const QmlDomValueBinding &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the binding expression.
+
+ In the example below, the string "Other.x" will be returned.
+ \qml
+Rectangle { x: Other.x }
+ \endqml
+*/
+QString QmlDomValueBinding::binding() const
+{
+ if (d->value)
+ return d->value->value.asScript();
+ else
+ return QString();
+}
+
+/*!
+ \class QmlDomValueValueSource
+ \internal
+ \brief The QmlDomValueValueSource class represents a value source assignment value.
+
+ In QML, value sources are special value generating types that may be
+ assigned to properties. Value sources inherit the QmlPropertyValueSource
+ class. In the example below, the "x" property is being assigned the
+ NumberAnimation value source.
+
+ \qml
+Rectangle {
+ x: NumberAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource(const QmlDomValueValueSource &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::~QmlDomValueValueSource()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueValueSource.
+*/
+QmlDomValueValueSource &QmlDomValueValueSource::operator=(const QmlDomValueValueSource &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the value source object.
+
+ In the example below, an object representing the NumberAnimation will be
+ returned.
+ \qml
+Rectangle {
+ x: NumberAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomValueValueSource::object() const
+{
+ QmlDomObject rv;
+ if (d->value) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ \class QmlDomValueValueInterceptor
+ \internal
+ \brief The QmlDomValueValueInterceptor class represents a value interceptor assignment value.
+
+ In QML, value interceptor are special write-intercepting types that may be
+ assigned to properties. Value interceptor inherit the QmlPropertyValueInterceptor
+ class. In the example below, the "x" property is being assigned the
+ Behavior value interceptor.
+
+ \qml
+Rectangle {
+ x: Behavior { NumberAnimation { duration: 500 } }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueValueInterceptor.
+*/
+QmlDomValueValueInterceptor::QmlDomValueValueInterceptor():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueValueInterceptor.
+*/
+QmlDomValueValueInterceptor::QmlDomValueValueInterceptor(const QmlDomValueValueInterceptor &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueValueInterceptor.
+*/
+QmlDomValueValueInterceptor::~QmlDomValueValueInterceptor()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueValueInterceptor.
+*/
+QmlDomValueValueInterceptor &QmlDomValueValueInterceptor::operator=(const QmlDomValueValueInterceptor &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the value interceptor object.
+
+ In the example below, an object representing the Behavior will be
+ returned.
+ \qml
+Rectangle {
+ x: Behavior { NumberAnimation { duration: 500 } }
+}
+ \endqml
+*/
+QmlDomObject QmlDomValueValueInterceptor::object() const
+{
+ QmlDomObject rv;
+ if (d->value) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate()
+: property(0), value(0)
+{
+}
+
+QmlDomValuePrivate::~QmlDomValuePrivate()
+{
+ if (property) property->release();
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValue
+ \internal
+ \brief The QmlDomValue class represents a generic Qml value.
+
+ QmlDomValue's can be assigned to QML \l {QmlDomProperty}{properties}. In
+ QML, properties can be assigned various different values, including basic
+ literals, property bindings, property value sources, objects and lists of
+ values. The QmlDomValue class allows a programmer to determine the specific
+ value type being assigned and access more detailed information through a
+ corresponding value type class.
+
+ For example, in the following example,
+
+ \qml
+Text {
+ text: "Hello World!"
+ y: Other.y
+}
+ \endqml
+
+ The text property is being assigned a literal, and the y property a property
+ binding. To output the values assigned to the text and y properties in the
+ above example from C++,
+
+ \code
+ QmlDomDocument document;
+ QmlDomObject root = document.rootObject();
+
+ QmlDomProperty text = root.property("text");
+ if (text.value().isLiteral()) {
+ QmlDomValueLiteral literal = text.value().toLiteral();
+ qDebug() << literal.literal();
+ }
+
+ QmlDomProperty y = root.property("y");
+ if (y.value().isBinding()) {
+ QmlDomValueBinding binding = y.value().toBinding();
+ qDebug() << binding.binding();
+ }
+ \endcode
+*/
+
+/*!
+ Construct an invalid QmlDomValue.
+*/
+QmlDomValue::QmlDomValue()
+: d(new QmlDomValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValue.
+*/
+QmlDomValue::QmlDomValue(const QmlDomValue &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValue
+*/
+QmlDomValue::~QmlDomValue()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValue.
+*/
+QmlDomValue &QmlDomValue::operator=(const QmlDomValue &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \enum QmlDomValue::Type
+
+ The type of the QmlDomValue node.
+
+ \value Invalid The QmlDomValue is invalid.
+ \value Literal The QmlDomValue is a literal value assignment. Use QmlDomValue::toLiteral() to access the type instance.
+ \value PropertyBinding The QmlDomValue is a property binding. Use QmlDomValue::toBinding() to access the type instance.
+ \value ValueSource The QmlDomValue is a property value source. Use QmlDomValue::toValueSource() to access the type instance.
+ \value ValueInterceptor The QmlDomValue is a property value interceptor. Use QmlDomValue::toValueInterceptor() to access the type instance.
+ \value Object The QmlDomValue is an object assignment. Use QmlDomValue::toObject() to access the type instnace.
+ \value List The QmlDomValue is a list of other values. Use QmlDomValue::toList() to access the type instance.
+*/
+
+/*!
+ Returns the type of this QmlDomValue.
+*/
+QmlDomValue::Type QmlDomValue::type() const
+{
+ if (d->property)
+ if (QmlMetaType::isList(d->property->type) ||
+ QmlMetaType::isQmlList(d->property->type) ||
+ (d->property && d->property->values.count() > 1))
+ return List;
+
+ QmlParser::Value *value = d->value;
+ if (!value && !d->property)
+ return Invalid;
+
+ switch(value->type) {
+ case QmlParser::Value::Unknown:
+ return Invalid;
+ case QmlParser::Value::Literal:
+ return Literal;
+ case QmlParser::Value::PropertyBinding:
+ return PropertyBinding;
+ case QmlParser::Value::ValueSource:
+ return ValueSource;
+ case QmlParser::Value::ValueInterceptor:
+ return ValueInterceptor;
+ case QmlParser::Value::CreatedObject:
+ return Object;
+ case QmlParser::Value::SignalObject:
+ return Invalid;
+ case QmlParser::Value::SignalExpression:
+ return Literal;
+ case QmlParser::Value::Id:
+ return Literal;
+ }
+ return Invalid;
+}
+
+/*!
+ Returns true if this is an invalid value, otherwise false.
+*/
+bool QmlDomValue::isInvalid() const
+{
+ return type() == Invalid;
+}
+
+/*!
+ Returns true if this is a literal value, otherwise false.
+*/
+bool QmlDomValue::isLiteral() const
+{
+ return type() == Literal;
+}
+
+/*!
+ Returns true if this is a property binding value, otherwise false.
+*/
+bool QmlDomValue::isBinding() const
+{
+ return type() == PropertyBinding;
+}
+
+/*!
+ Returns true if this is a value source value, otherwise false.
+*/
+bool QmlDomValue::isValueSource() const
+{
+ return type() == ValueSource;
+}
+
+/*!
+ Returns true if this is a value interceptor value, otherwise false.
+*/
+bool QmlDomValue::isValueInterceptor() const
+{
+ return type() == ValueInterceptor;
+}
+
+/*!
+ Returns true if this is an object value, otherwise false.
+*/
+bool QmlDomValue::isObject() const
+{
+ return type() == Object;
+}
+
+/*!
+ Returns true if this is a list value, otherwise false.
+*/
+bool QmlDomValue::isList() const
+{
+ return type() == List;
+}
+
+/*!
+ Returns a QmlDomValueLiteral if this value is a literal type, otherwise
+ returns an invalid QmlDomValueLiteral.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueLiteral QmlDomValue::toLiteral() const
+{
+ QmlDomValueLiteral rv;
+ if (type() == Literal) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueBinding if this value is a property binding type,
+ otherwise returns an invalid QmlDomValueBinding.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueBinding QmlDomValue::toBinding() const
+{
+ QmlDomValueBinding rv;
+ if (type() == PropertyBinding) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueValueSource if this value is a property value source
+ type, otherwise returns an invalid QmlDomValueValueSource.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueValueSource QmlDomValue::toValueSource() const
+{
+ QmlDomValueValueSource rv;
+ if (type() == ValueSource) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueValueInterceptor if this value is a property value interceptor
+ type, otherwise returns an invalid QmlDomValueValueInterceptor.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueValueInterceptor QmlDomValue::toValueInterceptor() const
+{
+ QmlDomValueValueInterceptor rv;
+ if (type() == ValueInterceptor) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomObject if this value is an object assignment type, otherwise
+ returns an invalid QmlDomObject.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomObject QmlDomValue::toObject() const
+{
+ QmlDomObject rv;
+ if (type() == Object) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomList if this value is a list type, otherwise returns an
+ invalid QmlDomList.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomList QmlDomValue::toList() const
+{
+ QmlDomList rv;
+ if (type() == List) {
+ rv.d = d;
+ }
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property value startd, or -1
+ if the value is invalid.
+*/
+int QmlDomValue::position() const
+{
+ if (type() == Invalid)
+ return -1;
+ else
+ return d->value->location.range.offset;
+}
+
+/*!
+ Returns the length in the input data from where the property value started u
+pto the end of it, or -1 if the value is invalid.
+*/
+int QmlDomValue::length() const
+{
+ if (type() == Invalid)
+ return -1;
+ else
+ return d->value->location.range.length;
+}
+
+/*!
+ \class QmlDomList
+ \internal
+ \brief The QmlDomList class represents a list of values assigned to a QML property.
+
+ Lists of values can be assigned to properties. For example, the following
+ example assigns multiple objects to Item's "children" property
+ \qml
+Item {
+ children: [
+ Text { },
+ Rectangle { }
+ ]
+}
+ \endqml
+
+ Lists can also be implicitly created by assigning multiple
+ \l {QmlDomValueValueSource}{value sources} or constants to a property.
+ \qml
+Item {
+ x: 10
+ x: NumberAnimation {
+ running: false
+ from: 0
+ to: 100
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomList.
+*/
+QmlDomList::QmlDomList()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomList.
+*/
+QmlDomList::QmlDomList(const QmlDomList &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomList.
+*/
+QmlDomList::~QmlDomList()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomList.
+*/
+QmlDomList &QmlDomList::operator=(const QmlDomList &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the list of QmlDomValue's.
+*/
+QList<QmlDomValue> QmlDomList::values() const
+{
+ QList<QmlDomValue> rv;
+ if (!d->property)
+ return rv;
+
+ for (int ii = 0; ii < d->property->values.count(); ++ii) {
+ QmlDomValue v;
+ v.d->value = d->property->values.at(ii);
+ v.d->value->addref();
+ rv << v;
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the list started, or -1 if
+ the property is invalid.
+*/
+int QmlDomList::position() const
+{
+ if (d && d->property) {
+ return d->property->listValueRange.offset;
+ } else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the list started upto
+ the end of it, or 0 if the property is invalid.
+*/
+int QmlDomList::length() const
+{
+ if (d && d->property)
+ return d->property->listValueRange.length;
+ else
+ return -1;
+}
+
+/*!
+ Returns a list of positions of the commas in the QML file.
+*/
+QList<int> QmlDomList:: commaPositions() const
+{
+ if (d && d->property)
+ return d->property->listCommaPositions;
+ else
+ return QList<int>();
+}
+
+/*!
+ \class QmlDomComponent
+ \internal
+ \brief The QmlDomComponent class represents sub-component within a QML document.
+
+ Sub-components are QmlComponents defined within a QML document. The
+ following example shows the definition of a sub-component with the id
+ "listDelegate".
+
+ \qml
+Item {
+ Component {
+ id: listDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+
+ Like QmlDomDocument's, components contain a single root object.
+*/
+
+/*!
+ Construct an empty QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent(const QmlDomComponent &other)
+: QmlDomObject(other)
+{
+}
+
+/*!
+ Destroy the QmlDomComponent.
+*/
+QmlDomComponent::~QmlDomComponent()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomComponent.
+*/
+QmlDomComponent &QmlDomComponent::operator=(const QmlDomComponent &other)
+{
+ static_cast<QmlDomObject &>(*this) = other;
+ return *this;
+}
+
+/*!
+ Returns the component's root object.
+
+ In the example below, the root object is the "Text" object.
+ \qml
+Item {
+ Component {
+ id: listDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomComponent::componentRoot() const
+{
+ QmlDomObject rv;
+ if (d->object) {
+ QmlParser::Object *obj = 0;
+ if (d->object->defaultProperty &&
+ d->object->defaultProperty->values.count() == 1 &&
+ d->object->defaultProperty->values.at(0)->object)
+ obj = d->object->defaultProperty->values.at(0)->object;
+
+ if (obj) {
+ rv.d->object = obj;
+ rv.d->object->addref();
+ }
+ }
+
+ return rv;
+}
+
+QmlDomImportPrivate::QmlDomImportPrivate()
+: type(File)
+{
+}
+
+QmlDomImportPrivate::~QmlDomImportPrivate()
+{
+}
+
+/*!
+ \class QmlDomImport
+ \internal
+ \brief The QmlDomImport class represents an import statement.
+*/
+
+/*!
+ Construct an empty QmlDomImport.
+*/
+QmlDomImport::QmlDomImport()
+: d(new QmlDomImportPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomImport.
+*/
+QmlDomImport::QmlDomImport(const QmlDomImport &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomImport.
+*/
+QmlDomImport::~QmlDomImport()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomImport.
+*/
+QmlDomImport &QmlDomImport::operator=(const QmlDomImport &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the type of the import.
+ */
+QmlDomImport::Type QmlDomImport::type() const
+{
+ return static_cast<QmlDomImport::Type>(d->type);
+}
+
+/*!
+ Returns the URI of the import (e.g. 'subdir' or 'com.nokia.Qt')
+ */
+QString QmlDomImport::uri() const
+{
+ return d->uri;
+}
+
+/*!
+ Returns the version specified by the import. An empty string if no version was specified.
+ */
+QString QmlDomImport::version() const
+{
+ return d->version;
+}
+
+/*!
+ Returns the (optional) qualifier string (the token following the 'as' keyword) of the import.
+ */
+QString QmlDomImport::qualifier() const
+{
+ return d->qualifier;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h
new file mode 100644
index 0000000..8442f49
--- /dev/null
+++ b/src/declarative/qml/qmldom.h
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDOM_H
+#define QMLDOM_H
+
+#include "qmlerror.h"
+
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QByteArray;
+class QmlDomObject;
+class QmlDomList;
+class QmlDomValue;
+class QmlEngine;
+class QmlDomComponent;
+class QmlDomImport;
+class QIODevice;
+
+class QmlDomDocumentPrivate;
+
+class Q_DECLARATIVE_EXPORT QmlDomDocument
+{
+public:
+ QmlDomDocument();
+ QmlDomDocument(const QmlDomDocument &);
+ ~QmlDomDocument();
+ QmlDomDocument &operator=(const QmlDomDocument &);
+
+ QList<QmlDomImport> imports() const;
+
+ QList<QmlError> errors() const;
+ bool load(QmlEngine *, const QByteArray &, const QUrl & = QUrl());
+
+ QmlDomObject rootObject() const;
+
+private:
+ QSharedDataPointer<QmlDomDocumentPrivate> d;
+};
+
+class QmlDomPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomProperty
+{
+public:
+ QmlDomProperty();
+ QmlDomProperty(const QmlDomProperty &);
+ ~QmlDomProperty();
+ QmlDomProperty &operator=(const QmlDomProperty &);
+
+ bool isValid() const;
+
+ QByteArray propertyName() const;
+ QList<QByteArray> propertyNameParts() const;
+
+ bool isDefaultProperty() const;
+
+ QmlDomValue value() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomObject;
+ friend class QmlDomDynamicProperty;
+ QSharedDataPointer<QmlDomPropertyPrivate> d;
+};
+
+class QmlDomDynamicPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomDynamicProperty
+{
+public:
+ QmlDomDynamicProperty();
+ QmlDomDynamicProperty(const QmlDomDynamicProperty &);
+ ~QmlDomDynamicProperty();
+ QmlDomDynamicProperty &operator=(const QmlDomDynamicProperty &);
+
+ bool isValid() const;
+
+ QByteArray propertyName() const;
+ int propertyType() const;
+ QByteArray propertyTypeName() const;
+
+ bool isDefaultProperty() const;
+ QmlDomProperty defaultValue() const;
+
+ bool isAlias() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomObject;
+ QSharedDataPointer<QmlDomDynamicPropertyPrivate> d;
+};
+
+class QmlDomObjectPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomObject
+{
+public:
+ QmlDomObject();
+ QmlDomObject(const QmlDomObject &);
+ ~QmlDomObject();
+ QmlDomObject &operator=(const QmlDomObject &);
+
+ bool isValid() const;
+
+ QByteArray objectType() const;
+ QByteArray objectClassName() const;
+
+ int objectTypeMajorVersion() const;
+ int objectTypeMinorVersion() const;
+
+ QString objectId() const;
+
+ QList<QmlDomProperty> properties() const;
+ QmlDomProperty property(const QByteArray &) const;
+
+ QList<QmlDomDynamicProperty> dynamicProperties() const;
+ QmlDomDynamicProperty dynamicProperty(const QByteArray &) const;
+
+ bool isCustomType() const;
+ QByteArray customTypeData() const;
+
+ bool isComponent() const;
+ QmlDomComponent toComponent() const;
+
+ int position() const;
+ int length() const;
+
+ QUrl url() const;
+private:
+ friend class QmlDomDocument;
+ friend class QmlDomComponent;
+ friend class QmlDomValue;
+ friend class QmlDomValueValueSource;
+ friend class QmlDomValueValueInterceptor;
+ QSharedDataPointer<QmlDomObjectPrivate> d;
+};
+
+class QmlDomValuePrivate;
+class QmlDomBasicValuePrivate;
+class Q_DECLARATIVE_EXPORT QmlDomValueLiteral
+{
+public:
+ QmlDomValueLiteral();
+ QmlDomValueLiteral(const QmlDomValueLiteral &);
+ ~QmlDomValueLiteral();
+ QmlDomValueLiteral &operator=(const QmlDomValueLiteral &);
+
+ QString literal() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueBinding
+{
+public:
+ QmlDomValueBinding();
+ QmlDomValueBinding(const QmlDomValueBinding &);
+ ~QmlDomValueBinding();
+ QmlDomValueBinding &operator=(const QmlDomValueBinding &);
+
+ QString binding() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueValueSource
+{
+public:
+ QmlDomValueValueSource();
+ QmlDomValueValueSource(const QmlDomValueValueSource &);
+ ~QmlDomValueValueSource();
+ QmlDomValueValueSource &operator=(const QmlDomValueValueSource &);
+
+ QmlDomObject object() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueValueInterceptor
+{
+public:
+ QmlDomValueValueInterceptor();
+ QmlDomValueValueInterceptor(const QmlDomValueValueInterceptor &);
+ ~QmlDomValueValueInterceptor();
+ QmlDomValueValueInterceptor &operator=(const QmlDomValueValueInterceptor &);
+
+ QmlDomObject object() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+
+class Q_DECLARATIVE_EXPORT QmlDomComponent : public QmlDomObject
+{
+public:
+ QmlDomComponent();
+ QmlDomComponent(const QmlDomComponent &);
+ ~QmlDomComponent();
+ QmlDomComponent &operator=(const QmlDomComponent &);
+
+ QmlDomObject componentRoot() const;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValue
+{
+public:
+ enum Type {
+ Invalid,
+ Literal,
+ PropertyBinding,
+ ValueSource,
+ ValueInterceptor,
+ Object,
+ List
+ };
+
+ QmlDomValue();
+ QmlDomValue(const QmlDomValue &);
+ ~QmlDomValue();
+ QmlDomValue &operator=(const QmlDomValue &);
+
+ Type type() const;
+
+ bool isInvalid() const;
+ bool isLiteral() const;
+ bool isBinding() const;
+ bool isValueSource() const;
+ bool isValueInterceptor() const;
+ bool isObject() const;
+ bool isList() const;
+
+ QmlDomValueLiteral toLiteral() const;
+ QmlDomValueBinding toBinding() const;
+ QmlDomValueValueSource toValueSource() const;
+ QmlDomValueValueInterceptor toValueInterceptor() const;
+ QmlDomObject toObject() const;
+ QmlDomList toList() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomProperty;
+ friend class QmlDomList;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomList
+{
+public:
+ QmlDomList();
+ QmlDomList(const QmlDomList &);
+ ~QmlDomList();
+ QmlDomList &operator=(const QmlDomList &);
+
+ QList<QmlDomValue> values() const;
+
+ int position() const;
+ int length() const;
+
+ QList<int> commaPositions() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+class QmlDomImportPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomImport
+{
+public:
+ enum Type { Library, File };
+
+ QmlDomImport();
+ QmlDomImport(const QmlDomImport &);
+ ~QmlDomImport();
+ QmlDomImport &operator=(const QmlDomImport &);
+
+ Type type() const;
+ QString uri() const;
+ QString version() const;
+ QString qualifier() const;
+
+private:
+ friend class QmlDomDocument;
+ QSharedDataPointer<QmlDomImportPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_H
diff --git a/src/declarative/qml/qmldom_p.h b/src/declarative/qml/qmldom_p.h
new file mode 100644
index 0000000..df6a980
--- /dev/null
+++ b/src/declarative/qml/qmldom_p.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDOM_P_H
+#define QMLDOM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlparser_p.h"
+
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_NAMESPACE
+
+class QmlDomDocumentPrivate : public QSharedData
+{
+public:
+ QmlDomDocumentPrivate();
+ QmlDomDocumentPrivate(const QmlDomDocumentPrivate &o)
+ : QSharedData(o) { qFatal("Not impl"); }
+ ~QmlDomDocumentPrivate();
+
+ QList<QmlError> errors;
+ QList<QmlDomImport> imports;
+ QmlParser::Object *root;
+ QList<int> automaticSemicolonOffsets;
+};
+
+class QmlDomObjectPrivate : public QSharedData
+{
+public:
+ QmlDomObjectPrivate();
+ QmlDomObjectPrivate(const QmlDomObjectPrivate &o)
+ : QSharedData(o) { qFatal("Not impl"); }
+ ~QmlDomObjectPrivate();
+
+ typedef QList<QPair<QmlParser::Property *, QByteArray> > Properties;
+ Properties properties() const;
+ Properties properties(QmlParser::Property *) const;
+
+ QmlParser::Object *object;
+};
+
+class QmlDomPropertyPrivate : public QSharedData
+{
+public:
+ QmlDomPropertyPrivate();
+ QmlDomPropertyPrivate(const QmlDomPropertyPrivate &o)
+ : QSharedData(o) { qFatal("Not impl"); }
+ ~QmlDomPropertyPrivate();
+
+ QByteArray propertyName;
+ QmlParser::Property *property;
+};
+
+class QmlDomDynamicPropertyPrivate : public QSharedData
+{
+public:
+ QmlDomDynamicPropertyPrivate();
+ QmlDomDynamicPropertyPrivate(const QmlDomDynamicPropertyPrivate &o)
+ : QSharedData(o) { qFatal("Not impl"); }
+ ~QmlDomDynamicPropertyPrivate();
+
+ bool valid;
+ QmlParser::Object::DynamicProperty property;
+};
+
+class QmlDomValuePrivate : public QSharedData
+{
+public:
+ QmlDomValuePrivate();
+ QmlDomValuePrivate(const QmlDomValuePrivate &o)
+ : QSharedData(o) { qFatal("Not impl"); }
+ ~QmlDomValuePrivate();
+
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+};
+
+class QmlDomBasicValuePrivate : public QSharedData
+{
+public:
+ QmlDomBasicValuePrivate();
+ QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &o)
+ : QSharedData(o) { qFatal("Not impl"); }
+ ~QmlDomBasicValuePrivate();
+
+ QmlParser::Value *value;
+};
+
+class QmlDomImportPrivate : public QSharedData
+{
+public:
+ QmlDomImportPrivate();
+ QmlDomImportPrivate(const QmlDomImportPrivate &o)
+ : QSharedData(o) { qFatal("Not impl"); }
+ ~QmlDomImportPrivate();
+
+ enum Type { Library, File };
+
+ Type type;
+ QString uri;
+ QString version;
+ QString qualifier;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLDOM_P_H
+
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
new file mode 100644
index 0000000..cdbe5f3
--- /dev/null
+++ b/src/declarative/qml/qmlengine.cpp
@@ -0,0 +1,1659 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlengine_p.h"
+#include "qmlengine.h"
+
+#include "qmlcontext_p.h"
+#include "qmlcompiler_p.h"
+#include "qmlglobalscriptclass_p.h"
+#include "qml.h"
+#include "qmlcontext.h"
+#include "qmlexpression.h"
+#include "qmlcomponent.h"
+#include "qmlmetaproperty_p.h"
+#include "qmlmoduleplugin.h"
+#include "qmlbinding_p.h"
+#include "qmlvme_p.h"
+#include "qmlenginedebug_p.h"
+#include "qmlstringconverters_p.h"
+#include "qmlxmlhttprequest_p.h"
+#include "qmlsqldatabase_p.h"
+#include "qmltypenamescriptclass_p.h"
+#include "qmllistscriptclass_p.h"
+#include "qmlscriptstring.h"
+#include "qmlglobal_p.h"
+#include "qmlworkerscript_p.h"
+#include "qmlcomponent_p.h"
+#include "qmlscriptclass_p.h"
+#include "qmlnetworkaccessmanagerfactory.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QtCore/qmetaobject.h>
+#include <QScriptClass>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QNetworkAccessManager>
+#include <QDesktopServices>
+#include <QTimer>
+#include <QList>
+#include <QPair>
+#include <QDebug>
+#include <QMetaObject>
+#include <QStack>
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qsound.h>
+#include <QGraphicsObject>
+#include <QtCore/qcryptographichash.h>
+
+#include <private/qfactoryloader_p.h>
+#include <private/qobject_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+
+#ifdef Q_OS_WIN // for %APPDATA%
+#include <qt_windows.h>
+#include <qlibrary.h>
+
+#define CSIDL_APPDATA 0x001a // <username>\Application Data
+#endif
+
+Q_DECLARE_METATYPE(QmlMetaProperty)
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlImportTrace, QML_IMPORT_TRACE)
+
+QML_DEFINE_TYPE(Qt,4,6,QtObject,QObject)
+/*!
+ \qmlclass QtObject QObject
+ \brief The QtObject element is the most basic element in QML
+
+ The QtObject element is a non-visual element which contains only
+ the objectName property. It is useful for when you need an extremely
+ lightweight element to place your own custom properties in.
+
+ It can also be useful for C++ integration, as it is just a plain QObject. See
+ the QObject documentation for further details.
+*/
+/*!
+ \qmlproperty string QtObject::objectName
+ This property allows you to give a name to this specific object instance.
+
+ See \l{scripting.html#accessing-child-qobjects}{Accessing Child QObjects}
+ in the scripting documentation for details how objectName can be used from
+ scripts.
+*/
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
+: captureProperties(false), rootContext(0), currentExpression(0), isDebugging(false),
+ contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0),
+ globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0),
+ scriptEngine(this), workerScriptEngine(0), componentAttacheds(0), inBeginCreate(false),
+ networkAccessManager(0), networkAccessManagerFactory(0),
+ typeManager(e), uniqueId(1)
+{
+ globalClass = new QmlGlobalScriptClass(&scriptEngine);
+ fileImportPath.append(QLibraryInfo::location(QLibraryInfo::DataPath)+QDir::separator()+QLatin1String("qml"));
+}
+
+QUrl QmlScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url)
+{
+ if (p) {
+ QmlContext *ctxt = QmlEnginePrivate::get(this)->getContext(context);
+ Q_ASSERT(ctxt);
+ return ctxt->resolvedUrl(url);
+ }
+ return baseUrl.resolved(url);
+}
+
+QmlScriptEngine::QmlScriptEngine(QmlEnginePrivate *priv)
+: p(priv), sqlQueryClass(0), namedNodeMapClass(0), nodeListClass(0)
+{
+ // Note that all documentation for stuff put on the global object goes in
+ // doc/src/declarative/globalobject.qdoc
+
+ bool mainthread = priv != 0;
+
+ QScriptValue qtObject =
+ newQMetaObject(StaticQtMetaObject::get());
+ globalObject().setProperty(QLatin1String("Qt"), qtObject);
+
+ offlineStoragePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation).replace(QLatin1Char('/'), QDir::separator())
+ + QDir::separator() + QLatin1String("QML")
+ + QDir::separator() + QLatin1String("OfflineStorage");
+
+
+ qt_add_qmlxmlhttprequest(this);
+ qt_add_qmlsqldatabase(this);
+ // XXX A Multimedia "Qt.Sound" class also needs to be made available,
+ // XXX but we don't want a dependency in that cirection.
+ // XXX When the above a done some better way, that way should also be
+ // XXX used to add Qt.Sound class.
+
+
+ //types
+ qtObject.setProperty(QLatin1String("rgba"), newFunction(QmlEnginePrivate::rgba, 4));
+ qtObject.setProperty(QLatin1String("hsla"), newFunction(QmlEnginePrivate::hsla, 4));
+ qtObject.setProperty(QLatin1String("rect"), newFunction(QmlEnginePrivate::rect, 4));
+ qtObject.setProperty(QLatin1String("point"), newFunction(QmlEnginePrivate::point, 2));
+ qtObject.setProperty(QLatin1String("size"), newFunction(QmlEnginePrivate::size, 2));
+ qtObject.setProperty(QLatin1String("vector3d"), newFunction(QmlEnginePrivate::vector, 3));
+
+ if (mainthread) {
+ //color helpers
+ qtObject.setProperty(QLatin1String("lighter"), newFunction(QmlEnginePrivate::lighter, 1));
+ qtObject.setProperty(QLatin1String("darker"), newFunction(QmlEnginePrivate::darker, 1));
+ qtObject.setProperty(QLatin1String("tint"), newFunction(QmlEnginePrivate::tint, 2));
+ }
+
+ //misc methods
+ qtObject.setProperty(QLatin1String("closestAngle"), newFunction(QmlEnginePrivate::closestAngle, 2));
+ qtObject.setProperty(QLatin1String("playSound"), newFunction(QmlEnginePrivate::playSound, 1));
+ qtObject.setProperty(QLatin1String("openUrlExternally"),newFunction(QmlEnginePrivate::desktopOpenUrl, 1));
+ qtObject.setProperty(QLatin1String("md5"),newFunction(QmlEnginePrivate::md5, 1));
+ qtObject.setProperty(QLatin1String("btoa"),newFunction(QmlEnginePrivate::btoa, 1));
+ qtObject.setProperty(QLatin1String("atob"),newFunction(QmlEnginePrivate::atob, 1));
+ qtObject.setProperty(QLatin1String("quit"), newFunction(QmlEnginePrivate::quit, 0));
+ qtObject.setProperty(QLatin1String("resolvedUrl"),newFunction(QmlScriptEngine::resolvedUrl, 1));
+
+ //firebug/webkit compat
+ QScriptValue consoleObject = newObject();
+ consoleObject.setProperty(QLatin1String("log"),newFunction(QmlEnginePrivate::consoleLog, 1));
+ consoleObject.setProperty(QLatin1String("debug"),newFunction(QmlEnginePrivate::consoleLog, 1));
+ globalObject().setProperty(QLatin1String("console"), consoleObject);
+
+ if (mainthread) {
+ globalObject().setProperty(QLatin1String("createQmlObject"),
+ newFunction(QmlEnginePrivate::createQmlObject, 1));
+ globalObject().setProperty(QLatin1String("createComponent"),
+ newFunction(QmlEnginePrivate::createComponent, 1));
+ }
+
+ // translation functions need to be installed
+ // before the global script class is constructed (QTBUG-6437)
+ installTranslatorFunctions();
+}
+
+QmlScriptEngine::~QmlScriptEngine()
+{
+ delete sqlQueryClass;
+ delete nodeListClass;
+ delete namedNodeMapClass;
+}
+
+QScriptValue QmlScriptEngine::resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ QString arg = ctxt->argument(0).toString();
+ QUrl r = QmlScriptEngine::get(engine)->resolvedUrl(ctxt,QUrl(arg));
+ return QScriptValue(r.toString());
+}
+
+QNetworkAccessManager *QmlScriptEngine::networkAccessManager()
+{
+ return p->getNetworkAccessManager();
+}
+
+QmlEnginePrivate::~QmlEnginePrivate()
+{
+ while (cleanup) {
+ QmlCleanup *c = cleanup;
+ cleanup = c->next;
+ if (cleanup) cleanup->prev = &cleanup;
+ c->next = 0;
+ c->prev = 0;
+ c->clear();
+ }
+
+ delete rootContext;
+ rootContext = 0;
+ delete contextClass;
+ contextClass = 0;
+ delete objectClass;
+ objectClass = 0;
+ delete valueTypeClass;
+ valueTypeClass = 0;
+ delete typeNameClass;
+ typeNameClass = 0;
+ delete listClass;
+ listClass = 0;
+ delete globalClass;
+ globalClass = 0;
+
+ for(int ii = 0; ii < bindValues.count(); ++ii)
+ clear(bindValues[ii]);
+ for(int ii = 0; ii < parserStatus.count(); ++ii)
+ clear(parserStatus[ii]);
+ for(QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
+ (*iter)->release();
+ for(QHash<const QMetaObject *, QmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
+ (*iter)->release();
+
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlAbstractBinding> &bvs)
+{
+ bvs.clear();
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss)
+{
+ for (int ii = 0; ii < pss.count; ++ii) {
+ QmlParserStatus *ps = pss.at(ii);
+ if(ps)
+ ps->d = 0;
+ }
+ pss.clear();
+}
+
+Q_GLOBAL_STATIC(QmlEngineDebugServer, qmlEngineDebugServer);
+
+void QmlEnginePrivate::init()
+{
+ Q_Q(QmlEngine);
+ qRegisterMetaType<QVariant>("QVariant");
+ qRegisterMetaType<QmlScriptString>("QmlScriptString");
+ qRegisterMetaType<QScriptValue>("QScriptValue");
+
+ contextClass = new QmlContextScriptClass(q);
+ objectClass = new QmlObjectScriptClass(q);
+ valueTypeClass = new QmlValueTypeScriptClass(q);
+ typeNameClass = new QmlTypeNameScriptClass(q);
+ listClass = new QmlListScriptClass(q);
+ rootContext = new QmlContext(q,true);
+
+ if (QCoreApplication::instance()->thread() == q->thread() &&
+ QmlEngineDebugServer::isDebuggingEnabled()) {
+ qmlEngineDebugServer();
+ isDebugging = true;
+ QmlEngineDebugServer::addEngine(q);
+
+ qmlEngineDebugServer()->waitForClients();
+ }
+}
+
+QmlWorkerScriptEngine *QmlEnginePrivate::getWorkerScriptEngine()
+{
+ Q_Q(QmlEngine);
+ if (!workerScriptEngine)
+ workerScriptEngine = new QmlWorkerScriptEngine(q);
+ return workerScriptEngine;
+}
+
+/*!
+ \class QmlEngine
+ \brief The QmlEngine class provides an environment for instantiating QML components.
+ \mainclass
+
+ Each QML component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are arranged
+ hierarchically and this hierarchy is managed by the QmlEngine.
+
+ Prior to creating any QML components, an application must have created a
+ QmlEngine to gain access to a QML context. The following example shows how
+ to create a simple Text item.
+
+ \code
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6\nText { text: \"Hello world!\" }", QUrl());
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(component.create());
+
+ //add item to view, etc
+ ...
+ \endcode
+
+ In this case, the Text item will be created in the engine's
+ \l {QmlEngine::rootContext()}{root context}.
+
+ \sa QmlComponent QmlContext
+*/
+
+/*!
+ Create a new QmlEngine with the given \a parent.
+*/
+QmlEngine::QmlEngine(QObject *parent)
+: QObject(*new QmlEnginePrivate(this), parent)
+{
+ Q_D(QmlEngine);
+ d->init();
+}
+
+/*!
+ Destroys the QmlEngine.
+
+ Any QmlContext's created on this engine will be invalidated, but not
+ destroyed (unless they are parented to the QmlEngine object).
+*/
+QmlEngine::~QmlEngine()
+{
+ Q_D(QmlEngine);
+ if (d->isDebugging)
+ QmlEngineDebugServer::remEngine(this);
+}
+
+/*!
+ Clears the engine's internal component cache.
+
+ Normally the QmlEngine caches components loaded from qml files. This method
+ clears this cache and forces the component to be reloaded.
+ */
+void QmlEngine::clearComponentCache()
+{
+ Q_D(QmlEngine);
+ d->typeManager.clearCache();
+}
+
+/*!
+ Returns the engine's root context.
+
+ The root context is automatically created by the QmlEngine. Data that
+ should be available to all QML component instances instantiated by the
+ engine should be put in the root context.
+
+ Additional data that should only be available to a subset of component
+ instances should be added to sub-contexts parented to the root context.
+*/
+QmlContext *QmlEngine::rootContext()
+{
+ Q_D(QmlEngine);
+ return d->rootContext;
+}
+
+/*!
+ Sets the \a factory to use for creating QNetworkAccessManager(s).
+
+ QNetworkAccessManager is used for all network access by QML.
+ By implementing a factory it is possible to create custom
+ QNetworkAccessManager with specialized caching, proxy and
+ cookie support.
+
+ The factory must be set before exceuting the engine.
+*/
+void QmlEngine::setNetworkAccessManagerFactory(QmlNetworkAccessManagerFactory *factory)
+{
+ Q_D(QmlEngine);
+ d->networkAccessManagerFactory = factory;
+}
+
+/*!
+ Returns the current QmlNetworkAccessManagerFactory.
+
+ \sa setNetworkAccessManagerFactory()
+*/
+QmlNetworkAccessManagerFactory *QmlEngine::networkAccessManagerFactory() const
+{
+ Q_D(const QmlEngine);
+ return d->networkAccessManagerFactory;
+}
+
+QNetworkAccessManager *QmlEnginePrivate::getNetworkAccessManager() const
+{
+ Q_Q(const QmlEngine);
+
+ if (!networkAccessManager) {
+ if (networkAccessManagerFactory) {
+ networkAccessManager = networkAccessManagerFactory->create(const_cast<QmlEngine*>(q));
+ } else {
+ networkAccessManager = new QNetworkAccessManager(const_cast<QmlEngine*>(q));
+ }
+ }
+ return networkAccessManager;
+}
+
+/*!
+ Returns a common QNetworkAccessManager which can be used by any QML element
+ instantiated by this engine.
+
+ If a QmlNetworkAccessManagerFactory has been set and a QNetworkAccessManager
+ has not yet been created, the QmlNetworkAccessManagerFactory will be used
+ to create the QNetworkAccessManager; otherwise the returned QNetworkAccessManager
+ will have no proxy or cache set.
+
+ \sa setNetworkAccessManagerFactory()
+*/
+QNetworkAccessManager *QmlEngine::networkAccessManager() const
+{
+ Q_D(const QmlEngine);
+ return d->getNetworkAccessManager();
+}
+
+/*!
+ Return the base URL for this engine. The base URL is only used to resolve
+ components when a relative URL is passed to the QmlComponent constructor.
+
+ If a base URL has not been explicitly set, this method returns the
+ application's current working directory.
+
+ \sa setBaseUrl()
+*/
+QUrl QmlEngine::baseUrl() const
+{
+ Q_D(const QmlEngine);
+ if (d->baseUrl.isEmpty()) {
+ return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
+ } else {
+ return d->baseUrl;
+ }
+}
+
+/*!
+ Set the base URL for this engine to \a url.
+
+ \sa baseUrl()
+*/
+void QmlEngine::setBaseUrl(const QUrl &url)
+{
+ Q_D(QmlEngine);
+ d->baseUrl = url;
+}
+
+/*!
+ Returns the QmlContext for the \a object, or 0 if no context has been set.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+QmlContext *QmlEngine::contextForObject(const QObject *object)
+{
+ if(!object)
+ return 0;
+
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+
+ QmlDeclarativeData *data =
+ static_cast<QmlDeclarativeData *>(priv->declarativeData);
+
+ if (!data)
+ return 0;
+ else if (data->outerContext)
+ return data->outerContext;
+ else
+ return data->context;
+}
+
+/*!
+ Sets the QmlContext for the \a object to \a context.
+ If the \a object already has a context, a warning is
+ output, but the context is not changed.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+void QmlEngine::setContextForObject(QObject *object, QmlContext *context)
+{
+ if (!object || !context)
+ return;
+
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object, true);
+ if (data->context) {
+ qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext");
+ return;
+ }
+
+ data->context = context;
+ data->nextContextObject = context->d_func()->contextObjects;
+ if (data->nextContextObject)
+ data->nextContextObject->prevContextObject = &data->nextContextObject;
+ data->prevContextObject = &context->d_func()->contextObjects;
+ context->d_func()->contextObjects = data;
+}
+
+void qmlExecuteDeferred(QObject *object)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object);
+
+ if (data && data->deferredComponent) {
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(data->context->engine());
+
+ QmlComponentPrivate::ConstructionState state;
+ QmlComponentPrivate::beginDeferred(data->context, ep, object, &state);
+
+ data->deferredComponent->release();
+ data->deferredComponent = 0;
+
+ QmlComponentPrivate::complete(ep, &state);
+
+ if (!state.errors.isEmpty())
+ qWarning() << state.errors;
+
+ }
+}
+
+QmlContext *qmlContext(const QObject *obj)
+{
+ return QmlEngine::contextForObject(obj);
+}
+
+QmlEngine *qmlEngine(const QObject *obj)
+{
+ QmlContext *context = QmlEngine::contextForObject(obj);
+ return context?context->engine():0;
+}
+
+QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object);
+ if (!data)
+ return 0; // Attached properties are only on objects created by QML
+
+ QObject *rv = data->attachedProperties?data->attachedProperties->value(id):0;
+ if (rv || !create)
+ return rv;
+
+ QmlAttachedPropertiesFunc pf = QmlMetaType::attachedPropertiesFuncById(id);
+ if (!pf)
+ return 0;
+
+ rv = pf(const_cast<QObject *>(object));
+
+ if (rv) {
+ if (!data->attachedProperties)
+ data->attachedProperties = new QHash<int, QObject *>();
+ data->attachedProperties->insert(id, rv);
+ }
+
+ return rv;
+}
+
+void QmlDeclarativeData::destroyed(QObject *object)
+{
+ if (deferredComponent)
+ deferredComponent->release();
+ if (attachedProperties)
+ delete attachedProperties;
+
+ if (nextContextObject)
+ nextContextObject->prevContextObject = prevContextObject;
+ if (prevContextObject)
+ *prevContextObject = nextContextObject;
+
+ QmlAbstractBinding *binding = bindings;
+ while (binding) {
+ QmlAbstractBinding *next = binding->m_nextBinding;
+ binding->m_prevBinding = 0;
+ binding->m_nextBinding = 0;
+ binding->destroy();
+ binding = next;
+ }
+
+ if (bindingBits)
+ free(bindingBits);
+
+ if (propertyCache)
+ propertyCache->release();
+
+ QmlGuard<QObject> *guard = guards;
+ while (guard) {
+ QmlGuard<QObject> *g = guard;
+ guard = guard->next;
+ g->o = 0;
+ g->prev = 0;
+ g->next = 0;
+ g->objectDestroyed(object);
+ }
+
+ delete this;
+}
+
+bool QmlDeclarativeData::hasBindingBit(int bit) const
+{
+ if (bindingBitsSize > bit)
+ return bindingBits[bit / 32] & (1 << (bit % 32));
+ else
+ return false;
+}
+
+void QmlDeclarativeData::clearBindingBit(int bit)
+{
+ if (bindingBitsSize > bit)
+ bindingBits[bit / 32] &= ~(1 << (bit % 32));
+}
+
+void QmlDeclarativeData::setBindingBit(QObject *obj, int bit)
+{
+ if (bindingBitsSize <= bit) {
+ int props = obj->metaObject()->propertyCount();
+ Q_ASSERT(bit < props);
+
+ int arraySize = (props + 31) / 32;
+ int oldArraySize = bindingBitsSize / 32;
+
+ bindingBits = (quint32 *)realloc(bindingBits,
+ arraySize * sizeof(quint32));
+
+ memset(bindingBits + oldArraySize,
+ 0x00,
+ sizeof(quint32) * (arraySize - oldArraySize));
+
+ bindingBitsSize = arraySize * 32;
+ }
+
+ bindingBits[bit / 32] |= (1 << (bit % 32));
+}
+
+/*!
+ Creates a QScriptValue allowing you to use \a object in QML script.
+ \a engine is the QmlEngine it is to be created in.
+
+ The QScriptValue returned is a QtScript Object, not a QtScript QObject, due
+ to the special needs of QML requiring more functionality than a standard
+ QtScript QObject.
+*/
+QScriptValue QmlEnginePrivate::qmlScriptObject(QObject* object,
+ QmlEngine* engine)
+{
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ return enginePriv->objectClass->newQObject(object);
+}
+
+/*!
+ Returns the QmlContext for the executing QScript \a ctxt.
+*/
+QmlContext *QmlEnginePrivate::getContext(QScriptContext *ctxt)
+{
+ QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
+ Q_ASSERT(scopeNode.isValid());
+ Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
+ return contextClass->contextFromValue(scopeNode);
+}
+
+QScriptValue QmlEnginePrivate::createComponent(QScriptContext *ctxt,
+ QScriptEngine *engine)
+{
+ QmlEnginePrivate *activeEnginePriv =
+ static_cast<QmlScriptEngine*>(engine)->p;
+ QmlEngine* activeEngine = activeEnginePriv->q_func();
+
+ QmlContext* context = activeEnginePriv->getContext(ctxt);
+ Q_ASSERT(context);
+ if(ctxt->argumentCount() != 1) {
+ return engine->nullValue();
+ }else{
+ QString arg = ctxt->argument(0).toString();
+ if (arg.isEmpty())
+ return engine->nullValue();
+ QUrl url = QUrl(context->resolvedUrl(QUrl(arg)));
+ QmlComponent *c = new QmlComponent(activeEngine, url, activeEngine);
+ c->setCreationContext(context);
+ return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QmlComponent*>());
+ }
+}
+
+QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ QmlEnginePrivate *activeEnginePriv =
+ static_cast<QmlScriptEngine*>(engine)->p;
+ QmlEngine* activeEngine = activeEnginePriv->q_func();
+
+ if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3)
+ return engine->nullValue();
+
+ QmlContext* context = activeEnginePriv->getContext(ctxt);
+ Q_ASSERT(context);
+
+ QString qml = ctxt->argument(0).toString();
+ if (qml.isEmpty())
+ return engine->nullValue();
+
+ QUrl url;
+ if(ctxt->argumentCount() > 2)
+ url = QUrl(ctxt->argument(2).toString());
+ else
+ url = QUrl(QLatin1String("inline"));
+
+ if (url.isValid() && url.isRelative())
+ url = context->resolvedUrl(url);
+
+ QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
+ if(!parentArg)
+ return engine->nullValue();
+
+ QmlComponent component(activeEngine);
+ component.setData(qml.toUtf8(), url);
+
+ if(component.isError()) {
+ QList<QmlError> errors = component.errors();
+ qWarning().nospace() << "QmlEngine::createQmlObject():";
+ foreach (const QmlError &error, errors)
+ qWarning().nospace() << " " << error;
+
+ return engine->nullValue();
+ }
+
+ if (!component.isReady()) {
+ qWarning().nospace() << "QmlEngine::createQmlObject(): Component is not ready";
+
+ return engine->nullValue();
+ }
+
+ QObject *obj = component.create(context);
+
+ if(component.isError()) {
+ QList<QmlError> errors = component.errors();
+ qWarning().nospace() << "QmlEngine::createQmlObject():";
+ foreach (const QmlError &error, errors)
+ qWarning().nospace() << " " << error;
+
+ return engine->nullValue();
+ }
+
+ Q_ASSERT(obj);
+
+ obj->setParent(parentArg);
+ QGraphicsObject* gobj = qobject_cast<QGraphicsObject*>(obj);
+ QGraphicsObject* gparent = qobject_cast<QGraphicsObject*>(parentArg);
+ if(gobj && gparent)
+ gobj->setParentItem(gparent);
+
+ return qmlScriptObject(obj, activeEngine);
+}
+
+QScriptValue QmlEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() != 3)
+ return engine->nullValue();
+ qsreal x = ctxt->argument(0).toNumber();
+ qsreal y = ctxt->argument(1).toNumber();
+ qsreal z = ctxt->argument(2).toNumber();
+ return engine->newVariant(qVariantFromValue(QVector3D(x, y, z)));
+}
+
+QScriptValue QmlEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ int argCount = ctxt->argumentCount();
+ if(argCount < 3 || argCount > 4)
+ return engine->nullValue();
+ qsreal r = ctxt->argument(0).toNumber();
+ qsreal g = ctxt->argument(1).toNumber();
+ qsreal b = ctxt->argument(2).toNumber();
+ qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
+
+ if (r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1 || a < 0 || a > 1)
+ return engine->nullValue();
+
+ return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromRgbF(r, g, b, a)));
+}
+
+QScriptValue QmlEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ int argCount = ctxt->argumentCount();
+ if(argCount < 3 || argCount > 4)
+ return engine->nullValue();
+ qsreal h = ctxt->argument(0).toNumber();
+ qsreal s = ctxt->argument(1).toNumber();
+ qsreal l = ctxt->argument(2).toNumber();
+ qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
+
+ if (h < 0 || h > 1 || s < 0 || s > 1 || l < 0 || l > 1 || a < 0 || a > 1)
+ return engine->nullValue();
+
+ return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromHslF(h, s, l, a)));
+}
+
+QScriptValue QmlEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() != 4)
+ return engine->nullValue();
+
+ qsreal x = ctxt->argument(0).toNumber();
+ qsreal y = ctxt->argument(1).toNumber();
+ qsreal w = ctxt->argument(2).toNumber();
+ qsreal h = ctxt->argument(3).toNumber();
+
+ if (w < 0 || h < 0)
+ return engine->nullValue();
+
+ return qScriptValueFromValue(engine, qVariantFromValue(QRectF(x, y, w, h)));
+}
+
+QScriptValue QmlEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() != 2)
+ return engine->nullValue();
+ qsreal x = ctxt->argument(0).toNumber();
+ qsreal y = ctxt->argument(1).toNumber();
+ return qScriptValueFromValue(engine, qVariantFromValue(QPointF(x, y)));
+}
+
+QScriptValue QmlEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() != 2)
+ return engine->nullValue();
+ qsreal w = ctxt->argument(0).toNumber();
+ qsreal h = ctxt->argument(1).toNumber();
+ return qScriptValueFromValue(engine, qVariantFromValue(QSizeF(w, h)));
+}
+
+QScriptValue QmlEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() != 1)
+ return engine->nullValue();
+ QVariant v = ctxt->argument(0).toVariant();
+ QColor color;
+ if (v.userType() == QVariant::Color)
+ color = v.value<QColor>();
+ else if (v.userType() == QVariant::String) {
+ bool ok;
+ color = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+ color = color.lighter();
+ return qScriptValueFromValue(engine, qVariantFromValue(color));
+}
+
+QScriptValue QmlEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() != 1)
+ return engine->nullValue();
+ QVariant v = ctxt->argument(0).toVariant();
+ QColor color;
+ if (v.userType() == QVariant::Color)
+ color = v.value<QColor>();
+ else if (v.userType() == QVariant::String) {
+ bool ok;
+ color = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+ color = color.darker();
+ return qScriptValueFromValue(engine, qVariantFromValue(color));
+}
+
+QScriptValue QmlEnginePrivate::playSound(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if (ctxt->argumentCount() != 1)
+ return engine->undefinedValue();
+
+ QUrl url(ctxt->argument(0).toString());
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ if (url.isRelative()) {
+ QmlContext *context = enginePriv->getContext(ctxt);
+ if (!context)
+ return engine->undefinedValue();
+
+ url = context->resolvedUrl(url);
+ }
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QSound::play(url.toLocalFile());
+
+ }
+ return engine->undefinedValue();
+}
+
+QScriptValue QmlEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
+{
+ if(ctxt->argumentCount() < 1)
+ return e->newVariant(QVariant(false));
+ bool ret = QDesktopServices::openUrl(QUrl(ctxt->argument(0).toString()));
+ return e->newVariant(QVariant(ret));
+}
+
+QScriptValue QmlEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *)
+{
+ QByteArray data;
+
+ if (ctxt->argumentCount() >= 1)
+ data = ctxt->argument(0).toString().toUtf8();
+
+ QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
+
+ return QScriptValue(QLatin1String(result.toHex()));
+}
+
+QScriptValue QmlEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
+{
+ QByteArray data;
+
+ if (ctxt->argumentCount() >= 1)
+ data = ctxt->argument(0).toString().toUtf8();
+
+ return QScriptValue(QLatin1String(data.toBase64()));
+}
+
+QScriptValue QmlEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
+{
+ QByteArray data;
+
+ if (ctxt->argumentCount() >= 1)
+ data = ctxt->argument(0).toString().toUtf8();
+
+ return QScriptValue(QLatin1String(QByteArray::fromBase64(data)));
+}
+
+QScriptValue QmlEnginePrivate::consoleLog(QScriptContext *ctxt, QScriptEngine *e)
+{
+ if(ctxt->argumentCount() < 1)
+ return e->newVariant(QVariant(false));
+
+ QByteArray msg;
+
+ for (int i=0; i<ctxt->argumentCount(); ++i) {
+ if (!msg.isEmpty()) msg += ' ';
+ msg += ctxt->argument(i).toString().toLocal8Bit();
+ // does not support firebug "%[a-z]" formatting, since firebug really
+ // does just ignore the format letter, which makes it pointless.
+ }
+
+ qDebug("%s",msg.constData());
+
+ return e->newVariant(QVariant(true));
+}
+
+void QmlEnginePrivate::sendQuit ()
+{
+ Q_Q(QmlEngine);
+ emit q->quit ();
+}
+
+QScriptValue QmlEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
+{
+ QmlEnginePrivate *qe = get (e);
+ qe->sendQuit ();
+ return QScriptValue();
+}
+
+QScriptValue QmlEnginePrivate::closestAngle(QScriptContext *ctxt, QScriptEngine *e)
+{
+ if(ctxt->argumentCount() < 2)
+ return e->newVariant(QVariant(0.0));
+ qreal a = ctxt->argument(0).toNumber();
+ qreal b = ctxt->argument(1).toNumber();
+ qreal ret = b;
+ qreal diff = b-a;
+ while(diff > 180.0){
+ ret -= 360.0;
+ diff -= 360.0;
+ }
+ while(diff < -180.0){
+ ret += 360.0;
+ diff += 360.0;
+ }
+ return e->newVariant(QVariant(ret));
+}
+
+QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() != 2)
+ return engine->nullValue();
+ //get color
+ QVariant v = ctxt->argument(0).toVariant();
+ QColor color;
+ if (v.userType() == QVariant::Color)
+ color = v.value<QColor>();
+ else if (v.userType() == QVariant::String) {
+ bool ok;
+ color = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+
+ //get tint color
+ v = ctxt->argument(1).toVariant();
+ QColor tintColor;
+ if (v.userType() == QVariant::Color)
+ tintColor = v.value<QColor>();
+ else if (v.userType() == QVariant::String) {
+ bool ok;
+ tintColor = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+
+ //tint
+ QColor finalColor;
+ int a = tintColor.alpha();
+ if (a == 0xFF)
+ finalColor = tintColor;
+ else if (a == 0x00)
+ finalColor = color;
+ else {
+ uint src = tintColor.rgba();
+ uint dest = color.rgba();
+
+ uint res = (((a * (src & 0xFF00FF)) +
+ ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF;
+ res |= (((a * ((src >> 8) & 0xFF00FF)) +
+ ((0xFF - a) * ((dest >> 8) & 0xFF00FF)))) & 0xFF00FF00;
+ if ((src & 0xFF000000) == 0xFF000000)
+ res |= 0xFF000000;
+
+ finalColor = QColor::fromRgba(res);
+ }
+
+ return qScriptValueFromValue(engine, qVariantFromValue(finalColor));
+}
+
+
+QScriptValue QmlEnginePrivate::scriptValueFromVariant(const QVariant &val)
+{
+ bool objOk;
+ QObject *obj = QmlMetaType::toQObject(val, &objOk);
+ if (objOk) {
+ return objectClass->newQObject(obj);
+ } else {
+ return qScriptValueFromValue(&scriptEngine, val);
+ }
+}
+
+QVariant QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val)
+{
+ QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
+ if (dc == objectClass)
+ return QVariant::fromValue(objectClass->toQObject(val));
+ else if (dc == contextClass)
+ return QVariant();
+
+ QScriptDeclarativeClass *sc = QScriptDeclarativeClass::scriptClass(val);
+ if (!sc) {
+ return val.toVariant();
+ } else if (sc == valueTypeClass) {
+ return valueTypeClass->toVariant(val);
+ } else {
+ return QVariant();
+ }
+}
+
+QmlScriptClass::QmlScriptClass(QScriptEngine *engine)
+: QScriptDeclarativeClass(engine)
+{
+}
+
+QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
+{
+ QmlEnginePrivate *ep =
+ static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
+
+ return ep->scriptValueToVariant(val);
+}
+
+// XXX this beyonds in QUrl::toLocalFile()
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+/////////////////////////////////////////////////////////////
+struct QmlEnginePrivate::ImportedNamespace {
+ QStringList uris;
+ QStringList urls;
+ QList<int> majversions;
+ QList<int> minversions;
+ QList<bool> isLibrary;
+ QList<bool> isBuiltin; // Types provided by C++ code (including plugins)
+ QList<QString> qmlDirContent;
+
+ bool find(const QByteArray& type, int *vmajor, int *vminor, QmlType** type_return, QUrl* url_return) const
+ {
+ for (int i=0; i<urls.count(); ++i) {
+ int vmaj = majversions.at(i);
+ int vmin = minversions.at(i);
+
+ if (isBuiltin.at(i)) {
+ QByteArray qt = uris.at(i).toUtf8();
+ qt += '/';
+ qt += type;
+ if (qmlImportTrace())
+ qDebug() << "Look in" << qt;
+ QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin);
+ if (vmajor) *vmajor = vmaj;
+ if (vminor) *vminor = vmin;
+ if (t) {
+ if (qmlImportTrace())
+ qDebug() << "Found" << qt;
+ if (type_return)
+ *type_return = t;
+ return true;
+ }
+ }
+ QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml"));
+ QString qmldircontent = qmlDirContent.at(i);
+ if (vmaj>=0 || !qmldircontent.isEmpty()) {
+ // Check version file - XXX cache these in QmlEngine!
+ if (qmldircontent.isEmpty()) {
+ QFile qmldir(toLocalFileOrQrc(QUrl(urls.at(i)+QLatin1String("/qmldir"))));
+ if (qmldir.open(QIODevice::ReadOnly)) {
+ qmldircontent = QString::fromUtf8(qmldir.readAll());
+ }
+ }
+ QString typespace = QString::fromUtf8(type)+QLatin1Char(' ');
+ QStringList lines = qmldircontent.split(QLatin1Char('\n'));
+ foreach (QString line, lines) {
+ if (line.isEmpty() || line.at(0) == QLatin1Char('#'))
+ continue;
+ if (line.startsWith(typespace)) {
+ int space1 = line.indexOf(QLatin1Char(' '));
+ int space2 = space1 >=0 ? line.indexOf(QLatin1Char(' '),space1+1) : -1;
+ QString mapversions = line.mid(space1+1,space2<0?line.length()-space1-1:space2-space1-1);
+ int dot = mapversions.indexOf(QLatin1Char('.'));
+ int mapvmaj = mapversions.left(dot).toInt();
+ if (mapvmaj<=vmaj) {
+ if (mapvmaj<vmaj || vmin >= mapversions.mid(dot+1).toInt()) {
+ QStringRef mapfile = space2<0 ? QStringRef() : line.midRef(space2+1,line.length()-space2-1);
+ if (url_return)
+ *url_return = url.resolved(QUrl(mapfile.toString()));
+ return true;
+ }
+ }
+ }
+ }
+ } else {
+ // XXX search non-files too! (eg. zip files, see QT-524)
+ QFileInfo f(toLocalFileOrQrc(url));
+ if (f.exists()) {
+ if (url_return)
+ *url_return = url;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+};
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QmlModuleFactoryInterface_iid, QLatin1String("/qmlmodules")))
+
+class QmlImportsPrivate {
+public:
+ QmlImportsPrivate() : ref(1)
+ {
+ }
+
+ ~QmlImportsPrivate()
+ {
+ foreach (QmlEnginePrivate::ImportedNamespace* s, set.values())
+ delete s;
+ }
+
+ bool add(const QUrl& base, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType, const QStringList& importPath)
+ {
+ QmlEnginePrivate::ImportedNamespace *s;
+ if (prefix.isEmpty()) {
+ s = &unqualifiedset;
+ } else {
+ s = set.value(prefix);
+ if (!s)
+ set.insert(prefix,(s=new QmlEnginePrivate::ImportedNamespace));
+ }
+ QString url = uri;
+ bool isbuiltin = false;
+ if (importType == QmlScriptParser::Import::Library) {
+ url.replace(QLatin1Char('.'),QLatin1Char('/'));
+ bool found = false;
+ foreach (QString p, importPath) {
+ QString dir = p+QLatin1Char('/')+url;
+ QFileInfo fi(dir+QLatin1String("/qmldir"));
+ if (fi.isFile()) {
+ url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // XXX assume it is a built-in type qualifier
+ isbuiltin = true;
+ }
+ QFactoryLoader *l = loader();
+ QmlModuleFactoryInterface *factory =
+ qobject_cast<QmlModuleFactoryInterface*>(l->instance(uri));
+ if (factory) {
+ factory->defineModuleOnce(uri);
+ isbuiltin = true;
+ }
+ } else {
+ url = base.resolved(QUrl(url)).toString();
+ }
+ s->uris.prepend(uri);
+ s->urls.prepend(url);
+ s->majversions.prepend(vmaj);
+ s->minversions.prepend(vmin);
+ s->isLibrary.prepend(importType == QmlScriptParser::Import::Library);
+ s->isBuiltin.prepend(isbuiltin);
+ s->qmlDirContent.prepend(qmldircontent);
+ return true;
+ }
+
+ bool find(const QByteArray& type, int *vmajor, int *vminor, QmlType** type_return, QUrl* url_return)
+ {
+ QmlEnginePrivate::ImportedNamespace *s = 0;
+ int slash = type.indexOf('/');
+ if (slash >= 0) {
+ s = set.value(QString::fromUtf8(type.left(slash)));
+ if (!s)
+ return false; // qualifier must be a namespace
+ int nslash = type.indexOf('/',slash+1);
+ if (nslash > 0)
+ return false; // only single qualification allowed
+ } else {
+ s = &unqualifiedset;
+ }
+ QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower)
+ if (s) {
+ if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return))
+ return true;
+ if (s->urls.count() == 1 && !s->isBuiltin[0] && !s->isLibrary[0] && url_return) {
+ *url_return = QUrl(s->urls[0]+QLatin1Char('/')).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml")));
+ return true;
+ }
+ }
+ if (url_return) {
+ *url_return = base.resolved(QUrl(QString::fromUtf8(type + ".qml")));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ QmlEnginePrivate::ImportedNamespace *findNamespace(const QString& type)
+ {
+ return set.value(type);
+ }
+
+ QUrl base;
+ int ref;
+
+private:
+ friend struct QmlEnginePrivate::Imports;
+ QmlEnginePrivate::ImportedNamespace unqualifiedset;
+ QHash<QString,QmlEnginePrivate::ImportedNamespace* > set;
+};
+
+QmlEnginePrivate::Imports::Imports(const Imports &copy) :
+ d(copy.d)
+{
+ ++d->ref;
+}
+
+QmlEnginePrivate::Imports &QmlEnginePrivate::Imports::operator =(const Imports &copy)
+{
+ ++copy.d->ref;
+ if (--d->ref == 0)
+ delete d;
+ d = copy.d;
+ return *this;
+}
+
+QmlEnginePrivate::Imports::Imports() :
+ d(new QmlImportsPrivate)
+{
+}
+
+QmlEnginePrivate::Imports::~Imports()
+{
+ if (--d->ref == 0)
+ delete d;
+}
+
+#include "qmlmetatype.h"
+#include "qmltypenamecache_p.h"
+
+static QmlTypeNameCache *cacheForNamespace(QmlEngine *engine, const QmlEnginePrivate::ImportedNamespace &set, QmlTypeNameCache *cache)
+{
+ if (!cache)
+ cache = new QmlTypeNameCache(engine);
+
+ QList<QmlType *> types = QmlMetaType::qmlTypes();
+
+ for (int ii = 0; ii < set.uris.count(); ++ii) {
+ if (!set.isBuiltin.at(ii))
+ continue;
+
+ QByteArray base = set.uris.at(ii).toUtf8() + '/';
+ int major = set.majversions.at(ii);
+ int minor = set.minversions.at(ii);
+
+ foreach (QmlType *type, types) {
+ if (type->qmlTypeName().startsWith(base) &&
+ type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) &&
+ type->availableInVersion(major,minor))
+ {
+ QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length()));
+
+ cache->add(name, type);
+ }
+ }
+ }
+
+ return cache;
+}
+
+QmlTypeNameCache *QmlEnginePrivate::Imports::cache(QmlEngine *engine) const
+{
+ const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
+
+ QmlTypeNameCache *cache = new QmlTypeNameCache(engine);
+
+ for (QHash<QString,QmlEnginePrivate::ImportedNamespace* >::ConstIterator iter = d->set.begin();
+ iter != d->set.end(); ++iter) {
+
+ QmlTypeNameCache::Data *d = cache->data(iter.key());
+ if (d) {
+ if (!d->typeNamespace)
+ cacheForNamespace(engine, *(*iter), d->typeNamespace);
+ } else {
+ QmlTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0);
+ cache->add(iter.key(), nc);
+ nc->release();
+ }
+ }
+
+ cacheForNamespace(engine, set, cache);
+
+ return cache;
+}
+
+/*
+QStringList QmlEnginePrivate::Imports::unqualifiedSet() const
+{
+ QStringList rv;
+
+ const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
+
+ for (int ii = 0; ii < set.urls.count(); ++ii) {
+ if (set.isBuiltin.at(ii))
+ rv << set.urls.at(ii);
+ }
+
+ return rv;
+}
+*/
+
+/*!
+ Sets the base URL to be used for all relative file imports added.
+*/
+void QmlEnginePrivate::Imports::setBaseUrl(const QUrl& url)
+{
+ d->base = url;
+}
+
+/*!
+ Returns the base URL to be used for all relative file imports added.
+*/
+QUrl QmlEnginePrivate::Imports::baseUrl() const
+{
+ return d->base;
+}
+
+/*!
+ Adds \a path as a directory where installed QML components are
+ defined in a URL-based directory structure.
+
+ For example, if you add \c /opt/MyApp/lib/qml and then load QML
+ that imports \c com.mycompany.Feature, then QmlEngine will look
+ in \c /opt/MyApp/lib/qml/com/mycompany/Feature/ for the components
+ provided by that module (and in the case of versioned imports,
+ for the \c qmldir file definiting the type version mapping.
+
+ By default, only the "qml" subdirectory of QLibraryInfo::location(QLibraryInfo::DataPath)
+ is included on the import path.
+*/
+void QmlEngine::addImportPath(const QString& path)
+{
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::addImportPath" << path;
+ Q_D(QmlEngine);
+ d->fileImportPath.prepend(path);
+}
+
+/*!
+ \property QmlEngine::offlineStoragePath
+ \brief the directory for storing offline user data
+
+ Returns the directory where SQL and other offline
+ storage is placed.
+
+ QmlGraphicsWebView and the SQL databases created with openDatabase()
+ are stored here.
+
+ The default is QML/OfflineStorage in the platform-standard
+ user application data directory.
+
+ Note that the path may not currently exist on the filesystem, so
+ callers wanting to \e create new files at this location should create
+ it first - see QDir::mkpath().
+*/
+void QmlEngine::setOfflineStoragePath(const QString& dir)
+{
+ Q_D(QmlEngine);
+ d->scriptEngine.offlineStoragePath = dir;
+}
+
+QString QmlEngine::offlineStoragePath() const
+{
+ Q_D(const QmlEngine);
+ return d->scriptEngine.offlineStoragePath;
+}
+
+
+/*!
+ \internal
+
+ Adds information to \a imports such that subsequent calls to resolveType()
+ will resolve types qualified by \a prefix by considering types found at the given \a uri.
+
+ The uri is either a directory (if importType is FileImport), or a URI resolved using paths
+ added via addImportPath() (if importType is LibraryImport).
+
+ The \a prefix may be empty, in which case the import location is considered for
+ unqualified types.
+
+ The base URL must already have been set with Import::setBaseUrl().
+*/
+bool QmlEnginePrivate::addToImport(Imports* imports, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const
+{
+ bool ok = imports->d->add(imports->d->base,qmldircontent,uri,prefix,vmaj,vmin,importType,fileImportPath);
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::addToImport(" << imports << uri << prefix << vmaj << '.' << vmin << (importType==QmlScriptParser::Import::Library? "Library" : "File") << ": " << ok;
+ return ok;
+}
+
+/*!
+ \internal
+
+ Using the given \a imports, the given (namespace qualified) \a type is resolved to either
+ an ImportedNamespace stored at \a ns_return,
+ a QmlType stored at \a type_return, or
+ a component located at \a url_return.
+
+ If any return pointer is 0, the corresponding search is not done.
+
+ \sa addToImport()
+*/
+bool QmlEnginePrivate::resolveType(const Imports& imports, const QByteArray& type, QmlType** type_return, QUrl* url_return, int *vmaj, int *vmin, ImportedNamespace** ns_return) const
+{
+ ImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type));
+ if (ns) {
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::resolveType" << type << "is namespace for" << ns->urls;
+ if (ns_return)
+ *ns_return = ns;
+ return true;
+ }
+ if (type_return || url_return) {
+ if (imports.d->find(type,vmaj,vmin,type_return,url_return)) {
+ if (qmlImportTrace()) {
+ if (type_return && *type_return)
+ qDebug() << "QmlEngine::resolveType" << type << '=' << (*type_return)->typeName();
+ if (url_return)
+ qDebug() << "QmlEngine::resolveType" << type << '=' << *url_return;
+ }
+ return true;
+ }
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::resolveType" << type << "not found";
+ }
+ return false;
+}
+
+/*!
+ \internal
+
+ Searching \e only in the namespace \a ns (previously returned in a call to
+ resolveType(), \a type is found and returned to either
+ a QmlType stored at \a type_return, or
+ a component located at \a url_return.
+
+ If either return pointer is 0, the corresponding search is not done.
+*/
+void QmlEnginePrivate::resolveTypeInNamespace(ImportedNamespace* ns, const QByteArray& type, QmlType** type_return, QUrl* url_return, int *vmaj, int *vmin ) const
+{
+ ns->find(type,vmaj,vmin,type_return,url_return);
+}
+
+static void voidptr_destructor(void *v)
+{
+ void **ptr = (void **)v;
+ delete ptr;
+}
+
+static void *voidptr_constructor(const void *v)
+{
+ if (!v) {
+ return new void*;
+ } else {
+ return new void*(*(void **)v);
+ }
+}
+
+void QmlEnginePrivate::registerCompositeType(QmlCompiledData *data)
+{
+ QByteArray name = data->root->className();
+
+ QByteArray ptr = name + '*';
+ QByteArray lst = "QmlList<" + ptr + ">*";
+
+ int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
+ voidptr_constructor);
+ int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
+ voidptr_constructor);
+
+ m_qmlLists.insert(lst_type, ptr_type);
+ m_compositeTypes.insert(ptr_type, data);
+ data->addref();
+}
+
+bool QmlEnginePrivate::isQmlList(int t) const
+{
+ return m_qmlLists.contains(t) || QmlMetaType::isQmlList(t);
+}
+
+bool QmlEnginePrivate::isQObject(int t)
+{
+ return m_compositeTypes.contains(t) || QmlMetaType::isQObject(t);
+}
+
+QObject *QmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
+{
+ int t = v.userType();
+ if (m_compositeTypes.contains(t)) {
+ if (ok) *ok = true;
+ return *(QObject **)(v.constData());
+ } else {
+ return QmlMetaType::toQObject(v, ok);
+ }
+}
+
+int QmlEnginePrivate::qmlListType(int t) const
+{
+ QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
+ if (iter != m_qmlLists.end())
+ return *iter;
+ else
+ return QmlMetaType::qmlListType(t);
+}
+
+QmlMetaType::TypeCategory QmlEnginePrivate::typeCategory(int t) const
+{
+ if (m_compositeTypes.contains(t))
+ return QmlMetaType::Object;
+ else if (m_qmlLists.contains(t))
+ return QmlMetaType::QmlList;
+ else
+ return QmlMetaType::typeCategory(t);
+}
+
+const QMetaObject *QmlEnginePrivate::rawMetaObjectForType(int t) const
+{
+ QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
+ if (iter != m_compositeTypes.end()) {
+ return (*iter)->root;
+ } else {
+ QmlType *type = QmlMetaType::qmlType(t);
+ return type?type->baseMetaObject():0;
+ }
+}
+
+const QMetaObject *QmlEnginePrivate::metaObjectForType(int t) const
+{
+ QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
+ if (iter != m_compositeTypes.end()) {
+ return (*iter)->root;
+ } else {
+ QmlType *type = QmlMetaType::qmlType(t);
+ return type?type->metaObject():0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
new file mode 100644
index 0000000..7ee014a
--- /dev/null
+++ b/src/declarative/qml/qmlengine.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLENGINE_H
+#define QMLENGINE_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qmap.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlComponent;
+class QmlEnginePrivate;
+class QmlImportsPrivate;
+class QmlExpression;
+class QmlContext;
+class QmlType;
+class QUrl;
+class QScriptEngine;
+class QScriptContext;
+class QNetworkAccessManager;
+class QmlNetworkAccessManagerFactory;
+class Q_DECLARATIVE_EXPORT QmlEngine : public QObject
+{
+ Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath)
+ Q_OBJECT
+public:
+ QmlEngine(QObject *p = 0);
+ virtual ~QmlEngine();
+
+ QmlContext *rootContext();
+
+ void clearComponentCache();
+
+ void addImportPath(const QString& dir);
+
+ void setNetworkAccessManagerFactory(QmlNetworkAccessManagerFactory *);
+ QmlNetworkAccessManagerFactory *networkAccessManagerFactory() const;
+
+ QNetworkAccessManager *networkAccessManager() const;
+
+ void setOfflineStoragePath(const QString& dir);
+ QString offlineStoragePath() const;
+
+ QUrl baseUrl() const;
+ void setBaseUrl(const QUrl &);
+
+ static QmlContext *contextForObject(const QObject *);
+ static void setContextForObject(QObject *, QmlContext *);
+
+Q_SIGNALS:
+ void quit ();
+
+private:
+ Q_DECLARE_PRIVATE(QmlEngine)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLENGINE_H
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
new file mode 100644
index 0000000..13ed5ef
--- /dev/null
+++ b/src/declarative/qml/qmlengine_p.h
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLENGINE_P_H
+#define QMLENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlengine.h"
+
+#include "qmlclassfactory_p.h"
+#include "qmlcompositetypemanager_p.h"
+#include "qpodvector_p.h"
+#include "qml.h"
+#include "qmlvaluetype_p.h"
+#include "qmlcontext.h"
+#include "qmlexpression.h"
+#include "qmlmetaproperty_p.h"
+#include "qmlpropertycache_p.h"
+#include "qmlobjectscriptclass_p.h"
+#include "qmlcontextscriptclass_p.h"
+#include "qmlvaluetypescriptclass_p.h"
+
+#include <QtScript/QScriptClass>
+#include <QtScript/QScriptValue>
+#include <QtScript/QScriptString>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstack.h>
+#include <QtScript/qscriptengine.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QmlEngine;
+class QmlContextPrivate;
+class QmlExpression;
+class QmlContextScriptClass;
+class QmlObjectScriptClass;
+class QmlTypeNameScriptClass;
+class QmlValueTypeScriptClass;
+class QScriptEngineDebugger;
+class QNetworkReply;
+class QNetworkAccessManager;
+class QmlNetworkAccessManagerFactory;
+class QmlAbstractBinding;
+class QScriptDeclarativeClass;
+class QmlTypeNameScriptClass;
+class QmlTypeNameCache;
+class QmlComponentAttached;
+class QmlListScriptClass;
+class QmlCleanup;
+class QmlDelayedError;
+class QmlWorkerScriptEngine;
+class QmlGlobalScriptClass;
+
+class QmlScriptEngine : public QScriptEngine
+{
+public:
+ QmlScriptEngine(QmlEnginePrivate *priv);
+ virtual ~QmlScriptEngine();
+
+ QUrl resolvedUrl(QScriptContext *context, const QUrl& url); // resolved against p's context, or baseUrl if no p
+ static QScriptValue resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine);
+
+ static QmlScriptEngine *get(QScriptEngine* e) { return static_cast<QmlScriptEngine*>(e); }
+
+ QmlEnginePrivate *p;
+
+ // User by SQL API
+ QScriptClass *sqlQueryClass;
+ QString offlineStoragePath;
+
+ // Used by DOM Core 3 API
+ QScriptClass *namedNodeMapClass;
+ QScriptClass *nodeListClass;
+
+ QUrl baseUrl;
+
+ virtual QNetworkAccessManager *networkAccessManager();
+};
+
+class Q_AUTOTEST_EXPORT QmlEnginePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEngine)
+public:
+ QmlEnginePrivate(QmlEngine *);
+ ~QmlEnginePrivate();
+
+ void init();
+
+ struct CapturedProperty {
+ CapturedProperty(QObject *o, int c, int n)
+ : object(o), coreIndex(c), notifyIndex(n) {}
+
+ QObject *object;
+ int coreIndex;
+ int notifyIndex;
+ };
+ bool captureProperties;
+ QPODVector<CapturedProperty> capturedProperties;
+
+ QmlContext *rootContext;
+ QmlExpression *currentExpression;
+ bool isDebugging;
+
+ struct ImportedNamespace;
+ QmlContextScriptClass *contextClass;
+ QmlContext *sharedContext;
+ QObject *sharedScope;
+ QmlObjectScriptClass *objectClass;
+ QmlValueTypeScriptClass *valueTypeClass;
+ QmlTypeNameScriptClass *typeNameClass;
+ QmlListScriptClass *listClass;
+ // Global script class
+ QmlGlobalScriptClass *globalClass;
+
+ // Registered cleanup handlers
+ QmlCleanup *cleanup;
+
+ // Bindings that have had errors during startup
+ QmlDelayedError *erroredBindings;
+ int inProgressCreations;
+
+ QmlScriptEngine scriptEngine;
+
+ QmlWorkerScriptEngine *getWorkerScriptEngine();
+ QmlWorkerScriptEngine *workerScriptEngine;
+
+ QUrl baseUrl;
+
+ template<class T>
+ struct SimpleList {
+ SimpleList()
+ : count(0), values(0) {}
+ SimpleList(int r)
+ : count(0), values(new T*[r]) {}
+
+ int count;
+ T **values;
+
+ void append(T *v) {
+ values[count++] = v;
+ }
+
+ T *at(int idx) const {
+ return values[idx];
+ }
+
+ void clear() {
+ delete [] values;
+ }
+ };
+
+ static void clear(SimpleList<QmlAbstractBinding> &);
+ static void clear(SimpleList<QmlParserStatus> &);
+
+ QList<SimpleList<QmlAbstractBinding> > bindValues;
+ QList<SimpleList<QmlParserStatus> > parserStatus;
+ QmlComponentAttached *componentAttacheds;
+
+ bool inBeginCreate;
+
+ QNetworkAccessManager *getNetworkAccessManager() const;
+ mutable QNetworkAccessManager *networkAccessManager;
+ mutable QmlNetworkAccessManagerFactory *networkAccessManagerFactory;
+
+ QmlCompositeTypeManager typeManager;
+ QStringList fileImportPath;
+ QString offlineStoragePath;
+
+ mutable quint32 uniqueId;
+ quint32 getUniqueId() const {
+ return uniqueId++;
+ }
+
+ QmlValueTypeFactory valueTypes;
+
+ QHash<const QMetaObject *, QmlPropertyCache *> propertyCache;
+ QmlPropertyCache *cache(QObject *obj) {
+ Q_Q(QmlEngine);
+ if (!obj || QObjectPrivate::get(obj)->metaObject) return 0;
+ const QMetaObject *mo = obj->metaObject();
+ QmlPropertyCache *rv = propertyCache.value(mo);
+ if (!rv) {
+ rv = QmlPropertyCache::create(q, mo);
+ propertyCache.insert(mo, rv);
+ }
+ return rv;
+ }
+
+ // ### This whole class is embarrassing
+ struct Imports {
+ Imports();
+ ~Imports();
+ Imports(const Imports &copy);
+ Imports &operator =(const Imports &copy);
+
+ void setBaseUrl(const QUrl& url);
+ QUrl baseUrl() const;
+
+ QmlTypeNameCache *cache(QmlEngine *) const;
+
+ private:
+ friend class QmlEnginePrivate;
+ QmlImportsPrivate *d;
+ };
+
+ bool addToImport(Imports*, const QString& qmlDirContent,const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const;
+ bool resolveType(const Imports&, const QByteArray& type,
+ QmlType** type_return, QUrl* url_return,
+ int *version_major, int *version_minor,
+ ImportedNamespace** ns_return) const;
+ void resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type,
+ QmlType** type_return, QUrl* url_return,
+ int *version_major, int *version_minor ) const;
+
+
+ void registerCompositeType(QmlCompiledData *);
+ bool isQmlList(int) const;
+ bool isQObject(int);
+ QObject *toQObject(const QVariant &, bool *ok = 0) const;
+ int qmlListType(int) const;
+ QmlMetaType::TypeCategory typeCategory(int) const;
+ const QMetaObject *rawMetaObjectForType(int) const;
+ const QMetaObject *metaObjectForType(int) const;
+ QHash<int, int> m_qmlLists;
+ QHash<int, QmlCompiledData *> m_compositeTypes;
+
+ QScriptValue scriptValueFromVariant(const QVariant &);
+ QVariant scriptValueToVariant(const QScriptValue &);
+
+ void sendQuit ();
+
+ static QScriptValue qmlScriptObject(QObject*, QmlEngine*);
+
+ static QScriptValue createComponent(QScriptContext*, QScriptEngine*);
+ static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*);
+ static QScriptValue vector(QScriptContext*, QScriptEngine*);
+ static QScriptValue rgba(QScriptContext*, QScriptEngine*);
+ static QScriptValue hsla(QScriptContext*, QScriptEngine*);
+ static QScriptValue point(QScriptContext*, QScriptEngine*);
+ static QScriptValue size(QScriptContext*, QScriptEngine*);
+ static QScriptValue rect(QScriptContext*, QScriptEngine*);
+
+ static QScriptValue lighter(QScriptContext*, QScriptEngine*);
+ static QScriptValue darker(QScriptContext*, QScriptEngine*);
+ static QScriptValue tint(QScriptContext*, QScriptEngine*);
+
+ static QScriptValue closestAngle(QScriptContext*, QScriptEngine*);
+ static QScriptValue playSound(QScriptContext*, QScriptEngine*);
+ static QScriptValue desktopOpenUrl(QScriptContext*, QScriptEngine*);
+ static QScriptValue md5(QScriptContext*, QScriptEngine*);
+ static QScriptValue btoa(QScriptContext*, QScriptEngine*);
+ static QScriptValue atob(QScriptContext*, QScriptEngine*);
+ static QScriptValue consoleLog(QScriptContext*, QScriptEngine*);
+ static QScriptValue quit(QScriptContext*, QScriptEngine*);
+
+ static QScriptEngine *getScriptEngine(QmlEngine *e) { return &e->d_func()->scriptEngine; }
+ static QmlEngine *getEngine(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p->q_func(); }
+ static QmlEnginePrivate *get(QmlEngine *e) { return e->d_func(); }
+ static QmlEnginePrivate *get(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p; }
+ static QmlEngine *get(QmlEnginePrivate *p) { return p->q_func(); }
+ QmlContext *getContext(QScriptContext *);
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QMLENGINE_P_H
diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp
new file mode 100644
index 0000000..b0c1ec9
--- /dev/null
+++ b/src/declarative/qml/qmlenginedebug.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlenginedebug_p.h"
+
+#include "qmlboundsignal_p.h"
+#include "qmlengine.h"
+#include "qmlmetatype.h"
+#include "qmlmetaproperty.h"
+#include "qmlbinding.h"
+#include "qmlcontext_p.h"
+#include "qmlwatcher_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+QList<QmlEngine *> QmlEngineDebugServer::m_engines;
+QmlEngineDebugServer::QmlEngineDebugServer(QObject *parent)
+: QmlDebugService(QLatin1String("QmlEngine"), parent),
+ m_watch(new QmlWatcher(this))
+{
+ QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
+ this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QmlEngineDebugServer::QmlObjectData &data)
+{
+ ds << data.url << data.lineNumber << data.columnNumber << data.objectName
+ << data.objectType << data.objectId << data.contextId;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QmlEngineDebugServer::QmlObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.objectName
+ >> data.objectType >> data.objectId >> data.contextId;
+ return ds;
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QmlEngineDebugServer::QmlObjectProperty &data)
+{
+ ds << (int)data.type << data.name << data.value << data.valueTypeName
+ << data.binding << data.hasNotifySignal;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QmlEngineDebugServer::QmlObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QmlEngineDebugServer::QmlObjectProperty::Type)type;
+ return ds;
+}
+
+QmlEngineDebugServer::QmlObjectProperty
+QmlEngineDebugServer::propertyData(QObject *obj, int propIdx)
+{
+ QmlObjectProperty rv;
+
+ QMetaProperty prop = obj->metaObject()->property(propIdx);
+
+ rv.type = QmlObjectProperty::Unknown;
+ rv.valueTypeName = QString::fromUtf8(prop.typeName());
+ rv.name = QString::fromUtf8(prop.name());
+ rv.hasNotifySignal = prop.hasNotifySignal();
+ QmlAbstractBinding *binding = QmlMetaProperty(obj, rv.name).binding();
+ if (binding)
+ rv.binding = binding->expression();
+
+ QVariant value = prop.read(obj);
+ rv.value = valueContents(value);
+
+ if (QVariant::Type(prop.userType()) < QVariant::UserType) {
+ rv.type = QmlObjectProperty::Basic;
+ } else if (QmlMetaType::isQObject(prop.userType())) {
+ rv.type = QmlObjectProperty::Object;
+ } else if (QmlMetaType::isList(prop.userType()) ||
+ QmlMetaType::isQmlList(prop.userType())) {
+ rv.type = QmlObjectProperty::List;
+ }
+
+ return rv;
+}
+
+QVariant QmlEngineDebugServer::valueContents(const QVariant &value) const
+{
+ int userType = value.userType();
+ if (QVariant::Type(userType) < QVariant::UserType)
+ return value;
+
+
+ if (QmlMetaType::isList(userType) || QmlMetaType::isQmlList(userType)) {
+ int count = QmlMetaType::listCount(value);
+ QVariantList contents;
+ for (int i=0; i<count; i++)
+ contents << valueContents(QmlMetaType::listAt(value, i));
+ return contents;
+ } else if (QmlMetaType::isQObject(userType)) {
+ QObject *o = QmlMetaType::toQObject(value);
+ if (o) {
+ QString name = o->objectName();
+ if (name.isEmpty())
+ name = QLatin1String("<unnamed object>");
+ return name;
+ }
+ }
+
+ return QLatin1String("<unknown value>");
+}
+
+void QmlEngineDebugServer::buildObjectDump(QDataStream &message,
+ QObject *object, bool recur)
+{
+ message << objectData(object);
+
+ // Some children aren't added to an object until particular properties are read
+ // - e.g. child state objects aren't added until the 'states' property is read -
+ // but this should only affect internal objects that aren't shown by the
+ // debugger anyway.
+
+ QObjectList children = object->children();
+
+ int childrenCount = children.count();
+ for (int ii = 0; ii < children.count(); ++ii) {
+ if (qobject_cast<QmlContext*>(children[ii]) || QmlBoundSignal::cast(children[ii]))
+ --childrenCount;
+ }
+
+ message << childrenCount << recur;
+
+ QList<QmlObjectProperty> fakeProperties;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+ if (qobject_cast<QmlContext*>(child))
+ continue;
+ QmlBoundSignal *signal = QmlBoundSignal::cast(child);
+ if (signal) {
+ QmlObjectProperty prop;
+ prop.type = QmlObjectProperty::SignalProperty;
+ prop.hasNotifySignal = false;
+ QmlExpression *expr = signal->expression();
+ if (expr) {
+ prop.value = expr->expression();
+ QObject *scope = expr->scopeObject();
+ if (scope) {
+ QString sig = QLatin1String(scope->metaObject()->method(signal->index()).signature());
+ int lparen = sig.indexOf(QLatin1Char('('));
+ if (lparen >= 0) {
+ QString methodName = sig.mid(0, lparen);
+ prop.name = QLatin1String("on") + methodName[0].toUpper()
+ + methodName.mid(1);
+ }
+ }
+ }
+ fakeProperties << prop;
+ } else {
+ if (recur)
+ buildObjectDump(message, child, recur);
+ else
+ message << objectData(child);
+ }
+ }
+
+ message << (object->metaObject()->propertyCount() + fakeProperties.count());
+
+ for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii)
+ message << propertyData(object, ii);
+
+ for (int ii = 0; ii < fakeProperties.count(); ++ii)
+ message << fakeProperties[ii];
+}
+
+void QmlEngineDebugServer::buildObjectList(QDataStream &message,
+ QmlContext *ctxt)
+{
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+
+ QString ctxtName = ctxt->objectName();
+ int ctxtId = QmlDebugService::idForObject(ctxt);
+
+ message << ctxtName << ctxtId;
+
+ int count = 0;
+
+ for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin();
+ iter != p->childContexts.end(); ++iter) {
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter);
+ if (p->isInternal)
+ continue;
+ ++count;
+ }
+
+ message << count;
+
+ for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin();
+ iter != p->childContexts.end(); ++iter) {
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter);
+ if (p->isInternal)
+ continue;
+ buildObjectList(message, *iter);
+ }
+
+ // Clean deleted objects
+ for (int ii = 0; ii < p->instances.count(); ++ii) {
+ if (!p->instances.at(ii)) {
+ p->instances.removeAt(ii);
+ --ii;
+ }
+ }
+
+ message << p->instances.count();
+ for (int ii = 0; ii < p->instances.count(); ++ii) {
+ message << objectData(p->instances.at(ii));
+ }
+}
+
+QmlEngineDebugServer::QmlObjectData
+QmlEngineDebugServer::objectData(QObject *object)
+{
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(object);
+ QmlObjectData rv;
+ if (ddata) {
+ rv.url = ddata->outerContext->baseUrl();
+ rv.lineNumber = ddata->lineNumber;
+ rv.columnNumber = ddata->columnNumber;
+ } else {
+ rv.lineNumber = -1;
+ rv.columnNumber = -1;
+ }
+
+ rv.objectName = object->objectName();
+ rv.objectId = QmlDebugService::idForObject(object);
+ rv.contextId = QmlDebugService::idForObject(qmlContext(object));
+
+ QmlType *type = QmlMetaType::qmlType(object->metaObject());
+ if (type) {
+ QString typeName = QLatin1String(type->qmlTypeName());
+ int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
+ } else {
+ rv.objectType = QString::fromUtf8(object->metaObject()->className());
+ int marker = rv.objectType.indexOf(QLatin1String("_QMLTYPE_"));
+ if (marker != -1)
+ rv.objectType = rv.objectType.left(marker);
+ }
+
+ return rv;
+}
+
+void QmlEngineDebugServer::messageReceived(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ QByteArray type;
+ ds >> type;
+
+ //qDebug() << "QmlEngineDebugServer::messageReceived()" << type;
+
+ if (type == "LIST_ENGINES") {
+ int queryId;
+ ds >> queryId;
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_ENGINES_R");
+ rs << queryId << m_engines.count();
+
+ for (int ii = 0; ii < m_engines.count(); ++ii) {
+ QmlEngine *engine = m_engines.at(ii);
+
+ QString engineName = engine->objectName();
+ int engineId = QmlDebugService::idForObject(engine);
+
+ rs << engineName << engineId;
+ }
+
+ sendMessage(reply);
+ } else if (type == "LIST_OBJECTS") {
+ int queryId;
+ int engineId = -1;
+ ds >> queryId >> engineId;
+
+ QmlEngine *engine =
+ qobject_cast<QmlEngine *>(QmlDebugService::objectForId(engineId));
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_OBJECTS_R") << queryId;
+
+ if (engine)
+ buildObjectList(rs, engine->rootContext());
+
+ sendMessage(reply);
+ } else if (type == "FETCH_OBJECT") {
+ int queryId;
+ int objectId;
+ bool recurse;
+
+ ds >> queryId >> objectId >> recurse;
+
+ QObject *object = QmlDebugService::objectForId(objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("FETCH_OBJECT_R") << queryId;
+
+ if (object)
+ buildObjectDump(rs, object, recurse);
+
+ sendMessage(reply);
+ } else if (type == "WATCH_OBJECT") {
+ int queryId;
+ int objectId;
+
+ ds >> queryId >> objectId;
+ bool ok = m_watch->addWatch(queryId, objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_PROPERTY") {
+ int queryId;
+ int objectId;
+ QByteArray property;
+
+ ds >> queryId >> objectId >> property;
+ bool ok = m_watch->addWatch(queryId, objectId, property);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_EXPR_OBJECT") {
+ int queryId;
+ int debugId;
+ QString expr;
+
+ ds >> queryId >> debugId >> expr;
+ bool ok = m_watch->addWatch(queryId, debugId, expr);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "NO_WATCH") {
+ int queryId;
+
+ ds >> queryId;
+ m_watch->removeWatch(queryId);
+ } else if (type == "EVAL_EXPRESSION") {
+ int queryId;
+ int objectId;
+ QString expr;
+
+ ds >> queryId >> objectId >> expr;
+
+ QObject *object = QmlDebugService::objectForId(objectId);
+ QmlContext *context = qmlContext(object);
+ QVariant result;
+ if (object && context) {
+ QmlExpression *exprObj = new QmlExpression(context, expr, object);
+ bool undefined = false;
+ QVariant value = exprObj->value(&undefined);
+ if (undefined)
+ result = QLatin1String("<undefined>");
+ else
+ result = valueContents(value);
+ delete exprObj;
+ } else {
+ result = QLatin1String("<unknown context>");
+ }
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
+
+ sendMessage(reply);
+ }
+}
+
+void QmlEngineDebugServer::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
+{
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+
+ rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
+
+ sendMessage(reply);
+}
+
+void QmlEngineDebugServer::addEngine(QmlEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(!m_engines.contains(engine));
+
+ m_engines.append(engine);
+}
+
+void QmlEngineDebugServer::remEngine(QmlEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ m_engines.removeAll(engine);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlenginedebug_p.h b/src/declarative/qml/qmlenginedebug_p.h
new file mode 100644
index 0000000..7c48b8b
--- /dev/null
+++ b/src/declarative/qml/qmlenginedebug_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLENGINEDEBUG_P_H
+#define QMLENGINEDEBUG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "../debugger/qmldebugservice_p.h"
+
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlContext;
+class QmlWatcher;
+class QDataStream;
+
+class QmlEngineDebugServer : public QmlDebugService
+{
+ Q_OBJECT
+public:
+ QmlEngineDebugServer(QObject * = 0);
+
+ struct QmlObjectData {
+ QUrl url;
+ int lineNumber;
+ int columnNumber;
+ QString objectName;
+ QString objectType;
+ int objectId;
+ int contextId;
+ };
+
+ struct QmlObjectProperty {
+ enum Type { Unknown, Basic, Object, List, SignalProperty };
+ Type type;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal;
+ };
+
+ static void addEngine(QmlEngine *);
+ static void remEngine(QmlEngine *);
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+ void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
+
+private:
+ void buildObjectList(QDataStream &, QmlContext *);
+ void buildObjectDump(QDataStream &, QObject *, bool);
+ QmlObjectData objectData(QObject *);
+ QmlObjectProperty propertyData(QObject *, int);
+ QVariant valueContents(const QVariant &defaultValue) const;
+
+ static QList<QmlEngine *> m_engines;
+ QmlWatcher *m_watch;
+};
+Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectData &);
+Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectData &);
+Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectProperty &);
+Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectProperty &);
+
+QT_END_NAMESPACE
+
+#endif // QMLENGINEDEBUG_P_H
+
diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp
new file mode 100644
index 0000000..d9ca20d
--- /dev/null
+++ b/src/declarative/qml/qmlerror.cpp
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlerror.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlError
+ \brief The QmlError class encapsulates a QML error
+*/
+class QmlErrorPrivate
+{
+public:
+ QmlErrorPrivate();
+
+ QUrl url;
+ QString description;
+ int line;
+ int column;
+};
+
+QmlErrorPrivate::QmlErrorPrivate()
+: line(-1), column(-1)
+{
+}
+
+/*!
+ Create an empty error object.
+*/
+QmlError::QmlError()
+: d(0)
+{
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlError::QmlError(const QmlError &other)
+: d(0)
+{
+ *this = other;
+}
+
+/*!
+ Assign \a other to this error object.
+*/
+QmlError &QmlError::operator=(const QmlError &other)
+{
+ if (!other.d) {
+ delete d;
+ d = 0;
+ } else {
+ if (!d) d = new QmlErrorPrivate;
+ d->url = other.d->url;
+ d->description = other.d->description;
+ d->line = other.d->line;
+ d->column = other.d->column;
+ }
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QmlError::~QmlError()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Return true if this error is valid, otherwise false.
+*/
+bool QmlError::isValid() const
+{
+ return d != 0;
+}
+
+/*!
+ Return the url for the file that caused this error.
+*/
+QUrl QmlError::url() const
+{
+ if (d) return d->url;
+ else return QUrl();
+}
+
+/*!
+ Set the \a url for the file that caused this error.
+*/
+void QmlError::setUrl(const QUrl &url)
+{
+ if (!d) d = new QmlErrorPrivate;
+ d->url = url;
+}
+
+/*!
+ Return the error description.
+*/
+QString QmlError::description() const
+{
+ if (d) return d->description;
+ else return QString();
+}
+
+/*!
+ Set the error \a description.
+*/
+void QmlError::setDescription(const QString &description)
+{
+ if (!d) d = new QmlErrorPrivate;
+ d->description = description;
+}
+
+/*!
+ Return the error line number.
+*/
+int QmlError::line() const
+{
+ if (d) return d->line;
+ else return -1;
+}
+
+/*!
+ Set the error \a line number.
+*/
+void QmlError::setLine(int line)
+{
+ if (!d) d = new QmlErrorPrivate;
+ d->line = line;
+}
+
+/*!
+ Return the error column number.
+*/
+int QmlError::column() const
+{
+ if (d) return d->column;
+ else return -1;
+}
+
+/*!
+ Set the error \a column number.
+*/
+void QmlError::setColumn(int column)
+{
+ if (!d) d = new QmlErrorPrivate;
+ d->column = column;
+}
+
+/*!
+ Return the error as a human readable string.
+*/
+QString QmlError::toString() const
+{
+ QString rv;
+ rv = url().toString() + QLatin1Char(':') + QString::number(line());
+ if(column() != -1)
+ rv += QLatin1Char(':') + QString::number(column());
+
+ rv += QLatin1String(": ") + description();
+
+ return rv;
+}
+
+/*!
+ \relates QmlError
+ \fn QDebug operator<<(QDebug debug, const QmlError &error)
+
+ Output a human readable version of \a error to \a debug.
+*/
+
+QDebug operator<<(QDebug debug, const QmlError &error)
+{
+ debug << qPrintable(error.toString());
+
+ QUrl url = error.url();
+
+ if (error.line() > 0 && url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ stream.setCodec("UTF-8");
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ debug << "\n " << qPrintable(line);
+
+ if(error.column() > 0) {
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ debug << "\n " << ind.constData();
+ }
+ }
+ }
+ }
+ return debug;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlerror.h b/src/declarative/qml/qmlerror.h
new file mode 100644
index 0000000..c54f932
--- /dev/null
+++ b/src/declarative/qml/qmlerror.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLERROR_H
+#define QMLERROR_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDebug;
+class QmlErrorPrivate;
+class Q_DECLARATIVE_EXPORT QmlError
+{
+public:
+ QmlError();
+ QmlError(const QmlError &);
+ QmlError &operator=(const QmlError &);
+ ~QmlError();
+
+ bool isValid() const;
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ QString description() const;
+ void setDescription(const QString &);
+ int line() const;
+ void setLine(int);
+ int column() const;
+ void setColumn(int);
+
+ QString toString() const;
+private:
+ QmlErrorPrivate *d;
+};
+
+QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, const QmlError &error);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLERROR_H
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
new file mode 100644
index 0000000..6f32ef4
--- /dev/null
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -0,0 +1,831 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlexpression.h"
+#include "qmlexpression_p.h"
+
+#include "qmlengine_p.h"
+#include "qmlcontext_p.h"
+#include "qmlrewrite_p.h"
+#include "qmlcompiler_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptprogram.h>
+
+#include <private/qscriptdeclarativeclass_p.h>
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+bool QmlDelayedError::addError(QmlEnginePrivate *e)
+{
+ if (!e || prevError) return false;
+
+ if (e->inProgressCreations == 0) return false; // Not in construction
+
+ prevError = &e->erroredBindings;
+ nextError = e->erroredBindings;
+ e->erroredBindings = this;
+ if (nextError) nextError->prevError = &nextError;
+
+ return true;
+}
+
+QmlExpressionData::QmlExpressionData()
+: q(0), dataRef(0), expressionFunctionValid(false), expressionRewritten(false), me(0),
+ trackChange(true), isShared(false), line(-1), guardList(0), guardListLength(0)
+{
+}
+
+QmlExpressionData::~QmlExpressionData()
+{
+ if (guardList) { delete [] guardList; guardList = 0; }
+ if (dataRef) dataRef->release();
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate()
+: data(new QmlExpressionData)
+{
+ data->q = this;
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpressionData *d)
+: data(d)
+{
+ data->q = this;
+}
+
+QmlExpressionPrivate::~QmlExpressionPrivate()
+{
+ if (data) { data->q = 0; data->release(); data = 0; }
+}
+
+void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr,
+ QObject *me)
+{
+ data->expression = expr;
+
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
+}
+
+void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
+ QObject *me, const QString &url, int lineNumber)
+{
+ data->url = url;
+ data->line = lineNumber;
+
+ if (data->dataRef) data->dataRef->release();
+ data->dataRef = rc;
+ if (data->dataRef) data->dataRef->addref();
+
+ quint32 *exprData = (quint32 *)expr;
+ QmlCompiledData *dd = (QmlCompiledData *)rc;
+
+ data->expressionRewritten = true;
+ data->expression = QString::fromRawData((QChar *)(exprData + 2), exprData[1]);
+
+ int progIdx = *(exprData);
+ bool isShared = progIdx & 0x80000000;
+ progIdx &= 0x7FFFFFFF;
+
+ QmlEngine *engine = ctxt->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (isShared) {
+
+ if (!dd->cachedClosures.at(progIdx)) {
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+ scriptContext->pushScope(ep->contextClass->newSharedContext());
+ dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line));
+ scriptEngine->popContext();
+ }
+
+ data->expressionFunction = *dd->cachedClosures.at(progIdx);
+ data->isShared = true;
+ data->expressionFunctionValid = true;
+
+ } else {
+
+#if !defined(Q_OS_SYMBIAN) //XXX Why doesn't this work?
+ if (!dd->cachedPrograms.at(progIdx)) {
+ dd->cachedPrograms[progIdx] =
+ new QScriptProgram(data->expression, data->url, data->line);
+ }
+
+ data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx));
+#else
+ data->expressionFunction = evalInObjectScope(ctxt, me, data->expression);
+#endif
+
+ data->expressionFunctionValid = true;
+ }
+
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
+}
+
+QScriptValue QmlExpressionPrivate::evalInObjectScope(QmlContext *context, QObject *object,
+ const QString &program)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(context->engine());
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
+ scriptContext->pushScope(ep->contextClass->newContext(context, object));
+ QScriptValue rv = ep->scriptEngine.evaluate(program);
+ ep->scriptEngine.popContext();
+ return rv;
+}
+
+QScriptValue QmlExpressionPrivate::evalInObjectScope(QmlContext *context, QObject *object,
+ const QScriptProgram &program)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(context->engine());
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
+ scriptContext->pushScope(ep->contextClass->newContext(context, object));
+ QScriptValue rv = ep->scriptEngine.evaluate(program);
+ ep->scriptEngine.popContext();
+ return rv;
+}
+
+/*!
+ \class QmlExpression
+ \brief The QmlExpression class evaluates JavaScript in a QML context.
+*/
+
+/*!
+ Create an invalid QmlExpression.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+ */
+QmlExpression::QmlExpression()
+: QObject(*new QmlExpressionPrivate, 0)
+{
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
+ QmlRefCount *rc, QObject *me,
+ const QString &url, int lineNumber,
+ QmlExpressionPrivate &dd)
+: QObject(dd, 0)
+{
+ Q_D(QmlExpression);
+ d->init(ctxt, expr, rc, me, url, lineNumber);
+}
+
+/*!
+ Create a QmlExpression object.
+
+ The \a expression JavaScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
+ QObject *scope)
+: QObject(*new QmlExpressionPrivate, 0)
+{
+ Q_D(QmlExpression);
+ d->init(ctxt, expression, scope);
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
+ QObject *scope, QmlExpressionPrivate &dd)
+: QObject(dd, 0)
+{
+ Q_D(QmlExpression);
+ d->init(ctxt, expression, scope);
+}
+
+/*!
+ Destroy the QmlExpression instance.
+*/
+QmlExpression::~QmlExpression()
+{
+}
+
+/*!
+ Returns the QmlEngine this expression is associated with, or 0 if there
+ is no association or the QmlEngine has been destroyed.
+*/
+QmlEngine *QmlExpression::engine() const
+{
+ Q_D(const QmlExpression);
+ return d->data->context()?d->data->context()->engine():0;
+}
+
+/*!
+ Returns the QmlContext this expression is associated with, or 0 if there
+ is no association or the QmlContext has been destroyed.
+*/
+QmlContext *QmlExpression::context() const
+{
+ Q_D(const QmlExpression);
+ return d->data->context();
+}
+
+/*!
+ Returns the expression string.
+*/
+QString QmlExpression::expression() const
+{
+ Q_D(const QmlExpression);
+ return d->data->expression;
+}
+
+/*!
+ Clear the expression.
+*/
+void QmlExpression::clearExpression()
+{
+ setExpression(QString());
+}
+
+/*!
+ Set the expression to \a expression.
+*/
+void QmlExpression::setExpression(const QString &expression)
+{
+ Q_D(QmlExpression);
+
+ d->clearGuards();
+
+ d->data->expression = expression;
+ d->data->expressionFunctionValid = false;
+ d->data->expressionRewritten = false;
+ d->data->expressionFunction = QScriptValue();
+}
+
+void QmlExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
+ QmlError &error)
+{
+ if (scriptEngine->hasUncaughtException() &&
+ scriptEngine->uncaughtException().isError()) {
+
+ QString fileName;
+ int lineNumber = scriptEngine->uncaughtExceptionLineNumber();
+
+ QScriptValue exception = scriptEngine->uncaughtException();
+ QLatin1String fileNameProp("fileName");
+
+ if (!exception.property(fileNameProp).toString().isEmpty()){
+ fileName = exception.property(fileNameProp).toString();
+ } else {
+ fileName = QLatin1String("<Unknown File>");
+ }
+
+ error.setUrl(QUrl(fileName));
+ error.setLine(lineNumber);
+ error.setColumn(-1);
+ error.setDescription(exception.toString());
+ } else {
+ error = QmlError();
+ }
+}
+
+QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::BindValueQt> perfqt;
+#endif
+
+ QmlExpressionData *data = this->data;
+ QmlContextPrivate *ctxtPriv = data->context()->d_func();
+ QmlEngine *engine = data->context()->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ if (secondaryScope)
+ ctxtPriv->defaultObjects.append(secondaryScope);
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!data->expressionFunctionValid) {
+
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+ scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me));
+
+ if (data->expressionRewritten) {
+ data->expressionFunction = scriptEngine->evaluate(data->expression,
+ data->url, data->line);
+ } else {
+ QmlRewrite::RewriteBinding rewriteBinding;
+
+ bool ok = true;
+ const QString code = rewriteBinding(data->expression, &ok);
+ if (!ok) {
+ scriptEngine->popContext();
+ return QVariant();
+ }
+ data->expressionFunction = scriptEngine->evaluate(code, data->url, data->line);
+ }
+
+ scriptEngine->popContext();
+ data->expressionFunctionValid = true;
+ }
+
+ QmlContext *oldSharedContext = 0;
+ QObject *oldSharedScope = 0;
+ if (data->isShared) {
+ oldSharedContext = ep->sharedContext;
+ oldSharedScope = ep->sharedScope;
+ ep->sharedContext = data->context();
+ ep->sharedScope = data->me;
+ }
+
+ QScriptValue svalue = data->expressionFunction.call();
+
+ if (data->isShared) {
+ ep->sharedContext = oldSharedContext;
+ ep->sharedScope = oldSharedScope;
+ }
+
+ if (isUndefined)
+ *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException();
+
+ // Handle exception
+ if (scriptEngine->hasUncaughtException()) {
+ exceptionToError(scriptEngine, data->error);
+ scriptEngine->clearExceptions();
+ return QVariant();
+ } else {
+ data->error = QmlError();
+ }
+
+ if (secondaryScope) {
+ QObject *last = ctxtPriv->defaultObjects.takeLast();
+ Q_ASSERT(last == secondaryScope);
+ Q_UNUSED(last);
+ }
+
+ QVariant rv;
+
+ if (svalue.isArray()) {
+ int length = svalue.property(QLatin1String("length")).toInt32();
+ if (length && svalue.property(0).isObject()) {
+ QList<QObject *> list;
+ for (int ii = 0; ii < length; ++ii) {
+ QScriptValue arrayItem = svalue.property(ii);
+ QObject *d = arrayItem.toQObject();
+ list << d;
+ }
+ rv = QVariant::fromValue(list);
+ }
+ } else if (svalue.isObject() &&
+ ep->objectClass->scriptClass(svalue) == ep->objectClass) {
+ QObject *o = svalue.toQObject();
+ int type = QMetaType::QObjectStar;
+ // If the object is null, we extract the predicted type. While this isn't
+ // 100% reliable, in many cases it gives us better error messages if we
+ // assign this null-object to an incompatible property
+ if (!o) type = ep->objectClass->objectType(svalue);
+
+ return QVariant(type, &o);
+ }
+
+ if (rv.isNull())
+ rv = svalue.toVariant();
+
+ return rv;
+}
+
+QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
+{
+ Q_Q(QmlExpression);
+
+ QVariant rv;
+ if (!q->engine()) {
+ qWarning("QmlExpression: Attempted to evaluate an expression in an invalid context");
+ return rv;
+ }
+
+ if (data->expression.isEmpty())
+ return rv;
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::BindValue> perf;
+#endif
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(q->engine());
+
+ QmlExpression *lastCurrentExpression = ep->currentExpression;
+ bool lastCaptureProperties = ep->captureProperties;
+ QPODVector<QmlEnginePrivate::CapturedProperty> lastCapturedProperties;
+ ep->capturedProperties.copyAndClear(lastCapturedProperties);
+
+ ep->currentExpression = q;
+ ep->captureProperties = data->trackChange;
+
+ // This object might be deleted during the eval
+ QmlExpressionData *localData = data;
+ localData->addref();
+
+ rv = evalQtScript(secondaryScope, isUndefined);
+
+ ep->currentExpression = lastCurrentExpression;
+ ep->captureProperties = lastCaptureProperties;
+
+ // Check if we were deleted
+ if (localData->q) {
+ if ((!data->trackChange || !ep->capturedProperties.count()) && data->guardList) {
+ clearGuards();
+ } else if(data->trackChange) {
+ updateGuards(ep->capturedProperties);
+ }
+ }
+
+ localData->release();
+
+ lastCapturedProperties.copyAndClear(ep->capturedProperties);
+
+ return rv;
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+
+ \a isUndefined is set to true if the expression resulted in an
+ undefined value.
+
+ \sa hasError(), error()
+*/
+QVariant QmlExpression::value(bool *isUndefined)
+{
+ Q_D(QmlExpression);
+ return d->value(0, isUndefined);
+}
+
+/*!
+ Returns true if the expression results in a constant value.
+ QmlExpression::value() must have been invoked at least once before the
+ return from this method is valid.
+ */
+bool QmlExpression::isConstant() const
+{
+ Q_D(const QmlExpression);
+ return !d->data->guardList;
+}
+
+/*!
+ Returns true if the changes are tracked in the expression's value.
+*/
+bool QmlExpression::trackChange() const
+{
+ Q_D(const QmlExpression);
+ return d->data->trackChange;
+}
+
+/*!
+ Set whether changes are tracked in the expression's value to \a trackChange.
+
+ If true, the QmlExpression will monitor properties involved in the
+ expression's evaluation, and call QmlExpression::valueChanged() if they have
+ changed. This allows an application to ensure that any value associated
+ with the result of the expression remains up to date.
+
+ If false, the QmlExpression will not montitor properties involved in the
+ expression's evaluation, and QmlExpression::valueChanged() will never be
+ called. This is more efficient if an application wants a "one off"
+ evaluation of the expression.
+
+ By default, trackChange is true.
+*/
+void QmlExpression::setTrackChange(bool trackChange)
+{
+ Q_D(QmlExpression);
+ d->data->trackChange = trackChange;
+}
+
+/*!
+ Returns the source file URL for this expression. The source location must
+ have been previously set by calling setSourceLocation().
+*/
+QString QmlExpression::sourceFile() const
+{
+ Q_D(const QmlExpression);
+ return d->data->url;
+}
+
+/*!
+ Returns the source file line number for this expression. The source location
+ must have been previously set by calling setSourceLocation().
+*/
+int QmlExpression::lineNumber() const
+{
+ Q_D(const QmlExpression);
+ return d->data->line;
+}
+
+/*!
+ Set the location of this expression to \a line of \a url. This information
+ is used by the script engine.
+*/
+void QmlExpression::setSourceLocation(const QString &url, int line)
+{
+ Q_D(QmlExpression);
+ d->data->url = url;
+ d->data->line = line;
+}
+
+/*!
+ Returns the expression's scope object, if provided, otherwise 0.
+
+ In addition to data provided by the expression's QmlContext, the scope
+ object's properties are also in scope during the expression's evaluation.
+*/
+QObject *QmlExpression::scopeObject() const
+{
+ Q_D(const QmlExpression);
+ return d->data->me;
+}
+
+/*!
+ Returns true if the last call to value() resulted in an error,
+ otherwise false.
+
+ \sa error(), clearError()
+*/
+bool QmlExpression::hasError() const
+{
+ Q_D(const QmlExpression);
+ return d->data->error.isValid();
+}
+
+/*!
+ Clear any expression errors. Calls to hasError() following this will
+ return false.
+
+ \sa hasError(), error()
+*/
+void QmlExpression::clearError()
+{
+ Q_D(QmlExpression);
+ d->data->error = QmlError();
+}
+
+/*!
+ Return any error from the last call to value(). If there was no error,
+ this returns an invalid QmlError instance.
+
+ \sa hasError(), clearError()
+*/
+
+QmlError QmlExpression::error() const
+{
+ Q_D(const QmlExpression);
+ return d->data->error;
+}
+
+/*! \internal */
+void QmlExpression::__q_notify()
+{
+ emitValueChanged();
+}
+
+void QmlExpressionPrivate::clearGuards()
+{
+ Q_Q(QmlExpression);
+
+ static int notifyIdx = -1;
+ if (notifyIdx == -1)
+ notifyIdx =
+ QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
+
+ for (int ii = 0; ii < data->guardListLength; ++ii) {
+ if (data->guardList[ii].data()) {
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+ QMetaObject::disconnectOne(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
+ q, notifyIdx);
+#else
+ // QTBUG-6781
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
+ q, notifyIdx);
+#endif
+ }
+ }
+
+ delete [] data->guardList; data->guardList = 0;
+ data->guardListLength = 0;
+}
+
+void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties)
+{
+ //clearGuards();
+ Q_Q(QmlExpression);
+
+ static int notifyIdx = -1;
+ if (notifyIdx == -1)
+ notifyIdx =
+ QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
+
+ QmlExpressionData::SignalGuard *newGuardList = 0;
+
+ if (properties.count() != data->guardListLength)
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
+
+ bool outputWarningHeader = false;
+ int hit = 0;
+ for (int ii = 0; ii < properties.count(); ++ii) {
+ const QmlEnginePrivate::CapturedProperty &property = properties.at(ii);
+
+ bool needGuard = true;
+ if (ii >= data->guardListLength) {
+ // New guard
+ } else if(data->guardList[ii].data() == property.object &&
+ data->guardList[ii].notifyIndex == property.notifyIndex) {
+ // Cache hit
+ if (!data->guardList[ii].isDuplicate ||
+ (data->guardList[ii].isDuplicate && hit == ii)) {
+ needGuard = false;
+ ++hit;
+ }
+ } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
+ // Cache miss
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+ QMetaObject::disconnectOne(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
+ q, notifyIdx);
+#else
+ // QTBUG-6781
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
+ q, notifyIdx);
+#endif
+ }
+ /* else {
+ // Cache miss, but nothing to do
+ } */
+
+ if (needGuard) {
+ if (!newGuardList) {
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
+ for (int jj = 0; jj < ii; ++jj)
+ newGuardList[jj] = data->guardList[jj];
+ }
+
+ if (property.notifyIndex != -1) {
+ bool existing = false;
+ for (int jj = 0; !existing && jj < ii; ++jj)
+ existing = newGuardList[jj].data() == property.object &&
+ newGuardList[jj].notifyIndex == property.notifyIndex;
+
+ newGuardList[ii] = property.object;
+ newGuardList[ii].notifyIndex = property.notifyIndex;
+ if (existing)
+ newGuardList[ii].isDuplicate = true;
+ else
+ QMetaObject::connect(property.object, property.notifyIndex,
+ q, notifyIdx);
+ } else {
+ if (!outputWarningHeader) {
+ outputWarningHeader = true;
+ qWarning() << "QmlExpression: Expression" << q->expression()
+ << "depends on non-NOTIFYable properties:";
+ }
+
+ const QMetaObject *metaObj = property.object->metaObject();
+ QMetaProperty metaProp = metaObj->property(property.coreIndex);
+
+ qWarning().nospace() << " " << metaObj->className()
+ << "::" << metaProp.name();
+ }
+ } else if (newGuardList) {
+ newGuardList[ii] = data->guardList[ii];
+ }
+ }
+
+ for (int ii = properties.count(); ii < data->guardListLength; ++ii) {
+ if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+ QMetaObject::disconnectOne(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
+ q, notifyIdx);
+#else
+ // QTBUG-6781
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
+ q, notifyIdx);
+#endif
+ }
+ }
+
+ if (newGuardList) {
+ if (data->guardList) delete [] data->guardList;
+ data->guardList = newGuardList;
+ data->guardListLength = properties.count();
+ }
+}
+
+/*!
+ \fn void QmlExpression::valueChanged()
+
+ Emitted each time the expression value changes from the last time it was
+ evaluated. The expression must have been evaluated at least once (by
+ calling QmlExpression::value()) before this signal will be emitted.
+*/
+
+/*!
+ Subclasses can capture the emission of the valueChanged() signal by overriding
+ this function. They can choose whether to then call valueChanged().
+*/
+void QmlExpression::emitValueChanged()
+{
+ emit valueChanged();
+}
+
+QmlAbstractExpression::QmlAbstractExpression()
+: m_context(0), m_prevExpression(0), m_nextExpression(0)
+{
+}
+
+QmlAbstractExpression::~QmlAbstractExpression()
+{
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ }
+}
+
+QmlContext *QmlAbstractExpression::context() const
+{
+ return m_context;
+}
+
+void QmlAbstractExpression::setContext(QmlContext *context)
+{
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ m_prevExpression = 0;
+ m_nextExpression = 0;
+ }
+
+ m_context = context;
+
+ if (m_context) {
+ QmlContextPrivate *cp =
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(m_context));
+ m_nextExpression = cp->expressions;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = &m_nextExpression;
+ m_prevExpression = &cp->expressions;
+ cp->expressions = this;
+ }
+}
+
+void QmlAbstractExpression::refresh()
+{
+}
+
+bool QmlAbstractExpression::isValid() const
+{
+ return m_context != 0;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
new file mode 100644
index 0000000..4df7641
--- /dev/null
+++ b/src/declarative/qml/qmlexpression.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLEXPRESSION_H
+#define QMLEXPRESSION_H
+
+#include "qmlerror.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlRefCount;
+class QmlEngine;
+class QmlContext;
+class QmlExpressionPrivate;
+class Q_DECLARATIVE_EXPORT QmlExpression : public QObject
+{
+ Q_OBJECT
+public:
+ QmlExpression();
+ QmlExpression(QmlContext *, const QString &, QObject *);
+ virtual ~QmlExpression();
+
+ QmlEngine *engine() const;
+ QmlContext *context() const;
+
+ QString expression() const;
+ void clearExpression();
+ virtual void setExpression(const QString &);
+ bool isConstant() const;
+
+ bool trackChange() const;
+ void setTrackChange(bool);
+
+ QString sourceFile() const;
+ int lineNumber() const;
+ void setSourceLocation(const QString &fileName, int line);
+
+ QObject *scopeObject() const;
+
+ bool hasError() const;
+ void clearError();
+ QmlError error() const;
+
+public Q_SLOTS:
+ QVariant value(bool *isUndefined = 0);
+
+Q_SIGNALS:
+ void valueChanged();
+
+protected:
+ virtual void emitValueChanged();
+
+ QmlExpression(QmlContext *, const QString &, QObject *,
+ QmlExpressionPrivate &dd);
+ QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, const QString &,
+ int, QmlExpressionPrivate &dd);
+
+private Q_SLOTS:
+ void __q_notify();
+
+private:
+ Q_DECLARE_PRIVATE(QmlExpression)
+ friend class QmlDebugger;
+ friend class QmlContext;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLEXPRESSION_H
+
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
new file mode 100644
index 0000000..b19c60c
--- /dev/null
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLEXPRESSION_P_H
+#define QMLEXPRESSION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlexpression.h"
+
+#include "qmlengine_p.h"
+#include "qmlguard_p.h"
+
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlAbstractExpression
+{
+public:
+ QmlAbstractExpression();
+ virtual ~QmlAbstractExpression();
+
+ bool isValid() const;
+
+ QmlContext *context() const;
+ void setContext(QmlContext *);
+
+ virtual void refresh();
+
+private:
+ friend class QmlContext;
+ friend class QmlContextPrivate;
+ QmlContext *m_context;
+ QmlAbstractExpression **m_prevExpression;
+ QmlAbstractExpression *m_nextExpression;
+};
+
+class QmlDelayedError
+{
+public:
+ inline QmlDelayedError() : nextError(0), prevError(0) {}
+ inline ~QmlDelayedError() { removeError(); }
+
+ QmlError error;
+
+ bool addError(QmlEnginePrivate *);
+
+ inline void removeError() {
+ if (!prevError) return;
+ if (nextError) nextError->prevError = prevError;
+ *prevError = nextError;
+ nextError = 0;
+ prevError = 0;
+ }
+
+private:
+ QmlDelayedError *nextError;
+ QmlDelayedError **prevError;
+};
+
+class QmlExpressionData : public QmlAbstractExpression, public QmlDelayedError, public QmlRefCount
+{
+public:
+ QmlExpressionData();
+ virtual ~QmlExpressionData();
+
+ QmlExpressionPrivate *q;
+
+ QmlRefCount *dataRef;
+ QString expression;
+ bool expressionFunctionValid:1;
+ bool expressionRewritten:1;
+ QScriptValue expressionFunction;
+
+ QObject *me;
+ bool trackChange;
+
+ bool isShared;
+
+ QString url; // This is a QString for a reason. QUrls are slooooooow...
+ int line;
+
+ struct SignalGuard : public QmlGuard<QObject> {
+ SignalGuard() : isDuplicate(false), notifyIndex(-1) {}
+
+ SignalGuard &operator=(QObject *obj) {
+ QmlGuard<QObject>::operator=(obj);
+ return *this;
+ }
+ SignalGuard &operator=(const SignalGuard &o) {
+ QmlGuard<QObject>::operator=(o);
+ isDuplicate = o.isDuplicate;
+ notifyIndex = o.notifyIndex;
+ return *this;
+ }
+
+ bool isDuplicate:1;
+ int notifyIndex:31;
+ };
+ SignalGuard *guardList;
+ int guardListLength;
+};
+
+class QmlExpression;
+class QString;
+class QmlExpressionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlExpression)
+public:
+ QmlExpressionPrivate();
+ QmlExpressionPrivate(QmlExpressionData *);
+ ~QmlExpressionPrivate();
+
+ void init(QmlContext *, const QString &, QObject *);
+ void init(QmlContext *, void *, QmlRefCount *, QObject *, const QString &, int);
+
+ QmlExpressionData *data;
+
+ QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
+ QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0);
+
+ void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties);
+ void clearGuards();
+
+ static QmlExpressionPrivate *get(QmlExpression *expr) {
+ return static_cast<QmlExpressionPrivate *>(QObjectPrivate::get(expr));
+ }
+ static QmlExpression *get(QmlExpressionPrivate *expr) {
+ return expr->q_func();
+ }
+
+ static void exceptionToError(QScriptEngine *, QmlError &);
+ static QScriptValue evalInObjectScope(QmlContext *, QObject *, const QString &);
+ static QScriptValue evalInObjectScope(QmlContext *, QObject *, const QScriptProgram &);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLEXPRESSION_P_H
diff --git a/src/declarative/qml/qmlglobal_p.h b/src/declarative/qml/qmlglobal_p.h
new file mode 100644
index 0000000..dc282bc
--- /dev/null
+++ b/src/declarative/qml/qmlglobal_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGLOBAL_H
+#define QMLGLOBAL_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+#define DEFINE_BOOL_CONFIG_OPTION(name, var) \
+ static bool name() \
+ { \
+ static enum { Yes, No, Unknown } status = Unknown; \
+ if (status == Unknown) { \
+ QByteArray v = qgetenv(#var); \
+ bool value = !v.isEmpty() && v != "0" && v != "false"; \
+ if (value) status = Yes; \
+ else status = No; \
+ } \
+ return status == Yes; \
+ }
+
+struct QmlGraphics_DerivedObject : public QObject
+{
+ void setParent_noEvent(QObject *parent) {
+ bool sce = d_ptr->sendChildEvents;
+ d_ptr->sendChildEvents = false;
+ setParent(parent);
+ d_ptr->sendChildEvents = sce;
+ }
+};
+
+/*!
+ Makes the \a object a child of \a parent. Note that when using this method,
+ neither \a parent nor the object's previous parent (if it had one) will
+ receive ChildRemoved or ChildAdded events.
+*/
+inline void QmlGraphics_setParent_noEvent(QObject *object, QObject *parent)
+{
+ static_cast<QmlGraphics_DerivedObject *>(object)->setParent_noEvent(parent);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLGLOBAL_H
diff --git a/src/declarative/qml/qmlglobalscriptclass.cpp b/src/declarative/qml/qmlglobalscriptclass.cpp
new file mode 100644
index 0000000..13c1017
--- /dev/null
+++ b/src/declarative/qml/qmlglobalscriptclass.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlglobalscriptclass_p.h"
+
+#include <QtScript/qscriptstring.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptvalueiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Used to prevent any writes to the global object.
+*/
+QmlGlobalScriptClass::QmlGlobalScriptClass(QScriptEngine *engine)
+: QScriptClass(engine)
+{
+ QScriptValue v = engine->newObject();
+ globalObject = engine->globalObject();
+
+ QScriptValueIterator iter(globalObject);
+ while (iter.hasNext()) {
+ iter.next();
+ v.setProperty(iter.scriptName(), iter.value());
+ }
+
+ v.setScriptClass(this);
+ engine->setGlobalObject(v);
+}
+
+QScriptClass::QueryFlags
+QmlGlobalScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(flags);
+ Q_UNUSED(id);
+ return HandlesReadAccess | HandlesWriteAccess;
+}
+
+QScriptValue
+QmlGlobalScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(id);
+ return engine()->undefinedValue();
+}
+
+void QmlGlobalScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id, const QScriptValue &value)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(id);
+ Q_UNUSED(value);
+ QString error = QLatin1String("Invalid write to global property \"") +
+ name.toString() + QLatin1Char('\"');
+ engine()->currentContext()->throwError(error);
+}
+
+void QmlGlobalScriptClass::explicitSetProperty(const QString &name, const QScriptValue &value)
+{
+ QScriptValue v = engine()->newObject();
+ globalObject = engine()->globalObject();
+
+ QScriptValueIterator iter(globalObject);
+ while (iter.hasNext()) {
+ iter.next();
+ v.setProperty(iter.scriptName(), iter.value());
+ }
+
+ v.setProperty(name, value);
+ v.setScriptClass(this);
+ engine()->setGlobalObject(v);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlglobalscriptclass_p.h b/src/declarative/qml/qmlglobalscriptclass_p.h
new file mode 100644
index 0000000..56c91fe
--- /dev/null
+++ b/src/declarative/qml/qmlglobalscriptclass_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGLOBALSCRIPTCLASS_P_H
+#define QMLGLOBALSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptclass.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QmlGlobalScriptClass : public QScriptClass
+{
+public:
+ QmlGlobalScriptClass(QScriptEngine *);
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name, uint id);
+
+ virtual void setProperty(QScriptValue &object, const QScriptString &name,
+ uint id, const QScriptValue &value);
+
+ void explicitSetProperty(const QString &, const QScriptValue &);
+
+private:
+ QScriptValue globalObject;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGLOBALSCRIPTCLASS_P_H
diff --git a/src/declarative/qml/qmlguard_p.h b/src/declarative/qml/qmlguard_p.h
new file mode 100644
index 0000000..1e55bcb
--- /dev/null
+++ b/src/declarative/qml/qmlguard_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGUARD_P_H
+#define QMLGUARD_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 <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+template<class T>
+class QmlGuard
+{
+ QObject *o;
+ QmlGuard<QObject> *next;
+ QmlGuard<QObject> **prev;
+ friend class QmlDeclarativeData;
+public:
+ inline QmlGuard();
+ inline QmlGuard(T *);
+ inline QmlGuard(const QmlGuard<T> &);
+ inline virtual ~QmlGuard();
+
+ inline QmlGuard<T> &operator=(const QmlGuard<T> &o);
+ inline QmlGuard<T> &operator=(T *);
+
+ inline bool isNull() const
+ { return !o; }
+
+ inline T* operator->() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+ inline T& operator*() const
+ { return *static_cast<T*>(const_cast<QObject*>(o)); }
+ inline operator T*() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+ inline T* data() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+
+protected:
+ virtual void objectDestroyed(T *) {}
+
+private:
+ inline void addGuard();
+ inline void remGuard();
+};
+
+Q_DECLARE_METATYPE(QmlGuard<QObject>);
+
+QT_END_NAMESPACE
+
+#include "qmldeclarativedata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+template<class T>
+QmlGuard<T>::QmlGuard()
+: o(0), next(0), prev(0)
+{
+}
+
+template<class T>
+QmlGuard<T>::QmlGuard(T *g)
+: o(g), next(0), prev(0)
+{
+ if (o) addGuard();
+}
+
+template<class T>
+QmlGuard<T>::QmlGuard(const QmlGuard<T> &g)
+: o(g.o), next(0), prev(0)
+{
+ if (o) addGuard();
+}
+
+template<class T>
+QmlGuard<T>::~QmlGuard()
+{
+ if (prev) remGuard();
+ o = 0;
+}
+
+template<class T>
+QmlGuard<T> &QmlGuard<T>::operator=(const QmlGuard<T> &g)
+{
+ if (g.o != o) {
+ if (prev) remGuard();
+ o = g.o;
+ if (o) addGuard();
+ }
+ return *this;
+}
+
+template<class T>
+QmlGuard<T> &QmlGuard<T>::operator=(T *g)
+{
+ if (g != o) {
+ if (prev) remGuard();
+ o = g;
+ if (o) addGuard();
+ }
+ return *this;
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLGUARD_P_H
diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp
new file mode 100644
index 0000000..dabf944
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlinfo.h"
+
+#include "qmldeclarativedata_p.h"
+#include "qmlcontext.h"
+#include "qmlmetatype.h"
+
+#include <QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \fn QmlInfo qmlInfo(const QObject *object)
+
+ \brief Prints warnings messages that include the file and line number for QML types.
+
+ When QML types display warning messages, it improves traceability
+ if they include the QML file and line number on which the
+ particular instance was instantiated.
+
+ To include the file and line number, an object must be passed. If
+ the file and line number is not available for that instance
+ (either it was not instantiated by the QML engine or location
+ information is disabled), "unknown location" will be used instead.
+
+ For example,
+
+ \code
+ qmlInfo(object) << tr("component property is a write-once property");
+ \endcode
+
+ prints
+
+ \code
+ QML MyCustomType (unknown location): component property is a write-once property
+ \endcode
+*/
+
+QmlInfo::QmlInfo(const QObject *object)
+: QDebug(QtWarningMsg)
+{
+ QString pos = QLatin1String("QML");
+ if (object) {
+ pos += QLatin1Char(' ');
+
+ QString typeName;
+ QmlType *type = QmlMetaType::qmlType(object->metaObject());
+ if (type) {
+ typeName = QLatin1String(type->qmlTypeName());
+ int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash != -1)
+ typeName = typeName.mid(lastSlash+1);
+ } else {
+ typeName = QString::fromUtf8(object->metaObject()->className());
+ int marker = typeName.indexOf(QLatin1String("_QMLTYPE_"));
+ if (marker != -1)
+ typeName = typeName.left(marker);
+ }
+
+ pos += typeName;
+ }
+ QmlDeclarativeData *ddata = object?QmlDeclarativeData::get(object):0;
+ pos += QLatin1String(" (");
+ if (ddata) {
+ if (ddata->outerContext) {
+ pos += ddata->outerContext->baseUrl().toString();
+ pos += QLatin1Char(':');
+ pos += QString::number(ddata->lineNumber);
+ pos += QLatin1Char(':');
+ pos += QString::number(ddata->columnNumber);
+ } else {
+ pos += QCoreApplication::translate("QmlInfo","unknown location");
+ }
+ } else {
+ pos += QCoreApplication::translate("QmlInfo","unknown location");
+ }
+ pos += QLatin1Char(')');
+ *this << pos;
+ nospace();
+}
+
+QmlInfo::~QmlInfo()
+{
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinfo.h b/src/declarative/qml/qmlinfo.h
new file mode 100644
index 0000000..fd56118
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINFO_H
+#define QMLINFO_H
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlInfo : public QDebug
+{
+public:
+ QmlInfo(const QObject *);
+ ~QmlInfo();
+
+ inline QmlInfo &operator<<(QChar t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(QBool t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(bool t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(char t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(signed short t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(unsigned short t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(signed int t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(unsigned int t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(signed long t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(unsigned long t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(qint64 t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(quint64 t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(float t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(double t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(const char* t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(const QString & t) { QDebug::operator<<(t.toLocal8Bit().constData()); return *this; }
+ inline QmlInfo &operator<<(const QStringRef & t) { return operator<<(t.toString()); }
+ inline QmlInfo &operator<<(const QLatin1String &t) { QDebug::operator<<(t.latin1()); return *this; }
+ inline QmlInfo &operator<<(const QByteArray & t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(const void * t) { QDebug::operator<<(t); return *this; }
+ inline QmlInfo &operator<<(QTextStreamFunction f) { QDebug::operator<<(f); return *this; }
+ inline QmlInfo &operator<<(QTextStreamManipulator m) { QDebug::operator<<(m); return *this; }
+};
+
+Q_DECLARATIVE_EXPORT inline QmlInfo qmlInfo(const QObject *me)
+{
+ return QmlInfo(me);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLINFO_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
new file mode 100644
index 0000000..d99bf65
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlinstruction_p.h"
+
+#include "qmlcompiler_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+void QmlCompiledData::dump(QmlInstruction *instr, int idx)
+{
+ QByteArray lineNumber = QByteArray::number(instr->line);
+ if (instr->line == (unsigned short)-1)
+ lineNumber = "NA";
+ const char *line = lineNumber.constData();
+
+ switch(instr->type) {
+ case QmlInstruction::Init:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "INIT\t\t\t" << instr->init.bindingsSize << "\t" << instr->init.parserStatusSize << "\t" << instr->init.contextCache << "\t" << instr->init.compiledBinding;
+ break;
+ case QmlInstruction::CreateObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
+ break;
+ case QmlInstruction::SetId:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value);
+ break;
+ case QmlInstruction::SetDefault:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "SET_DEFAULT";
+ break;
+ case QmlInstruction::CreateComponent:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
+ break;
+ case QmlInstruction::StoreMetaObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data;
+ break;
+
+ case QmlInstruction::StoreFloat:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value;
+ break;
+ case QmlInstruction::StoreDouble:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
+ break;
+ case QmlInstruction::StoreInteger:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
+ break;
+ case QmlInstruction::StoreBool:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
+ break;
+ case QmlInstruction::StoreString:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreUrl:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << primitives.at(instr->storeUrl.value);
+ break;
+ case QmlInstruction::StoreColor:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t\t\t" << QString::number(instr->storeColor.value, 16);
+ break;
+ case QmlInstruction::StoreDate:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value;
+ break;
+ case QmlInstruction::StoreTime:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex;
+ break;
+ case QmlInstruction::StoreDateTime:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex;
+ break;
+ case QmlInstruction::StorePoint:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StorePointF:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSize:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSizeF:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreRect:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreRectF:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreVector3D:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.valueIndex;
+ break;
+ case QmlInstruction::StoreVariant:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex;
+ break;
+ case QmlInstruction::StoreVariantObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex;
+ break;
+ case QmlInstruction::StoreInterface:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex;
+ break;
+
+ case QmlInstruction::StoreSignal:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value);
+ break;
+ case QmlInstruction::StoreScript:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SCRIPT\t\t" << instr->storeScript.value;
+ break;
+ case QmlInstruction::StoreScriptString:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SCRIPT_STRING\t" << instr->storeScriptString.propertyIndex << "\t" << instr->storeScriptString.value << "\t" << instr->storeScriptString.scope;
+ break;
+
+ case QmlInstruction::AssignSignalObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal);
+ break;
+ case QmlInstruction::AssignCustomType:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
+ break;
+
+ case QmlInstruction::StoreBinding:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
+ break;
+ case QmlInstruction::StoreCompiledBinding:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
+ break;
+ case QmlInstruction::StoreValueSource:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue;
+ break;
+ case QmlInstruction::StoreValueInterceptor:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue;
+ break;
+
+ case QmlInstruction::BeginObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue;
+ break;
+ case QmlInstruction::StoreObjectQmlList:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT_QMLLIST";
+ break;
+ case QmlInstruction::StoreObjectQList:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT_QLIST";
+ break;
+ case QmlInstruction::AssignObjectList:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "ASSIGN_OBJECT_LIST";
+ break;
+ case QmlInstruction::FetchAttached:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id;
+ break;
+ case QmlInstruction::FetchQmlList:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_QMLLIST\t\t" << instr->fetchQmlList.property << "\t" << instr->fetchQmlList.type;
+ break;
+ case QmlInstruction::FetchQList:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_QLIST\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::FetchObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH\t\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::FetchValueType:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type;
+ break;
+ case QmlInstruction::PopFetchedObject:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "POP";
+ break;
+ case QmlInstruction::PopQList:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "POP_QLIST";
+ break;
+ case QmlInstruction::PopValueType:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "POP_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type;
+ break;
+ case QmlInstruction::Defer:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "DEFER" << "\t\t\t" << instr->defer.deferCount;
+ break;
+ default:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "XXX UNKOWN INSTRUCTION" << "\t" << instr->type;
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
new file mode 100644
index 0000000..0639397
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINSTRUCTION_P_H
+#define QMLINSTRUCTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompiledData;
+class Q_DECLARATIVE_EXPORT QmlInstruction
+{
+public:
+ enum Type {
+ //
+ // Object Creation
+ //
+ // CreateObject - Create a new object instance and push it on the
+ // object stack
+ // SetId - Set the id of the object on the top of the object stack
+ // SetDefault - Sets the instance on the top of the object stack to
+ // be the context's default object.
+ // StoreMetaObject - Assign the dynamic metaobject to object on the
+ // top of the stack.
+ Init, /* init */
+ CreateObject, /* create */
+ SetId, /* setId */
+ SetDefault,
+ CreateComponent, /* createComponent */
+ StoreMetaObject, /* storeMeta */
+
+ //
+ // Precomputed single assignment
+ //
+ // StoreFloat - Store a float in a core property
+ // StoreDouble - Store a double in a core property
+ // StoreInteger - Store a int or uint in a core property
+ // StoreBool - Store a bool in a core property
+ // StoreString - Store a QString in a core property
+ // StoreUrl - Store a QUrl in a core property
+ // StoreColor - Store a QColor in a core property
+ // StoreDate - Store a QDate in a core property
+ // StoreTime - Store a QTime in a core property
+ // StoreDateTime - Store a QDateTime in a core property
+ // StoreVariant - Store a QVariant in a core property
+ // StoreObject - Pop the object on the top of the object stack and
+ // store it in a core property
+ StoreFloat, /* storeFloat */
+ StoreDouble, /* storeDouble */
+ StoreInteger, /* storeInteger */
+ StoreBool, /* storeBool */
+ StoreString, /* storeString */
+ StoreUrl, /* storeUrl */
+ StoreColor, /* storeColor */
+ StoreDate, /* storeDate */
+ StoreTime, /* storeTime */
+ StoreDateTime, /* storeDateTime */
+ StorePoint, /* storeRealPair */
+ StorePointF, /* storeRealPair */
+ StoreSize, /* storeRealPair */
+ StoreSizeF, /* storeRealPair */
+ StoreRect, /* storeRect */
+ StoreRectF, /* storeRect */
+ StoreVector3D, /* storeVector3D */
+ StoreVariant, /* storeString */
+ StoreObject, /* storeObject */
+ StoreVariantObject, /* storeObject */
+ StoreInterface, /* storeObject */
+
+ StoreSignal, /* storeSignal */
+ StoreScript, /* storeScript */
+ StoreScriptString, /* storeScriptString */
+
+ //
+ // Unresolved single assignment
+ //
+ AssignSignalObject, /* assignSignalObject */
+ AssignCustomType, /* assignCustomType */
+
+ StoreBinding, /* assignBinding */
+ StoreCompiledBinding, /* assignBinding */
+ StoreValueSource, /* assignValueSource */
+ StoreValueInterceptor, /* assignValueInterceptor */
+
+ BeginObject, /* begin */
+
+ StoreObjectQmlList, /* NA */
+ StoreObjectQList, /* NA */
+ AssignObjectList, /* NA */
+
+ FetchAttached, /* fetchAttached */
+ FetchQmlList, /* fetchQmlList */
+ FetchQList, /* fetch */
+ FetchObject, /* fetch */
+ FetchValueType, /* fetchValue */
+
+ //
+ // Stack manipulation
+ //
+ // PopFetchedObject - Remove an object from the object stack
+ // PopQList - Remove a list from the list stack
+ PopFetchedObject,
+ PopQList,
+ PopValueType, /* fetchValue */
+
+ //
+ // Deferred creation
+ //
+ Defer, /* defer */
+ };
+ QmlInstruction()
+ : line(0) {}
+
+ Type type;
+ unsigned short line;
+ union {
+ struct {
+ int bindingsSize;
+ int parserStatusSize;
+ int contextCache;
+ int compiledBinding;
+ } init;
+ struct {
+ int type;
+ int data;
+ int bindingBits;
+ ushort column;
+ } create;
+ struct {
+ int data;
+ int aliasData;
+ int propertyCache;
+ } storeMeta;
+ struct {
+ int value;
+ int index;
+ } setId;
+ struct {
+ int property;
+ int owner;
+ int castValue;
+ } assignValueSource;
+ struct {
+ int property;
+ int owner;
+ int castValue;
+ } assignValueInterceptor;
+ struct {
+ unsigned int property;
+ int value;
+ short context;
+ short owner;
+ } assignBinding;
+ struct {
+ int property;
+ int id;
+ } assignIdOptBinding;
+ struct {
+ int property;
+ int contextIdx;
+ short context;
+ short notifyIdx;
+ } assignObjPropBinding;
+ struct {
+ int property;
+ } fetch;
+ struct {
+ int property;
+ int type;
+ } fetchValue;
+ struct {
+ int property;
+ int type;
+ } fetchQmlList;
+ struct {
+ int castValue;
+ } begin;
+ struct {
+ int propertyIndex;
+ float value;
+ } storeFloat;
+ struct {
+ int propertyIndex;
+ double value;
+ } storeDouble;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeInteger;
+ struct {
+ int propertyIndex;
+ bool value;
+ } storeBool;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeString;
+ struct {
+ int propertyIndex;
+ int value;
+ int scope;
+ } storeScriptString;
+ struct {
+ int value;
+ } storeScript;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeUrl;
+ struct {
+ int propertyIndex;
+ unsigned int value;
+ } storeColor;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeDate;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeDateTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRealPair;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRect;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeVector3D;
+ struct {
+ int propertyIndex;
+ } storeObject;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } assignCustomType;
+ struct {
+ int signalIndex;
+ int value;
+ } storeSignal;
+ struct {
+ int signal;
+ } assignSignalObject;
+ struct {
+ int count;
+ ushort column;
+ int endLine;
+ int metaObject;
+ } createComponent;
+ struct {
+ int id;
+ } fetchAttached;
+ struct {
+ int deferCount;
+ } defer;
+ };
+
+ void dump(QmlCompiledData *);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLINSTRUCTION_P_H
diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp
new file mode 100644
index 0000000..1968873
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlintegercache_p.h"
+
+#include "qmlengine_p.h"
+#include "qmlmetatype.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlIntegerCache::QmlIntegerCache(QmlEngine *e)
+: QmlCleanup(e), engine(e)
+{
+}
+
+QmlIntegerCache::~QmlIntegerCache()
+{
+ clear();
+}
+
+void QmlIntegerCache::clear()
+{
+ qDeleteAll(stringCache);
+ stringCache.clear();
+ identifierCache.clear();
+ engine = 0;
+}
+
+void QmlIntegerCache::add(const QString &id, int value)
+{
+ Q_ASSERT(!stringCache.contains(id));
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### use contextClass
+ Data *d = new Data(enginePriv->objectClass->createPersistentIdentifier(id), value);
+
+ stringCache.insert(id, d);
+ identifierCache.insert(d->identifier, d);
+}
+
+int QmlIntegerCache::value(const QString &id)
+{
+ Data *d = stringCache.value(id);
+ return d?d->value:-1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlintegercache_p.h b/src/declarative/qml/qmlintegercache_p.h
new file mode 100644
index 0000000..d9df52a
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINTEGERCACHE_P_H
+#define QMLINTEGERCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlrefcount_p.h"
+#include "qmlcleanup_p.h"
+
+#include <QtCore/qhash.h>
+
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlIntegerCache : public QmlRefCount, public QmlCleanup
+{
+public:
+ QmlIntegerCache(QmlEngine *);
+ virtual ~QmlIntegerCache();
+
+ inline int count() const;
+ void add(const QString &, int);
+ int value(const QString &);
+ inline int value(const QScriptDeclarativeClass::Identifier &id) const;
+
+protected:
+ virtual void clear();
+
+private:
+ struct Data : public QScriptDeclarativeClass::PersistentIdentifier {
+ Data(const QScriptDeclarativeClass::PersistentIdentifier &i, int v)
+ : QScriptDeclarativeClass::PersistentIdentifier(i), value(v) {}
+
+ int value;
+ };
+
+ typedef QHash<QString, Data *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, Data *> IdentifierCache;
+
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+ QmlEngine *engine;
+};
+
+int QmlIntegerCache::value(const QScriptDeclarativeClass::Identifier &id) const
+{
+ Data *d = identifierCache.value(id);
+ return d?d->value:-1;
+}
+
+int QmlIntegerCache::count() const
+{
+ return stringCache.count();
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLINTEGERCACHE_P_H
+
diff --git a/src/declarative/qml/qmllist.h b/src/declarative/qml/qmllist.h
new file mode 100644
index 0000000..ad2d874
--- /dev/null
+++ b/src/declarative/qml/qmllist.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLIST_H
+#define QMLLIST_H
+
+#include "qmlprivate.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<typename T>
+class QmlList : private QmlPrivate::ListInterface
+{
+public:
+ virtual void append(T) = 0;
+ virtual void insert(int, T) = 0;
+ virtual void removeAt(int) = 0;
+ virtual T at(int) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ QmlList<T> &operator<<(T t) { append(t); return *this; }
+
+protected:
+ virtual int type() const { return qMetaTypeId<T>(); }
+ virtual void append(void *d) { const T &v = *(T *)d; append(v); }
+ virtual void insert(int i, void *d) { const T &v = *(T *)d; insert(i, v); }
+ virtual void at(int i, void *p) const { const T &v = at(i); *((T*)p) = v; }
+};
+
+template<typename T>
+class QmlConcreteList : public QList<T>, public QmlList<T>
+{
+public:
+ virtual void append(T v) { QList<T>::append(v); }
+ virtual void insert(int i, T v) { QList<T>::insert(i, v); }
+ virtual void clear() { QList<T>::clear(); }
+ virtual T at(int i) const { return QList<T>::at(i); }
+ virtual void removeAt(int i) { QList<T>::removeAt(i); }
+ virtual int count() const { return QList<T>::count(); }
+};
+
+#define QML_DECLARE_LIST_PROXY(ClassName, ListType, ListName) \
+class Qml_ProxyList_ ##ListName : public QmlList<ListType> \
+{ \
+ public: \
+ virtual void removeAt(int idx) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _removeAt(idx); \
+ } \
+ virtual int count() const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _count(); \
+ } \
+ virtual void append(ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _append(v); \
+ } \
+ virtual void insert(int idx, ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _insert(idx, v); \
+ } \
+ virtual ListType at(int idx) const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _at(idx); \
+ } \
+ virtual void clear() \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _clear(); \
+ } \
+}; \
+friend class Qml_ProxyList_ ##ListName ; \
+Qml_ProxyList_##ListName ListName;
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLIST_H
diff --git a/src/declarative/qml/qmllistscriptclass.cpp b/src/declarative/qml/qmllistscriptclass.cpp
new file mode 100644
index 0000000..d4cdc6e
--- /dev/null
+++ b/src/declarative/qml/qmllistscriptclass.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmllistscriptclass_p.h"
+
+#include "qmlengine_p.h"
+#include "qmlguard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct ListData : public QScriptDeclarativeClass::Object {
+ QmlGuard<QObject> object;
+ int propertyIdx;
+ QmlListScriptClass::ListCategory type;
+ int propertyType;
+};
+
+QmlListScriptClass::QmlListScriptClass(QmlEngine *e)
+: QmlScriptClass(QmlEnginePrivate::getScriptEngine(e)), engine(e)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ Q_UNUSED(scriptEngine);
+
+ m_lengthId = createPersistentIdentifier(QLatin1String("length"));
+}
+
+QmlListScriptClass::~QmlListScriptClass()
+{
+}
+
+QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListCategory type, int propType)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!object || propId == -1)
+ return scriptEngine->nullValue();
+
+ ListData *data = new ListData;
+ data->object = object;
+ data->propertyIdx = propId;
+ data->type = type;
+ data->propertyType = propType;
+
+ return newObject(scriptEngine, this, data);
+}
+
+QScriptClass::QueryFlags
+QmlListScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(flags);
+ if (name == m_lengthId.identifier)
+ return QScriptClass::HandlesReadAccess;
+
+ bool ok = false;
+ quint32 idx = toArrayIndex(name, &ok);
+
+ if (ok) {
+ lastIndex = idx;
+ return QScriptClass::HandlesReadAccess;
+ } else {
+ return 0;
+ }
+}
+
+QmlListScriptClass::ScriptValue QmlListScriptClass::property(Object *obj, const Identifier &name)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ ListData *data = (ListData *)obj;
+ if (!data->object)
+ return Value();
+
+ void *list = 0;
+ void *args[] = { &list, 0 };
+ QMetaObject::metacall(data->object, QMetaObject::ReadProperty,
+ data->propertyIdx, args);
+
+ if (!list)
+ return Value();
+
+ if (data->type == QListPtr) {
+ const QList<QObject *> &qlist = *((QList<QObject *>*)list);
+
+ quint32 count = qlist.count();
+
+ if (name == m_lengthId.identifier)
+ return Value(scriptEngine, count);
+ else if (lastIndex < count)
+ return Value(scriptEngine, enginePriv->objectClass->newQObject(qlist.at(lastIndex)));
+ else
+ return Value();
+
+ } else {
+ Q_ASSERT(data->type == QmlListPtr);
+ const QmlList<QObject *> &qmllist = *((QmlList<QObject *>*)list);
+
+ quint32 count = qmllist.count();
+
+ if (name == m_lengthId.identifier)
+ return Value(scriptEngine, count);
+ else if (lastIndex < count)
+ return Value(scriptEngine, enginePriv->objectClass->newQObject(qmllist.at(lastIndex)));
+ else
+ return Value();
+ }
+}
+
+QVariant QmlListScriptClass::toVariant(Object *obj, bool *ok)
+{
+ ListData *data = (ListData *)obj;
+
+ if (!data->object) {
+ if (ok) *ok = false;
+ return QVariant();
+ }
+
+ void *list = 0;
+ void *args[] = { &list, 0 };
+ QMetaObject::metacall(data->object, QMetaObject::ReadProperty,
+ data->propertyIdx, args);
+
+ if (!list) {
+ if (ok) *ok = false;
+ return QVariant();
+ }
+
+ if (ok) *ok = true;
+ return QVariant(data->propertyType, &list);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmllistscriptclass_p.h b/src/declarative/qml/qmllistscriptclass_p.h
new file mode 100644
index 0000000..e484b34
--- /dev/null
+++ b/src/declarative/qml/qmllistscriptclass_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLISTSCRIPTCLASS_P_H
+#define QMLLISTSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qmlscriptclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlListScriptClass : public QmlScriptClass
+{
+public:
+ QmlListScriptClass(QmlEngine *);
+ ~QmlListScriptClass();
+
+ enum ListCategory { QListPtr, QmlListPtr };
+ QScriptValue newList(QObject *, int, ListCategory, int);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ virtual ScriptValue property(Object *, const Identifier &);
+ virtual QVariant toVariant(Object *, bool *ok);
+
+private:
+ PersistentIdentifier m_lengthId;
+ QmlEngine *engine;
+
+ quint32 lastIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLLISTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
new file mode 100644
index 0000000..f23a50a
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -0,0 +1,1245 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlmetaproperty.h"
+#include "qmlmetaproperty_p.h"
+
+#include "qmlcompositetypedata_p.h"
+#include "qml.h"
+#include "qmlbinding.h"
+#include "qmlcontext.h"
+#include "qmlcontext_p.h"
+#include "qmlboundsignal_p.h"
+#include "qmlengine.h"
+#include "qmlengine_p.h"
+#include "qmldeclarativedata_p.h"
+#include "qmlstringconverters_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QStringList>
+#include <QtCore/qdebug.h>
+
+#include <math.h>
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlMetaProperty
+ \brief The QmlMetaProperty class abstracts accessing QML properties.
+ \internal
+ */
+
+/*!
+ Create an invalid QmlMetaProperty.
+*/
+QmlMetaProperty::QmlMetaProperty()
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+}
+
+/*! \internal */
+QmlMetaProperty::~QmlMetaProperty()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->initDefault(obj);
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->context = ctxt;
+ d->initDefault(obj);
+}
+
+/*!
+ Initialize from the default property of \a obj
+*/
+void QmlMetaPropertyPrivate::initDefault(QObject *obj)
+{
+ if (!obj)
+ return;
+
+ QMetaProperty p = QmlMetaType::defaultProperty(obj);
+ core.load(p);
+ if (core.isValid()) {
+ isDefaultProperty = true;
+ object = obj;
+ }
+}
+
+/*!
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->initProperty(obj, name);
+ if (!isValid()) d->object = 0;
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->context = ctxt;
+ d->initProperty(obj, name);
+ if (!isValid()) { d->object = 0; d->context = 0; }
+}
+
+void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
+{
+ QmlEnginePrivate *enginePrivate = 0;
+ if (context && context->engine())
+ enginePrivate = QmlEnginePrivate::get(context->engine());
+
+ object = obj;
+
+ if (name.isEmpty() || !obj)
+ return;
+
+ if (enginePrivate && name.at(0).isUpper()) {
+ // Attached property
+ // ### What about qualified types?
+ QmlTypeNameCache *tnCache = QmlContextPrivate::get(context)->imports;
+ if (tnCache) {
+ QmlTypeNameCache::Data *d = tnCache->data(name);
+ if (d && d->type && d->type->attachedPropertiesFunction()) {
+ attachedFunc = d->type->index();
+ }
+ }
+ return;
+
+ } else if (name.count() >= 3 &&
+ name.at(0) == QChar(QLatin1Char('o')) &&
+ name.at(1) == QChar(QLatin1Char('n')) &&
+ name.at(2).isUpper()) {
+ // Signal
+ QString signalName = name.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ QMetaMethod method = findSignal(obj, signalName);
+ if (method.signature()) {
+ core.load(method);
+ return;
+ }
+ }
+
+ // Property
+ QmlPropertyCache::Data local;
+ QmlPropertyCache::Data *property =
+ QmlPropertyCache::property(context?context->engine():0, obj, name, local);
+ if (property && !(property->flags & QmlPropertyCache::Data::IsFunction))
+ core = *property;
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other)
+: d(new QmlMetaPropertyPrivate(*other.d))
+{
+ d->q = this;
+}
+
+/*!
+ \enum QmlMetaProperty::PropertyCategory
+
+ This enum specifies a category of QML property.
+
+ \value Unknown The category is unknown. This will never be returned from propertyCategory()
+ \value InvalidProperty The property is invalid.
+ \value Bindable The property is a QmlBinding.
+ \value List The property is a QList pointer
+ \value QmlList The property is a QmlList pointer
+ \value Object The property is a QObject derived type pointer
+ \value Normal The property is none of the above.
+ */
+
+/*!
+ \enum QmlMetaProperty::Type
+
+ This enum specifies a type of QML property.
+
+ \value Invalid The property is invalid.
+ \value Property The property is a regular Qt property.
+ \value SignalProperty The property is a signal property.
+ \value Default The property is the default property.
+ \value Attached The property is an attached property.
+*/
+
+/*!
+ Returns the property category.
+*/
+QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
+{
+ return d->propertyCategory();
+}
+
+QmlMetaProperty::PropertyCategory
+QmlMetaPropertyPrivate::propertyCategory() const
+{
+ uint type = q->type();
+
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return QmlMetaProperty::Normal;
+ } else if (type & QmlMetaProperty::Attached) {
+ return QmlMetaProperty::Object;
+ } else if (type & QmlMetaProperty::Property) {
+ int type = propertyType();
+ if (type == QVariant::Invalid)
+ return QmlMetaProperty::InvalidProperty;
+ else if ((uint)type < QVariant::UserType)
+ return QmlMetaProperty::Normal;
+ else if (type == qMetaTypeId<QmlBinding *>())
+ return QmlMetaProperty::Bindable;
+ else if (core.flags & QmlPropertyCache::Data::IsQObjectDerived)
+ return QmlMetaProperty::Object;
+ else if (core.flags & QmlPropertyCache::Data::IsQmlList)
+ return QmlMetaProperty::QmlList;
+ else if (core.flags & QmlPropertyCache::Data::IsQList)
+ return QmlMetaProperty::List;
+ else
+ return QmlMetaProperty::Normal;
+ } else {
+ return QmlMetaProperty::InvalidProperty;
+ }
+}
+
+/*!
+ Returns the type name of the property, or 0 if the property has no type
+ name.
+*/
+const char *QmlMetaProperty::propertyTypeName() const
+{
+ if (type() & ValueTypeProperty) {
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ const char *rv = valueType->metaObject()->property(d->valueType.valueTypeCoreIdx).typeName();
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else if (d->object && type() & Property && d->core.isValid()) {
+ return d->object->metaObject()->property(d->core.coreIndex).typeName();
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Returns true if \a other and this QmlMetaProperty represent the same
+ property.
+*/
+bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
+{
+ // category is intentially omitted here as it is generated
+ // from the other members
+ return d->object == other.d->object &&
+ d->core == other.d->core &&
+ d->valueType == other.d->valueType &&
+ d->attachedFunc == other.d->attachedFunc;
+}
+
+/*!
+ Returns the QVariant type of the property, or QVariant::Invalid if the
+ property has no QVariant type.
+*/
+int QmlMetaProperty::propertyType() const
+{
+ return d->propertyType();
+}
+
+int QmlMetaPropertyPrivate::propertyType() const
+{
+ uint type = q->type();
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return valueType.valueTypePropType;
+ } else if (type & QmlMetaProperty::Attached) {
+ return qMetaTypeId<QObject *>();
+ } else if (type & QmlMetaProperty::Property) {
+ if (core.propType == (int)QVariant::LastType)
+ return qMetaTypeId<QVariant>();
+ else
+ return core.propType;
+ } else {
+ return QVariant::Invalid;
+ }
+}
+
+/*!
+ Returns the type of the property.
+*/
+QmlMetaProperty::Type QmlMetaProperty::type() const
+{
+ if (d->core.flags & QmlPropertyCache::Data::IsFunction)
+ return SignalProperty;
+ else if (d->attachedFunc != -1)
+ return Attached;
+ else if (d->valueType.valueTypeCoreIdx != -1)
+ return (Type)(Property | ValueTypeProperty);
+ else if (d->core.isValid())
+ return (Type)(Property | ((d->isDefaultProperty)?Default:0));
+ else
+ return Invalid;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a regular Qt property.
+*/
+bool QmlMetaProperty::isProperty() const
+{
+ return type() & Property;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a default property.
+*/
+bool QmlMetaProperty::isDefault() const
+{
+ return type() & Default;
+}
+
+/*!
+ Returns the QmlMetaProperty's QObject.
+*/
+QObject *QmlMetaProperty::object() const
+{
+ return d->object;
+}
+
+/*!
+ Assign \a other to this QmlMetaProperty.
+*/
+QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
+{
+ d->context = other.d->context;
+ d->object = other.d->object;
+
+ d->isDefaultProperty = other.d->isDefaultProperty;
+ d->core = other.d->core;
+
+ d->valueType = other.d->valueType;
+
+ d->attachedFunc = other.d->attachedFunc;
+ return *this;
+}
+
+/*!
+ Returns true if the property is writable, otherwise false.
+*/
+bool QmlMetaProperty::isWritable() const
+{
+ QmlMetaProperty::PropertyCategory category = propertyCategory();
+
+ if (!d->object)
+ return false;
+ if (category == List || category == QmlList)
+ return true;
+ else if (type() & SignalProperty)
+ return false;
+ else if (d->core.isValid() && d->object)
+ return d->core.flags & QmlPropertyCache::Data::IsWritable;
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is designable, otherwise false.
+*/
+bool QmlMetaProperty::isDesignable() const
+{
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isDesignable();
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is resettable, otherwise false.
+*/
+bool QmlMetaProperty::isResettable() const
+{
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->core.flags & QmlPropertyCache::Data::IsResettable;
+ else
+ return false;
+}
+
+/*!
+ Returns true if the QmlMetaProperty refers to a valid property, otherwise
+ false.
+*/
+bool QmlMetaProperty::isValid() const
+{
+ return type() != Invalid;
+}
+
+/*!
+ Return the name of this QML property.
+*/
+QString QmlMetaProperty::name() const
+{
+ if (!d->isNameCached) {
+ // ###
+ if (!d->object) {
+ } else if (type() & ValueTypeProperty) {
+ QString rv = d->core.name(d->object) + QLatin1Char('.');
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ rv += QString::fromUtf8(valueType->metaObject()->property(d->valueType.valueTypeCoreIdx).name());
+
+ if (!ep) delete valueType;
+
+ d->nameCache = rv;
+ } else if (type() & SignalProperty) {
+ QString name = QLatin1String("on") + d->core.name(d->object);
+ name[2] = name.at(2).toUpper();
+ d->nameCache = name;
+ } else {
+ d->nameCache = d->core.name(d->object);
+ }
+ d->isNameCached = true;
+ }
+
+ return d->nameCache;
+}
+
+/*!
+ Returns the \l{QMetaProperty} {Qt property} associated with
+ this QML property.
+ */
+QMetaProperty QmlMetaProperty::property() const
+{
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex);
+ else
+ return QMetaProperty();
+}
+
+/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ if (type() & SignalProperty && d->object)
+ return d->object->metaObject()->method(d->core.coreIndex);
+ else
+ return QMetaMethod();
+}
+
+
+/*!
+ Returns the binding associated with this property, or 0 if no binding
+ exists.
+*/
+QmlAbstractBinding *QmlMetaProperty::binding() const
+{
+ if (!isProperty() || (type() & Attached) || !d->object)
+ return 0;
+
+ QmlDeclarativeData *data = QmlDeclarativeData::get(d->object);
+ if (!data)
+ return 0;
+
+ if (!data->hasBindingBit(d->core.coreIndex))
+ return 0;
+
+ QmlAbstractBinding *binding = data->bindings;
+ while (binding) {
+ // ### This wont work for value types
+ if (binding->propertyIndex() == d->core.coreIndex)
+ return binding;
+ binding = binding->m_nextBinding;
+ }
+ return 0;
+}
+
+/*!
+ Set the binding associated with this property to \a newBinding. Returns
+ the existing binding (if any), otherwise 0.
+
+ \a newBinding will be enabled, and the returned binding (if any) will be
+ disabled.
+
+ Ownership of \a newBinding transfers to QML. Ownership of the return value
+ is assumed by the caller.
+
+ \a flags is passed through to the binding and is used for the initial update (when
+ the binding sets the intial value, it will use these flags for the write).
+*/
+QmlAbstractBinding *
+QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) const
+{
+ if (!isProperty() || (type() & Attached) || !d->object) {
+ if (newBinding)
+ newBinding->destroy();
+ return 0;
+ }
+
+ return d->setBinding(d->object, d->core, newBinding, flags);
+}
+
+QmlAbstractBinding *
+QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core,
+ QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding);
+
+ if (data && data->hasBindingBit(core.coreIndex)) {
+ QmlAbstractBinding *binding = data->bindings;
+ while (binding) {
+ // ### This wont work for value types
+ if (binding->propertyIndex() == core.coreIndex) {
+ binding->setEnabled(false);
+
+ if (newBinding)
+ newBinding->setEnabled(true, flags);
+
+ return binding; // ### QmlAbstractBinding;
+ }
+
+ binding = binding->m_nextBinding;
+ }
+ }
+
+ if (newBinding)
+ newBinding->setEnabled(true, flags);
+
+ return 0;
+}
+/*!
+ Returns the expression associated with this signal property, or 0 if no
+ signal expression exists.
+*/
+QmlExpression *QmlMetaProperty::signalExpression() const
+{
+ if (!(type() & SignalProperty))
+ return 0;
+
+ const QObjectList &children = d->object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+
+ QmlBoundSignal *signal = QmlBoundSignal::cast(child);
+ if (signal && signal->index() == coreIndex())
+ return signal->expression();
+ }
+
+ return 0;
+}
+
+/*!
+ Set the signal expression associated with this signal property to \a expr.
+ Returns the existing signal expression (if any), otherwise 0.
+
+ Ownership of \a expr transfers to QML. Ownership of the return value is
+ assumed by the caller.
+*/
+QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const
+{
+ if (!(type() & SignalProperty)) {
+ delete expr;
+ return 0;
+ }
+
+ const QObjectList &children = d->object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+
+ QmlBoundSignal *signal = QmlBoundSignal::cast(child);
+ if (signal && signal->index() == coreIndex())
+ return signal->setExpression(expr);
+ }
+
+ if (expr) {
+ QmlBoundSignal *signal = new QmlBoundSignal(d->object, method(), d->object);
+ return signal->setExpression(expr);
+ } else {
+ return 0;
+ }
+}
+
+QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name)
+{
+ const QMetaObject *mo = obj->metaObject();
+
+ int methods = mo->methodCount();
+ for (int ii = methods - 1; ii >= 0; --ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QString::fromUtf8(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+
+ if (methodName == name)
+ return method;
+ }
+ return QMetaMethod();
+}
+
+QObject *QmlMetaPropertyPrivate::attachedObject() const
+{
+ if (attachedFunc == -1)
+ return 0;
+ else
+ return qmlAttachedPropertiesObjectById(attachedFunc, object);
+}
+
+/*!
+ Returns the property value.
+*/
+QVariant QmlMetaProperty::read() const
+{
+ if (!d->object)
+ return QVariant();
+
+ if (type() & SignalProperty) {
+
+ return QVariant();
+
+ } else if (type() & Property || type() & Attached) {
+
+ return d->readValueProperty();
+
+ }
+ return QVariant();
+}
+
+QVariant QmlMetaPropertyPrivate::readValueProperty()
+{
+ uint type = q->type();
+ if (type & QmlMetaProperty::Attached) {
+
+ return QVariant::fromValue(attachedObject());
+
+ } else if(type & QmlMetaProperty::ValueTypeProperty) {
+
+ QmlEnginePrivate *ep = context?QmlEnginePrivate::get(context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[core.propType];
+ else valueType = QmlValueTypeFactory::valueType(core.propType);
+ Q_ASSERT(valueType);
+
+ valueType->read(object, core.coreIndex);
+
+ QVariant rv =
+ valueType->metaObject()->property(this->valueType.valueTypeCoreIdx).read(valueType);
+
+ if (!ep) delete valueType;
+ return rv;
+
+ } else {
+
+ return object->metaObject()->property(core.coreIndex).read(object.data());
+
+ }
+}
+
+//###
+//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC!
+//###
+bool QmlMetaPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags)
+{
+ if (!object || !prop.isWritable())
+ return false;
+
+ QVariant v = value;
+ if (prop.isEnumType()) {
+ QMetaEnum menum = prop.enumerator();
+ if (v.userType() == QVariant::String
+#ifdef QT3_SUPPORT
+ || v.userType() == QVariant::CString
+#endif
+ ) {
+ if (prop.isFlagType())
+ v = QVariant(menum.keysToValue(value.toByteArray()));
+ else
+ v = QVariant(menum.keyToValue(value.toByteArray()));
+ } else if (v.userType() != QVariant::Int && v.userType() != QVariant::UInt) {
+ int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope()) + "::" + menum.name());
+ if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+ return false;
+ v = QVariant(*reinterpret_cast<const int *>(v.constData()));
+ }
+ v.convert(QVariant::Int);
+ }
+
+ // 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[] = { v.data(), &v, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv);
+ return status;
+}
+
+bool QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
+ QmlMetaProperty::WriteFlags flags)
+{
+ // Remove any existing bindings on this property
+ if (!(flags & QmlMetaProperty::DontRemoveBinding))
+ delete q->setBinding(0);
+
+ bool rv = false;
+ uint type = q->type();
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ QmlEnginePrivate *ep =
+ context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+
+ QmlValueType *writeBack = 0;
+ if (ep) {
+ writeBack = ep->valueTypes[core.propType];
+ } else {
+ writeBack = QmlValueTypeFactory::valueType(core.propType);
+ }
+
+ writeBack->read(object, core.coreIndex);
+
+ QmlPropertyCache::Data data = core;
+ data.coreIndex = valueType.valueTypeCoreIdx;
+ data.propType = valueType.valueTypePropType;
+ rv = write(writeBack, data, value, context, flags);
+
+ writeBack->write(object, core.coreIndex, flags);
+ if (!ep) delete writeBack;
+
+ } else {
+
+ rv = write(object, core, value, context, flags);
+
+ }
+
+ return rv;
+}
+
+bool QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property,
+ const QVariant &value, QmlContext *context,
+ QmlMetaProperty::WriteFlags flags)
+{
+ int coreIdx = property.coreIndex;
+ int status = -1; //for dbus
+
+ if (property.flags & QmlPropertyCache::Data::IsEnumType) {
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
+ QVariant v = value;
+ // Enum values come through the script engine as doubles
+ if (value.userType() == QVariant::Double) {
+ double integral;
+ double fractional = modf(value.toDouble(), &integral);
+ if (qFuzzyIsNull(fractional))
+ v.convert(QVariant::Int);
+ }
+ return writeEnumProperty(prop, coreIdx, object, v, flags);
+ }
+
+ int t = property.propType;
+ int vt = value.userType();
+
+ QmlEnginePrivate *enginePriv = 0;
+ if (context && context->engine())
+ enginePriv = QmlEnginePrivate::get(context->engine());
+
+ if (t == QVariant::Url) {
+
+ QUrl u;
+ bool found = false;
+ if (vt == QVariant::Url) {
+ u = value.toUrl();
+ found = true;
+ } else if (vt == QVariant::ByteArray) {
+ u = QUrl(QString::fromUtf8(value.toByteArray()));
+ found = true;
+ } else if (vt == QVariant::String) {
+ u = QUrl(value.toString());
+ found = true;
+ }
+
+ if (!found)
+ return false;
+
+ if (context && u.isRelative() && !u.isEmpty())
+ u = context->resolvedUrl(u);
+ int status = -1;
+ void *argv[] = { &u, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
+
+ } else if (vt == t) {
+
+ void *a[] = { (void *)value.constData(), 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+
+ } else if (qMetaTypeId<QVariant>() == t) {
+
+ void *a[] = { (void *)&value, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+
+ } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) {
+
+ const QMetaObject *valMo = rawMetaObjectForType(enginePriv, value.userType());
+
+ if (!valMo)
+ return false;
+
+ QObject *o = *(QObject **)value.constData();
+ const QMetaObject *propMo = rawMetaObjectForType(enginePriv, t);
+
+ if (o) valMo = o->metaObject();
+
+ if (canConvert(valMo, propMo)) {
+ void *args[] = { &o, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx,
+ args);
+ } else if (!o && canConvert(propMo, valMo)) {
+ // In the case of a null QObject, we assign the null if there is
+ // any change that the null variant type could be up or down cast to
+ // the property type.
+ void *args[] = { &o, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx,
+ args);
+ } else {
+ return false;
+ }
+
+ } else if (property.flags & QmlPropertyCache::Data::IsQList) {
+
+ int listType = QmlMetaType::listType(t);
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
+
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = prop.read(object);
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::qmlType(listType)->fromObject(list.at(ii));
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (vt == listType ||
+ value.userType() == listType) {
+ QVariant listVar = prop.read(object);
+ QmlMetaType::append(listVar, value);
+ }
+
+ } else if (property.flags & QmlPropertyCache::Data::IsQmlList) {
+
+ // XXX - optimize!
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
+ QVariant list = prop.read(object);
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo = rawMetaObjectForType(enginePriv, type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (equal(objMo, mo))
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found)
+ return false;
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else {
+ Q_ASSERT(vt != t);
+
+ QVariant v = value;
+ if (v.convert((QVariant::Type)t)) {
+ void *a[] = { (void *)v.constData(), 0, &status, &flags};
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
+ QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
+ if (!con)
+ return false;
+
+ QVariant v = con(value.toString());
+ if (v.userType() == t) {
+ void *a[] = { (void *)v.constData(), 0, &status, &flags};
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ }
+ } else if (vt == QVariant::String) {
+ bool ok = false;
+ QVariant v = QmlStringConverters::variantFromString(value.toString(), t, &ok);
+ if (!ok)
+ return false;
+
+ void *a[] = { (void *)v.constData(), 0, &status, &flags};
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const QMetaObject *QmlMetaPropertyPrivate::rawMetaObjectForType(QmlEnginePrivate *engine, int userType)
+{
+ if (engine) {
+ return engine->rawMetaObjectForType(userType);
+ } else {
+ QmlType *type = QmlMetaType::qmlType(userType);
+ return type?type->baseMetaObject():0;
+ }
+}
+
+/*!
+ Set the property value to \a value.
+*/
+bool QmlMetaProperty::write(const QVariant &value) const
+{
+ return write(value, 0);
+}
+
+/*!
+ Resets the property value.
+*/
+bool QmlMetaProperty::reset() const
+{
+ if (isResettable()) {
+ void *args[] = { 0 };
+ QMetaObject::metacall(d->object, QMetaObject::ResetProperty, d->core.coreIndex, args);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const
+{
+ if (d->object && type() & Property && d->core.isValid() && isWritable())
+ return d->writeValueProperty(value, flags);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a change notifier signal, otherwise false.
+*/
+bool QmlMetaProperty::hasChangedNotifier() const
+{
+ if (type() & Property && !(type() & Attached) && d->object) {
+ return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal();
+ }
+ return false;
+}
+
+/*!
+ Returns true if the property needs a change notifier signal for bindings
+ to remain upto date, false otherwise.
+
+ Some properties, such as attached properties or those whose value never
+ changes, do not require a change notifier.
+*/
+bool QmlMetaProperty::needsChangedNotifier() const
+{
+ return type() & Property && !(type() & Attached) &&
+ !property().isConstant();
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a method of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a method.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
+{
+ if (!(type() & Property) || (type() & Attached) || !d->object)
+ return false;
+
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
+ if (prop.hasNotifySignal()) {
+ return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a slot of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a slot.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
+{
+ if (!(type() & Property) || (type() & Attached) || !d->object)
+ return false;
+
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
+ if (prop.hasNotifySignal()) {
+ QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
+ return QObject::connect(d->object, signal.constData(), dest, slot);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Return the Qt metaobject index of the property.
+*/
+int QmlMetaProperty::coreIndex() const
+{
+ return d->core.coreIndex;
+}
+
+/*! \internal */
+int QmlMetaProperty::valueTypeCoreIndex() const
+{
+ return d->valueType.valueTypeCoreIdx;
+}
+
+Q_GLOBAL_STATIC(QmlValueTypeFactory, qmlValueTypes);
+
+
+struct SerializedData {
+ QmlMetaProperty::Type type;
+ QmlPropertyCache::Data core;
+};
+
+struct ValueTypeSerializedData : public SerializedData {
+ QmlPropertyCache::ValueTypeData valueType;
+};
+
+QByteArray QmlMetaPropertyPrivate::saveValueType(const QMetaObject *metaObject, int index,
+ int subIndex, int subType)
+{
+ ValueTypeSerializedData sd;
+ sd.type = QmlMetaProperty::ValueTypeProperty;
+ sd.core.load(metaObject->property(index));
+ sd.valueType.valueTypeCoreIdx = subIndex;
+ sd.valueType.valueTypePropType = subType;
+
+ QByteArray rv((const char *)&sd, sizeof(sd));
+ return rv;
+}
+
+QByteArray QmlMetaPropertyPrivate::saveProperty(const QMetaObject *metaObject, int index)
+{
+ SerializedData sd;
+ sd.type = QmlMetaProperty::Property;
+ sd.core.load(metaObject->property(index));
+
+ QByteArray rv((const char *)&sd, sizeof(sd));
+ return rv;
+}
+
+QmlMetaProperty
+QmlMetaPropertyPrivate::restore(const QByteArray &data, QObject *object, QmlContext *ctxt)
+{
+ QmlMetaProperty prop;
+
+ if (data.isEmpty())
+ return prop;
+
+ prop.d->object = object;
+ prop.d->context = ctxt;
+
+ const SerializedData *sd = (const SerializedData *)data.constData();
+ if (sd->type == QmlMetaProperty::Property) {
+ prop.d->core = sd->core;
+ } else if(sd->type == QmlMetaProperty::ValueTypeProperty) {
+ const ValueTypeSerializedData *vt = (const ValueTypeSerializedData *)sd;
+ prop.d->core = vt->core;
+ prop.d->valueType = vt->valueType;
+ }
+
+ return prop;
+}
+
+/*!
+ \internal
+
+ Creates a QmlMetaProperty for the property \a name of \a obj. Unlike
+ the QmlMetaProperty(QObject*, QString, QmlContext*) constructor, this static function
+ will correctly handle dot properties, including value types and attached properties.
+*/
+QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj,
+ const QString &name,
+ QmlContext *context)
+{
+ QmlTypeNameCache *typeNameCache = context?QmlContextPrivate::get(context)->imports:0;
+
+ QStringList path = name.split(QLatin1Char('.'));
+ QObject *object = obj;
+
+ for (int jj = 0; jj < path.count() - 1; ++jj) {
+ const QString &pathName = path.at(jj);
+
+ if (QmlTypeNameCache::Data *data = typeNameCache?typeNameCache->data(pathName):0) {
+ if (data->type) {
+ QmlAttachedPropertiesFunc func = data->type->attachedPropertiesFunction();
+ if (!func)
+ return QmlMetaProperty();
+ object = qmlAttachedPropertiesObjectById(data->type->index(), object);
+ if (!object)
+ return QmlMetaProperty();
+ continue;
+ } else {
+ Q_ASSERT(data->typeNamespace);
+ ++jj;
+ data = data->typeNamespace->data(path.at(jj));
+ if (!data || !data->type)
+ return QmlMetaProperty();
+ QmlAttachedPropertiesFunc func = data->type->attachedPropertiesFunction();
+ if (!func)
+ return QmlMetaProperty();
+ object = qmlAttachedPropertiesObjectById(data->type->index(), object);
+ if (!object)
+ return QmlMetaProperty();
+ continue;
+ }
+ }
+
+ QmlMetaProperty prop(object, pathName, context);
+
+ if (jj == path.count() - 2 && prop.propertyType() < (int)QVariant::UserType &&
+ qmlValueTypes()->valueTypes[prop.propertyType()]) {
+ // We're now at a value type property. We can use a global valuetypes array as we
+ // never actually use the objects, just look up their properties.
+ QObject *typeObject =
+ qmlValueTypes()->valueTypes[prop.propertyType()];
+ int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
+ if (idx == -1)
+ return QmlMetaProperty();
+ QMetaProperty vtProp = typeObject->metaObject()->property(idx);
+
+ QmlMetaProperty p = prop;
+ p.d->valueType.valueTypeCoreIdx = idx;
+ p.d->valueType.valueTypePropType = vtProp.userType();
+ return p;
+ }
+
+ QObject *objVal = QmlMetaType::toQObject(prop.read());
+ if (!objVal)
+ return QmlMetaProperty();
+ object = objVal;
+ }
+
+ const QString &propName = path.last();
+ QmlMetaProperty prop(object, propName, context);
+ if (!prop.isValid())
+ return QmlMetaProperty();
+ else
+ return prop;
+}
+
+/*!
+ Returns true if lhs and rhs refer to the same metaobject data
+*/
+bool QmlMetaPropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs)
+{
+ return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata);
+}
+
+/*!
+ Returns true if from inherits to.
+*/
+bool QmlMetaPropertyPrivate::canConvert(const QMetaObject *from, const QMetaObject *to)
+{
+ if (from && to == &QObject::staticMetaObject)
+ return true;
+
+ while (from) {
+ if (equal(from, to))
+ return true;
+ from = from->superClass();
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
new file mode 100644
index 0000000..240f5a2
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETAPROPERTY_H
+#define QMLMETAPROPERTY_H
+
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlAbstractBinding;
+class QmlExpression;
+class QStringList;
+class QVariant;
+struct QMetaObject;
+class QmlContext;
+class QmlEngine;
+
+class QmlMetaPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlMetaProperty
+{
+public:
+ enum PropertyCategory {
+ Unknown,
+ InvalidProperty,
+ Bindable,
+ List,
+ QmlList, //XXX
+ Object,
+ Normal
+ };
+ QmlMetaProperty();
+ QmlMetaProperty(QObject *);
+ QmlMetaProperty(QObject *, const QString &);
+ QmlMetaProperty(QObject *, QmlContext *);
+ QmlMetaProperty(QObject *, const QString &, QmlContext *);
+ QmlMetaProperty(const QmlMetaProperty &);
+ QmlMetaProperty &operator=(const QmlMetaProperty &);
+ ~QmlMetaProperty();
+
+ QString name() const;
+
+ QVariant read() const;
+ bool write(const QVariant &) const;
+ enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 };
+ Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
+ bool write(const QVariant &, QmlMetaProperty::WriteFlags) const;
+ bool reset() const;
+
+ bool hasChangedNotifier() const;
+ bool needsChangedNotifier() const;
+ bool connectNotifier(QObject *dest, const char *slot) const;
+ bool connectNotifier(QObject *dest, int method) const;
+
+ QMetaMethod method() const;
+
+ enum Type { Invalid = 0x00,
+ Property = 0x01,
+ SignalProperty = 0x02,
+ Default = 0x08,
+ Attached = 0x10,
+ ValueTypeProperty = 0x20 };
+
+ Type type() const;
+ bool isProperty() const;
+ bool isDefault() const;
+ bool isWritable() const;
+ bool isDesignable() const;
+ bool isResettable() const;
+ bool isValid() const;
+ QObject *object() const;
+
+ PropertyCategory propertyCategory() const;
+
+ int propertyType() const;
+ const char *propertyTypeName() const;
+
+ bool operator==(const QmlMetaProperty &) const;
+
+ QMetaProperty property() const;
+
+ QmlAbstractBinding *binding() const;
+ QmlAbstractBinding *setBinding(QmlAbstractBinding *,
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding) const;
+
+ QmlExpression *signalExpression() const;
+ QmlExpression *setSignalExpression(QmlExpression *) const;
+
+ static QmlMetaProperty createProperty(QObject *, const QString &, QmlContext *context=0);
+
+ int coreIndex() const;
+ int valueTypeCoreIndex() const;
+private:
+ friend class QmlEnginePrivate;
+ friend class QmlMetaPropertyPrivate;
+ QmlMetaPropertyPrivate *d;
+};
+typedef QList<QmlMetaProperty> QmlMetaProperties;
+ Q_DECLARE_OPERATORS_FOR_FLAGS(QmlMetaProperty::WriteFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETAPROPERTY_H
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
new file mode 100644
index 0000000..90b443e
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETAPROPERTY_P_H
+#define QMLMETAPROPERTY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlmetaproperty.h"
+
+#include "qmlpropertycache_p.h"
+#include "qmlguard_p.h"
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QmlEnginePrivate;
+class QmlMetaPropertyPrivate
+{
+public:
+ QmlMetaPropertyPrivate()
+ : q(0), context(0), object(0), isDefaultProperty(false), isNameCached(false),
+ attachedFunc(-1) {}
+
+ QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
+ : q(0), context(other.context), object(other.object),
+ isDefaultProperty(other.isDefaultProperty), isNameCached(other.isNameCached),
+ core(other.core), nameCache(other.nameCache),
+ valueType(other.valueType), attachedFunc(other.attachedFunc) {}
+
+ QmlMetaProperty *q;
+ QmlContext *context;
+ QmlGuard<QObject> object;
+
+ bool isDefaultProperty:1;
+ bool isNameCached:1;
+ QmlPropertyCache::Data core;
+ QString nameCache;
+
+ // Describes the "virtual" value-type sub-property.
+ QmlPropertyCache::ValueTypeData valueType;
+
+ // The attached property accessor
+ int attachedFunc;
+
+ void initProperty(QObject *obj, const QString &name);
+ void initDefault(QObject *obj);
+
+ QObject *attachedObject() const;
+ QMetaMethod findSignal(QObject *, const QString &);
+
+ int propertyType() const;
+ QmlMetaProperty::PropertyCategory propertyCategory() const;
+
+ QVariant readValueProperty();
+ bool writeValueProperty(const QVariant &, QmlMetaProperty::WriteFlags);
+
+ static const QMetaObject *rawMetaObjectForType(QmlEnginePrivate *, int);
+ static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags);
+ static bool write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *,
+ QmlMetaProperty::WriteFlags flags = 0);
+ static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *,
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding);
+
+ static QByteArray saveValueType(const QMetaObject *, int, int, int);
+ static QByteArray saveProperty(const QMetaObject *, int);
+ static QmlMetaProperty restore(const QByteArray &, QObject *, QmlContext * = 0);
+
+ static bool equal(const QMetaObject *, const QMetaObject *);
+ static bool canConvert(const QMetaObject *from, const QMetaObject *to);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLMETAPROPERTY_P_H
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
new file mode 100644
index 0000000..e66f600
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -0,0 +1,1301 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlmetatype.h"
+
+#include "qmlproxymetaobject_p.h"
+#include "qmlcustomparser_p.h"
+#include "qmlguard_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qbitarray.h>
+#include <QtCore/qreadwritelock.h>
+#include <qmetatype.h>
+#include <qobjectdefs.h>
+#include <qdatetime.h>
+#include <qbytearray.h>
+#include <qreadwritelock.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvector.h>
+#include <qlocale.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtScript/qscriptvalue.h>
+
+#include <ctype.h>
+
+#ifdef QT_BOOTSTRAPPED
+# ifndef QT_NO_GEOM_VARIANT
+# define QT_NO_GEOM_VARIANT
+# endif
+#else
+# include <qbitarray.h>
+# include <qurl.h>
+# include <qvariant.h>
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+# include <qsize.h>
+# include <qpoint.h>
+# include <qrect.h>
+# include <qline.h>
+# include <qvector3d.h>
+#endif
+#define NS(x) QT_PREPEND_NAMESPACE(x)
+
+QT_BEGIN_NAMESPACE
+
+struct QmlMetaTypeData
+{
+ ~QmlMetaTypeData();
+ QList<QmlType *> types;
+ typedef QHash<int, QmlType *> Ids;
+ Ids idToType;
+ typedef QHash<QByteArray, QmlType *> Names;
+ Names nameToType;
+ typedef QHash<const QMetaObject *, QmlType *> MetaObjects;
+ MetaObjects metaObjectToType;
+ typedef QHash<int, QmlMetaType::StringConverter> StringConverters;
+ StringConverters stringConverters;
+
+ QBitArray objects;
+ QBitArray interfaces;
+ QBitArray qmllists;
+ QBitArray lists;
+};
+Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData)
+Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
+
+QmlMetaTypeData::~QmlMetaTypeData()
+{
+ for (int i = 0; i < types.count(); ++i)
+ delete types.at(i);
+}
+
+class QmlTypePrivate
+{
+public:
+ QmlTypePrivate();
+
+ void init() const;
+
+ bool m_isInterface : 1;
+ const char *m_iid;
+ QByteArray m_name;
+ int m_version_maj;
+ int m_version_min;
+ int m_typeId; int m_listId; int m_qmlListId;
+ QmlPrivate::Func m_opFunc;
+ const QMetaObject *m_baseMetaObject;
+ QmlAttachedPropertiesFunc m_attachedPropertiesFunc;
+ const QMetaObject *m_attachedPropertiesType;
+ int m_parserStatusCast;
+ int m_propertyValueSourceCast;
+ int m_propertyValueInterceptorCast;
+ QmlPrivate::CreateFunc m_extFunc;
+ const QMetaObject *m_extMetaObject;
+ int m_index;
+ QmlCustomParser *m_customParser;
+ mutable volatile bool m_isSetup:1;
+ mutable QList<QmlProxyMetaObject::ProxyData> m_metaObjects;
+};
+
+QmlTypePrivate::QmlTypePrivate()
+: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0),
+ m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0),
+ m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1),
+ m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false)
+{
+}
+
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *iid, int index)
+: d(new QmlTypePrivate)
+{
+ d->m_isInterface = true;
+ d->m_iid = iid;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_index = index;
+ d->m_isSetup = true;
+ d->m_version_maj = 0;
+ d->m_version_min = 0;
+}
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *qmlName,
+ int version_maj, int version_min,
+ const QMetaObject *metaObject,
+ QmlAttachedPropertiesFunc attachedPropertiesFunc,
+ const QMetaObject *attachedType,
+ int parserStatusCast, int propertyValueSourceCast, int propertyValueInterceptorCast,
+ QmlPrivate::CreateFunc extFunc,
+ const QMetaObject *extMetaObject, int index,
+ QmlCustomParser *customParser)
+: d(new QmlTypePrivate)
+{
+ d->m_name = qmlName;
+ d->m_version_maj = version_maj;
+ d->m_version_min = version_min;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_baseMetaObject = metaObject;
+ d->m_attachedPropertiesFunc = attachedPropertiesFunc;
+ d->m_attachedPropertiesType = attachedType;
+ d->m_parserStatusCast = parserStatusCast;
+ d->m_propertyValueSourceCast = propertyValueSourceCast;
+ d->m_propertyValueInterceptorCast = propertyValueInterceptorCast;
+ d->m_extFunc = extFunc;
+ d->m_index = index;
+ d->m_customParser = customParser;
+
+ if (extMetaObject)
+ d->m_extMetaObject = extMetaObject;
+}
+
+QmlType::~QmlType()
+{
+ delete d->m_customParser;
+ delete d;
+}
+
+int QmlType::majorVersion() const
+{
+ return d->m_version_maj;
+}
+
+int QmlType::minorVersion() const
+{
+ return d->m_version_min;
+}
+
+bool QmlType::availableInVersion(int vmajor, int vminor) const
+{
+ return vmajor > d->m_version_maj || (vmajor == d->m_version_maj && vminor >= d->m_version_min);
+}
+
+void QmlTypePrivate::init() const
+{
+ if (m_isSetup) return;
+
+ QWriteLocker lock(metaTypeDataLock());
+ if (m_isSetup)
+ return;
+
+ // Setup extended meta object
+ // XXX - very inefficient
+ const QMetaObject *mo = m_baseMetaObject;
+ if (m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *m_extMetaObject;
+ mmo->d.superdata = mo;
+ QmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
+ m_metaObjects << data;
+ }
+
+ mo = mo->d.superdata;
+ while(mo) {
+ QmlType *t = metaTypeData()->metaObjectToType.value(mo);
+ if (t) {
+ if (t->d->m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *t->d->m_extMetaObject;
+ mmo->d.superdata = m_baseMetaObject;
+ if (!m_metaObjects.isEmpty())
+ m_metaObjects.last().metaObject->d.superdata = mmo;
+ QmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
+ m_metaObjects << data;
+ }
+ }
+ mo = mo->d.superdata;
+ }
+
+ for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
+ m_metaObjects[ii].propertyOffset =
+ m_metaObjects.at(ii).metaObject->propertyOffset();
+ m_metaObjects[ii].methodOffset =
+ m_metaObjects.at(ii).metaObject->methodOffset();
+ }
+
+ m_isSetup = true;
+ lock.unlock();
+}
+
+QByteArray QmlType::typeName() const
+{
+ if (d->m_baseMetaObject)
+ return d->m_baseMetaObject->className();
+ else
+ return QByteArray();
+}
+
+QByteArray QmlType::qmlTypeName() const
+{
+ return d->m_name;
+}
+
+QObject *QmlType::create() const
+{
+ d->init();
+
+ QVariant v;
+ QObject *rv = 0;
+ d->m_opFunc(QmlPrivate::Create, 0, v, v, (void **)&rv);
+
+ if (rv && !d->m_metaObjects.isEmpty())
+ (void *)new QmlProxyMetaObject(rv, &d->m_metaObjects);
+
+ return rv;
+}
+
+QmlCustomParser *QmlType::customParser() const
+{
+ return d->m_customParser;
+}
+
+bool QmlType::isInterface() const
+{
+ return d->m_isInterface;
+}
+
+int QmlType::typeId() const
+{
+ return d->m_typeId;
+}
+
+int QmlType::qListTypeId() const
+{
+ return d->m_listId;
+}
+
+int QmlType::qmlListTypeId() const
+{
+ return d->m_qmlListId;
+}
+
+void QmlType::listClear(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant arg;
+ d->m_opFunc(QmlPrivate::Clear, 0, list, arg, 0);
+}
+
+void QmlType::listAppend(const QVariant &list, const QVariant &item)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ d->m_opFunc(QmlPrivate::Append, 0, list, item, 0);
+}
+
+QVariant QmlType::listAt(const QVariant &list, int idx)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant rv;
+ void *ptr = (void *)&rv;
+ d->m_opFunc(QmlPrivate::Value, idx, list, QVariant(), &ptr);
+ return rv;
+}
+
+int QmlType::listCount(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ return d->m_opFunc(QmlPrivate::Length, 0, list, QVariant(), 0);
+}
+
+const QMetaObject *QmlType::metaObject() const
+{
+ d->init();
+
+ if (d->m_metaObjects.isEmpty())
+ return d->m_baseMetaObject;
+ else
+ return d->m_metaObjects.first().metaObject;
+
+}
+
+const QMetaObject *QmlType::baseMetaObject() const
+{
+ return d->m_baseMetaObject;
+}
+
+QmlAttachedPropertiesFunc QmlType::attachedPropertiesFunction() const
+{
+ return d->m_attachedPropertiesFunc;
+}
+
+const QMetaObject *QmlType::attachedPropertiesType() const
+{
+ return d->m_attachedPropertiesType;
+}
+
+int QmlType::parserStatusCast() const
+{
+ return d->m_parserStatusCast;
+}
+
+int QmlType::propertyValueSourceCast() const
+{
+ return d->m_propertyValueSourceCast;
+}
+
+int QmlType::propertyValueInterceptorCast() const
+{
+ return d->m_propertyValueInterceptorCast;
+}
+
+QVariant QmlType::fromObject(QObject *obj) const
+{
+ QVariant rv;
+ QVariant *v_ptr = &rv;
+ QVariant vobj = QVariant::fromValue(obj);
+ d->m_opFunc(QmlPrivate::FromObject, 0, QVariant(), vobj, (void **)&v_ptr);
+ return rv;
+}
+
+const char *QmlType::interfaceIId() const
+{
+ return d->m_iid;
+}
+
+int QmlType::index() const
+{
+ return d->m_index;
+}
+
+int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id,
+ QmlPrivate::Func listFunction,
+ const char *iid)
+{
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ listFunction, iid, index);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+ // XXX No insertMulti, so no multi-version interfaces?
+ if (!type->qmlTypeName().isEmpty())
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ if (data->interfaces.size() < id.typeId)
+ data->interfaces.resize(id.typeId + 16);
+ if (data->qmllists.size() < id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() < id.listId)
+ data->lists.resize(id.listId + 16);
+ data->interfaces.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func,
+ const char *uri, int version_maj, int version_min, const char *cname,
+ const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo,
+ int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser)
+{
+ Q_UNUSED(object);
+
+ if (cname) {
+ for (int ii = 0; cname[ii]; ++ii) {
+ if (!isalnum(cname[ii])) {
+ qWarning("QmlMetaType: Invalid QML name %s", cname);
+ return -1;
+ }
+ }
+ }
+
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ int index = data->types.count();
+
+ QByteArray name = uri;
+ if (uri)
+ name += '/';
+ name += cname;
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ func, name, version_maj, version_min, mo, attach, attachMo, pStatus,
+ valueSource, valueInterceptor, extFunc, extmo, index, parser);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+
+ if (!type->qmlTypeName().isEmpty())
+ data->nameToType.insertMulti(type->qmlTypeName(), type);
+
+ data->metaObjectToType.insert(type->baseMetaObject(), type);
+
+ if (data->objects.size() <= id.typeId)
+ data->objects.resize(id.typeId + 16);
+ if (data->qmllists.size() <= id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() <= id.listId)
+ data->lists.resize(id.listId + 16);
+ data->objects.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+QObject *QmlMetaType::toQObject(const QVariant &v, bool *ok)
+{
+ if (!isQObject(v.userType())) {
+ if (ok) *ok = false;
+ return 0;
+ }
+
+ if (ok) *ok = true;
+
+ return *(QObject **)v.constData();
+}
+
+bool QmlMetaType::isQObject(int userType)
+{
+ if (userType == QMetaType::QObjectStar)
+ return true;
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
+}
+
+/*
+ Returns the item type for a list of type \a id.
+ */
+int QmlMetaType::listType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+/*
+ Returns the item type for a qml list of type \a id.
+ */
+int QmlMetaType::qmlListType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qmlListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::clear(const QVariant &list)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType) {
+ type->listClear(list);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QmlMetaType::append(const QVariant &list, const QVariant &item)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType &&
+ item.userType() == type->typeId()) {
+ type->listAppend(list, item);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int QmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->metaObjectToType.value(mo);
+ if (type && type->attachedPropertiesFunction())
+ return type->index();
+ else
+ return -1;
+}
+
+QmlAttachedPropertiesFunc QmlMetaType::attachedPropertiesFuncById(int id)
+{
+ if (id < 0)
+ return 0;
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return data->types.at(id)->attachedPropertiesFunction();
+}
+
+QMetaProperty QmlMetaType::defaultProperty(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultProperty");
+ if (-1 == idx)
+ return QMetaProperty();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaProperty();
+
+ idx = metaObject->indexOfProperty(info.value());
+ if (-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+QMetaProperty QmlMetaType::defaultProperty(QObject *obj)
+{
+ if (!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultProperty(metaObject);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultMethod");
+ if (-1 == idx)
+ return QMetaMethod();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaMethod();
+
+ idx = metaObject->indexOfMethod(info.value());
+ if (-1 == idx)
+ return QMetaMethod();
+
+ return metaObject->method(idx);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(QObject *obj)
+{
+ if (!obj)
+ return QMetaMethod();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultMethod(metaObject);
+}
+
+QmlMetaType::TypeCategory QmlMetaType::typeCategory(int userType)
+{
+ if (userType < 0)
+ return Unknown;
+ if (userType == QMetaType::QObjectStar)
+ return Object;
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ if (userType < data->objects.size() && data->objects.testBit(userType))
+ return Object;
+ else if (userType < data->qmllists.size() && data->qmllists.testBit(userType))
+ return QmlList;
+ else if (userType < data->lists.size() && data->lists.testBit(userType))
+ return List;
+ else
+ return Unknown;
+}
+
+bool QmlMetaType::isInterface(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
+}
+
+const char *QmlMetaType::interfaceIId(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->isInterface() && type->typeId() == userType)
+ return type->interfaceIId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::isQmlList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->qmllists.size() && data->qmllists.testBit(userType);
+}
+
+bool QmlMetaType::isList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
+}
+
+bool QmlMetaType::isList(const QVariant &v)
+{
+ return (v.type() == QVariant::UserType && isList(v.userType()));
+}
+
+int QmlMetaType::listCount(const QVariant &v)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listCount(v);
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::listAt(const QVariant &v, int idx)
+{
+ if (idx < 0)
+ return QVariant();
+
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listAt(v, idx);
+ else
+ return QVariant();
+}
+
+/*!
+ A custom string convertor allows you to specify a function pointer that
+ returns a variant of \a type. For example, if you have written your own icon
+ class that you want to support as an object property assignable in QML:
+
+ \code
+ int type = qRegisterMetaType<SuperIcon>("SuperIcon");
+ QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
+ \endcode
+
+ The function pointer must be of the form:
+ \code
+ QVariant (*StringConverter)(const QString &);
+ \endcode
+ */
+void QmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
+{
+ QWriteLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ if (data->stringConverters.contains(type))
+ return;
+ data->stringConverters.insert(type, converter);
+}
+
+/*!
+ Return the custom string converter for \a type, previously installed through
+ registerCustomStringConverter()
+ */
+QmlMetaType::StringConverter QmlMetaType::customStringConverter(int type)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ return data->stringConverters.value(type);
+}
+
+/*!
+ Returns the type (if any) of URI-qualified named \a name in version specified
+ by \a version_major and \a version_minor.
+*/
+QmlType *QmlMetaType::qmlType(const QByteArray &name, int version_major, int version_minor)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QList<QmlType*> types = data->nameToType.values(name);
+ foreach (QmlType *t, types) {
+ // XXX version_major<0 just a kludge for QmlMetaPropertyPrivate::initProperty
+ if (version_major<0 || t->availableInVersion(version_major,version_minor))
+ return t;
+ }
+ return 0;
+}
+
+/*!
+ Returns the type (if any) that corresponds to the \a metaObject. Returns null if no
+ type is registered.
+*/
+QmlType *QmlMetaType::qmlType(const QMetaObject *metaObject)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->metaObjectToType.value(metaObject);
+}
+
+/*!
+ Returns the type (if any) that corresponds to the QVariant::Type \a userType.
+ Returns null if no type is registered.
+*/
+QmlType *QmlMetaType::qmlType(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(userType);
+ if (type && type->typeId() == userType)
+ return type;
+ else
+ return 0;
+}
+
+/*!
+ Returns the list of registered QML type names.
+*/
+QList<QByteArray> QmlMetaType::qmlTypeNames()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.keys();
+}
+
+/*!
+ Returns the list of registered QML types.
+*/
+QList<QmlType*> QmlMetaType::qmlTypes()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.values();
+}
+
+#include <QtGui/qfont.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qbrush.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qicon.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qpolygon.h>
+#include <QtGui/qregion.h>
+#include <QtGui/qbitmap.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qsizepolicy.h>
+#include <QtGui/qkeysequence.h>
+#include <QtGui/qpen.h>
+
+//#include <QtGui/qtextlength.h>
+#include <QtGui/qtextformat.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qtransform.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+
+Q_DECLARE_METATYPE(QScriptValue);
+
+/*!
+ Copies \a copy into \a data, assuming they both are of type \a type. If
+ \a copy is zero, a default type is copied. Returns true if the copy was
+ successful and false if not.
+
+ \note This should move into QMetaType once complete
+
+*/
+bool QmlMetaType::copy(int type, void *data, const void *copy)
+{
+ if (copy) {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = *static_cast<const long*>(copy);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = *static_cast<const int*>(copy);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = *static_cast<const short*>(copy);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = *static_cast<const char*>(copy);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = *static_cast<const ulong*>(copy);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = *static_cast<const uint*>(copy);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = *static_cast<const qlonglong*>(copy);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = *static_cast<const qulonglong*>(copy);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = *static_cast<const ushort*>(copy);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = *static_cast<const uchar*>(copy);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = *static_cast<const bool*>(copy);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = *static_cast<const float*>(copy);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = *static_cast<const double*>(copy);
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = *static_cast<const NS(QChar)*>(copy);
+ return true;
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = *static_cast<const NS(QVariantMap)*>(copy);
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = *static_cast<const NS(QVariantHash)*>(copy);
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = *static_cast<const NS(QVariantList)*>(copy);
+ return true;
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = *static_cast<const NS(QByteArray)*>(copy);
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = *static_cast<const NS(QString)*>(copy);
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = *static_cast<const NS(QStringList)*>(copy);
+ return true;
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = *static_cast<const NS(QBitArray)*>(copy);
+ return true;
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = *static_cast<const NS(QDate)*>(copy);
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = *static_cast<const NS(QTime)*>(copy);
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = *static_cast<const NS(QDateTime)*>(copy);
+ return true;
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = *static_cast<const NS(QUrl)*>(copy);
+ return true;
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = *static_cast<const NS(QLocale)*>(copy);
+ return true;
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = *static_cast<const NS(QRect)*>(copy);
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = *static_cast<const NS(QRectF)*>(copy);
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = *static_cast<const NS(QSize)*>(copy);
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = *static_cast<const NS(QSizeF)*>(copy);
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = *static_cast<const NS(QLine)*>(copy);
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = *static_cast<const NS(QLineF)*>(copy);
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = *static_cast<const NS(QPoint)*>(copy);
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = *static_cast<const NS(QPointF)*>(copy);
+ return true;
+ case QMetaType::QVector3D:
+ *static_cast<NS(QVector3D) *>(data) = *static_cast<const NS(QVector3D)*>(copy);
+ return true;
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+
+
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+ *static_cast<NS(QColorGroup) *>(data) = *static_cast<const NS(QColorGroup)*>(copy);
+ return true;
+#endif
+
+ case QMetaType::QFont:
+ *static_cast<NS(QFont) *>(data) = *static_cast<const NS(QFont)*>(copy);
+ return true;
+ case QMetaType::QPixmap:
+ *static_cast<NS(QPixmap) *>(data) = *static_cast<const NS(QPixmap)*>(copy);
+ return true;
+ case QMetaType::QBrush:
+ *static_cast<NS(QBrush) *>(data) = *static_cast<const NS(QBrush)*>(copy);
+ return true;
+ case QMetaType::QColor:
+ *static_cast<NS(QColor) *>(data) = *static_cast<const NS(QColor)*>(copy);
+ return true;
+ case QMetaType::QPalette:
+ *static_cast<NS(QPalette) *>(data) = *static_cast<const NS(QPalette)*>(copy);
+ return true;
+ case QMetaType::QIcon:
+ *static_cast<NS(QIcon) *>(data) = *static_cast<const NS(QIcon)*>(copy);
+ return true;
+ case QMetaType::QImage:
+ *static_cast<NS(QImage) *>(data) = *static_cast<const NS(QImage)*>(copy);
+ return true;
+ case QMetaType::QPolygon:
+ *static_cast<NS(QPolygon) *>(data) = *static_cast<const NS(QPolygon)*>(copy);
+ return true;
+ case QMetaType::QRegion:
+ *static_cast<NS(QRegion) *>(data) = *static_cast<const NS(QRegion)*>(copy);
+ return true;
+ case QMetaType::QBitmap:
+ *static_cast<NS(QBitmap) *>(data) = *static_cast<const NS(QBitmap)*>(copy);
+ return true;
+#ifndef QT_NO_CURSOR
+ case QMetaType::QCursor:
+ *static_cast<NS(QCursor) *>(data) = *static_cast<const NS(QCursor)*>(copy);
+ return true;
+#endif
+ case QMetaType::QSizePolicy:
+ *static_cast<NS(QSizePolicy) *>(data) = *static_cast<const NS(QSizePolicy)*>(copy);
+ return true;
+ case QMetaType::QKeySequence:
+ *static_cast<NS(QKeySequence) *>(data) = *static_cast<const NS(QKeySequence)*>(copy);
+ return true;
+ case QMetaType::QPen:
+ *static_cast<NS(QPen) *>(data) = *static_cast<const NS(QPen)*>(copy);
+ return true;
+ case QMetaType::QTextLength:
+ *static_cast<NS(QTextLength) *>(data) = *static_cast<const NS(QTextLength)*>(copy);
+ return true;
+ case QMetaType::QTextFormat:
+ *static_cast<NS(QTextFormat) *>(data) = *static_cast<const NS(QTextFormat)*>(copy);
+ return true;
+ case QMetaType::QMatrix:
+ *static_cast<NS(QMatrix) *>(data) = *static_cast<const NS(QMatrix)*>(copy);
+ return true;
+ case QMetaType::QTransform:
+ *static_cast<NS(QTransform) *>(data) = *static_cast<const NS(QTransform)*>(copy);
+ return true;
+ case QMetaType::QMatrix4x4:
+ *static_cast<NS(QMatrix4x4) *>(data) = *static_cast<const NS(QMatrix4x4)*>(copy);
+ return true;
+ case QMetaType::QVector2D:
+ *static_cast<NS(QVector2D) *>(data) = *static_cast<const NS(QVector2D)*>(copy);
+ return true;
+ case QMetaType::QVector4D:
+ *static_cast<NS(QVector4D) *>(data) = *static_cast<const NS(QVector4D)*>(copy);
+ return true;
+ case QMetaType::QQuaternion:
+ *static_cast<NS(QQuaternion) *>(data) = *static_cast<const NS(QQuaternion)*>(copy);
+ return true;
+
+ default:
+ if (type == qMetaTypeId<QVariant>()) {
+ *static_cast<NS(QVariant) *>(data) = *static_cast<const NS(QVariant)*>(copy);
+ return true;
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ *static_cast<NS(QScriptValue) *>(data) = *static_cast<const NS(QScriptValue)*>(copy);
+ return true;
+ } else if (typeCategory(type) != Unknown) {
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ }
+ break;
+ }
+ } else {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = 0;
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = long(0);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = int(0);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = short(0);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = char(0);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = ulong(0);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = uint(0);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = qlonglong(0);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = qulonglong(0);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = ushort(0);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = uchar(0);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = bool(false);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = float(0);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = double();
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = NS(QChar)();
+ return true;
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = NS(QVariantMap)();
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = NS(QVariantHash)();
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = NS(QVariantList)();
+ return true;
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = NS(QByteArray)();
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = NS(QString)();
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = NS(QStringList)();
+ return true;
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = NS(QBitArray)();
+ return true;
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = NS(QDate)();
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = NS(QTime)();
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = NS(QDateTime)();
+ return true;
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = NS(QUrl)();
+ return true;
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = NS(QLocale)();
+ return true;
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = NS(QRect)();
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = NS(QRectF)();
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = NS(QSize)();
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = NS(QSizeF)();
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = NS(QLine)();
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = NS(QLineF)();
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = NS(QPoint)();
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = NS(QPointF)();
+ return true;
+ case QMetaType::QVector3D:
+ *static_cast<NS(QVector3D) *>(data) = NS(QVector3D)();
+ return true;
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+ *static_cast<NS(QColorGroup) *>(data) = NS(QColorGroup)();
+ return true;
+#endif
+
+ case QMetaType::QFont:
+ *static_cast<NS(QFont) *>(data) = NS(QFont)();
+ return true;
+ case QMetaType::QPixmap:
+ *static_cast<NS(QPixmap) *>(data) = NS(QPixmap)();
+ return true;
+ case QMetaType::QBrush:
+ *static_cast<NS(QBrush) *>(data) = NS(QBrush)();
+ return true;
+ case QMetaType::QColor:
+ *static_cast<NS(QColor) *>(data) = NS(QColor)();
+ return true;
+ case QMetaType::QPalette:
+ *static_cast<NS(QPalette) *>(data) = NS(QPalette)();
+ return true;
+ case QMetaType::QIcon:
+ *static_cast<NS(QIcon) *>(data) = NS(QIcon)();
+ return true;
+ case QMetaType::QImage:
+ *static_cast<NS(QImage) *>(data) = NS(QImage)();
+ return true;
+ case QMetaType::QPolygon:
+ *static_cast<NS(QPolygon) *>(data) = NS(QPolygon)();
+ return true;
+ case QMetaType::QRegion:
+ *static_cast<NS(QRegion) *>(data) = NS(QRegion)();
+ return true;
+ case QMetaType::QBitmap:
+ *static_cast<NS(QBitmap) *>(data) = NS(QBitmap)();
+ return true;
+#ifndef QT_NO_CURSOR
+ case QMetaType::QCursor:
+ *static_cast<NS(QCursor) *>(data) = NS(QCursor)();
+ return true;
+#endif
+ case QMetaType::QSizePolicy:
+ *static_cast<NS(QSizePolicy) *>(data) = NS(QSizePolicy)();
+ return true;
+ case QMetaType::QKeySequence:
+ *static_cast<NS(QKeySequence) *>(data) = NS(QKeySequence)();
+ return true;
+ case QMetaType::QPen:
+ *static_cast<NS(QPen) *>(data) = NS(QPen)();
+ return true;
+ case QMetaType::QTextLength:
+ *static_cast<NS(QTextLength) *>(data) = NS(QTextLength)();
+ return true;
+ case QMetaType::QTextFormat:
+ *static_cast<NS(QTextFormat) *>(data) = NS(QTextFormat)();
+ return true;
+ case QMetaType::QMatrix:
+ *static_cast<NS(QMatrix) *>(data) = NS(QMatrix)();
+ return true;
+ case QMetaType::QTransform:
+ *static_cast<NS(QTransform) *>(data) = NS(QTransform)();
+ return true;
+ case QMetaType::QMatrix4x4:
+ *static_cast<NS(QMatrix4x4) *>(data) = NS(QMatrix4x4)();
+ return true;
+ case QMetaType::QVector2D:
+ *static_cast<NS(QVector2D) *>(data) = NS(QVector2D)();
+ return true;
+ case QMetaType::QVector4D:
+ *static_cast<NS(QVector4D) *>(data) = NS(QVector4D)();
+ return true;
+ case QMetaType::QQuaternion:
+ *static_cast<NS(QQuaternion) *>(data) = NS(QQuaternion)();
+ return true;
+ default:
+ if (type == qMetaTypeId<QVariant>()) {
+ *static_cast<NS(QVariant) *>(data) = NS(QVariant)();
+ return true;
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ *static_cast<NS(QScriptValue) *>(data) = NS(QScriptValue)();
+ return true;
+ } else if (typeCategory(type) != Unknown) {
+ *static_cast<void **>(data) = 0;
+ return true;
+ }
+ break;
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h
new file mode 100644
index 0000000..45ec11d
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.h
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETATYPE_H
+#define QMLMETATYPE_H
+
+#include "qmlprivate.h"
+#include "qmlparserstatus.h"
+#include "qmlpropertyvaluesource.h"
+#include "qmlpropertyvalueinterceptor.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qbitarray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlType;
+class QmlCustomParser;
+class Q_DECLARATIVE_EXPORT QmlMetaType
+{
+public:
+ static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *);
+ static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *);
+
+ static bool copy(int type, void *data, const void *copy = 0);
+
+ static QList<QByteArray> qmlTypeNames();
+ static QList<QmlType*> qmlTypes();
+
+ static QmlType *qmlType(const QByteArray &, int, int);
+ static QmlType *qmlType(const QMetaObject *);
+ static QmlType *qmlType(int);
+
+ static QMetaProperty defaultProperty(const QMetaObject *);
+ static QMetaProperty defaultProperty(QObject *);
+ static QMetaMethod defaultMethod(const QMetaObject *);
+ static QMetaMethod defaultMethod(QObject *);
+
+ static bool isQObject(int);
+ static QObject *toQObject(const QVariant &, bool *ok = 0);
+
+ static int listType(int);
+ static bool clear(const QVariant &);
+ static bool append(const QVariant &, const QVariant &);
+ static int attachedPropertiesFuncId(const QMetaObject *);
+ static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int);
+
+ enum TypeCategory { Unknown, Object, List, QmlList };
+ static TypeCategory typeCategory(int);
+
+ static bool isInterface(int);
+ static const char *interfaceIId(int);
+ static bool isList(int);
+ static bool isList(const QVariant &);
+ static bool isQmlList(int);
+ static int qmlListType(int);
+ static int listCount(const QVariant &);
+ static QVariant listAt(const QVariant &, int);
+
+ typedef QVariant (*StringConverter)(const QString &);
+ static void registerCustomStringConverter(int, StringConverter);
+ static StringConverter customStringConverter(int);
+};
+
+class QmlTypePrivate;
+class Q_DECLARATIVE_EXPORT QmlType
+{
+public:
+ QByteArray typeName() const;
+ QByteArray qmlTypeName() const;
+
+ int majorVersion() const;
+ int minorVersion() const;
+ bool availableInVersion(int vmajor, int vminor) const;
+
+ QObject *create() const;
+
+ QmlCustomParser *customParser() const;
+
+ bool isInterface() const;
+ int typeId() const;
+ int qListTypeId() const;
+ int qmlListTypeId() const;
+
+ void listClear(const QVariant &);
+ void listAppend(const QVariant &, const QVariant &);
+ QVariant listAt(const QVariant &, int);
+ int listCount(const QVariant &);
+
+ const QMetaObject *metaObject() const;
+ const QMetaObject *baseMetaObject() const;
+
+ QmlAttachedPropertiesFunc attachedPropertiesFunction() const;
+ const QMetaObject *attachedPropertiesType() const;
+
+ int parserStatusCast() const;
+ QVariant fromObject(QObject *) const;
+ const char *interfaceIId() const;
+ int propertyValueSourceCast() const;
+ int propertyValueInterceptorCast() const;
+
+ int index() const;
+private:
+ friend class QmlMetaType;
+ friend class QmlTypePrivate;
+ friend struct QmlMetaTypeData;
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int);
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *);
+ ~QmlType();
+
+ QmlTypePrivate *d;
+};
+
+template<typename T>
+int qmlRegisterType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + '*').constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0, 0, 0, 0,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T>
+int qmlRegisterType(const char *uri, int version_maj, int version_min, const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + '*').constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ uri, version_maj, version_min, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + '*').constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMo =
+ QmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+ attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0, 0, 0, 0,
+ &T::staticMetaObject, attached, attachedMo,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min, const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + '*').constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMo =
+ QmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+ attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ uri, version_maj, version_min, qmlName,
+ &T::staticMetaObject,
+ attached, attachedMo,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ &QmlPrivate::CreateParent<E>::create,
+ &E::staticMetaObject, 0);
+}
+
+template<typename T>
+int qmlRegisterInterface(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + '*').constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerInterface(ids,
+ QmlPrivate::list_interface_op<T>,
+ qobject_interface_iid<T *>());
+}
+
+template<typename T>
+int qmlRegisterCustomType(const char *uri, int version_maj, int version_min, const char *qmlName, const char *typeName, QmlCustomParser *parser)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + '*').constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ uri, version_maj, version_min, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ 0, 0, parser);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETATYPE_H
+
diff --git a/src/declarative/qml/qmlmoduleplugin.cpp b/src/declarative/qml/qmlmoduleplugin.cpp
new file mode 100644
index 0000000..2f2cb25
--- /dev/null
+++ b/src/declarative/qml/qmlmoduleplugin.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlmoduleplugin.h"
+#include "qstringlist.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlModulePlugin
+ \brief The QmlModulePlugin class provides an abstract base for custom QML module plugins.
+ \reentrant
+ \ingroup plugins
+
+ The QML module plugin is a simple plugin interface that makes it
+ easy to add custom QML modules that can be loaded dynamically
+ into applications.
+
+ Writing a QML module plugin is achieved by subclassing this base
+ class, reimplementing the pure virtual function keys(), and
+ exporting the class with the Q_EXPORT_PLUGIN2() macro. See \l{How
+ to Create Qt Plugins} for details.
+
+ The strings returned by keys() should be the list of URIs of modules
+ that the plugin registers.
+
+ The plugin should register QML types with qmlRegisterType() when the
+ defineModule() method is called.
+
+ \sa examples/declarative/plugins
+*/
+
+/*!
+ Constructs a QML module plugin with the given \a parent. This is
+ invoked automatically by the Q_EXPORT_PLUGIN2() macro.
+*/
+QmlModulePlugin::QmlModulePlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the QML module plugin.
+
+ You never have to call this explicitly. Qt destroys a plugin
+ automatically when it is no longer used.
+*/
+QmlModulePlugin::~QmlModulePlugin()
+{
+}
+
+/*!
+ \fn void QmlModulePlugin::defineModule(const QString& uri)
+
+ Subclasses must override this function to register types
+ of the module \a uri, which will be one of the strings returned by keys().
+
+ The plugin registers QML types with qmlRegisterType():
+
+ \code
+ qmlRegisterType<MyClass>("com.nokia.MyModule", 1, 0, "MyType", "MyClass");
+ \endcode
+*/
+
+void QmlModulePlugin::defineModuleOnce(const QString& uri)
+{
+ if (!defined.contains(uri)) {
+ defined += uri;
+ defineModule(uri);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmoduleplugin.h b/src/declarative/qml/qmlmoduleplugin.h
new file mode 100644
index 0000000..384e05e
--- /dev/null
+++ b/src/declarative/qml/qmlmoduleplugin.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMODULEPLUGIN_H
+#define QMLMODULEPLUGIN_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qset.h>
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+struct Q_DECLARATIVE_EXPORT QmlModuleFactoryInterface : public QFactoryInterface
+{
+ virtual void defineModuleOnce(const QString& uri) = 0;
+};
+
+#define QmlModuleFactoryInterface_iid "com.nokia.Qt.QmlModuleFactoryInterface"
+
+Q_DECLARE_INTERFACE(QmlModuleFactoryInterface, QmlModuleFactoryInterface_iid)
+
+
+class Q_DECLARATIVE_EXPORT QmlModulePlugin : public QObject, public QmlModuleFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlModuleFactoryInterface:QFactoryInterface)
+public:
+ explicit QmlModulePlugin(QObject *parent = 0);
+ ~QmlModulePlugin();
+
+ virtual void defineModule(const QString& uri) = 0;
+
+private:
+ void defineModuleOnce(const QString& uri);
+ QSet<QString> defined;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMODULEPLUGIN_H
diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
new file mode 100644
index 0000000..76f20d8
--- /dev/null
+++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlnetworkaccessmanagerfactory.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlNetworkAccessManagerFactory
+ \brief The QmlNetworkAccessManagerFactory class provides a factory for QNetworkAccessManager
+
+ QNetworkAccessManager is used for all network access by QML.
+ By implementing a factory it is possible to create custom
+ QNetworkAccessManager with specialized caching, proxy and
+ cookie support.
+
+ To implement a factory, subclass QmlNetworkAccessManagerFactory and implement
+ the create() method.
+
+ If the created QNetworkAccessManager becomes invalid, due to a
+ change in proxy settings, for example, call the invalidate() method.
+ This will cause all QNetworkAccessManagers to be recreated.
+
+ Note: the create() method may be called by multiple threads, so ensure the
+ implementation of this method is reentrant.
+*/
+QmlNetworkAccessManagerFactory::~QmlNetworkAccessManagerFactory()
+{
+}
+
+/*!
+ \fn QNetworkAccessManager *QmlNetworkAccessManagerFactory::create(QObject *parent)
+
+ Implement this method to create a QNetworkAccessManager with \a parent.
+ This allows proxies, caching and cookie support to be setup appropriately.
+
+ Note: this method may be called by multiple threads, so ensure the
+ implementation of this method is reentrant.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.h b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
new file mode 100644
index 0000000..ce9860f
--- /dev/null
+++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLNETWORKACCESSMANAGERFACTORY_H
+#define QMLNETWORKACCESSMANAGERFACTORY_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QNetworkAccessManager;
+class Q_DECLARATIVE_EXPORT QmlNetworkAccessManagerFactory
+{
+public:
+ virtual ~QmlNetworkAccessManagerFactory();
+ virtual QNetworkAccessManager *create(QObject *parent) = 0;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLNETWORKACCESSMANAGERFACTORY_H
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
new file mode 100644
index 0000000..1c41d46
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -0,0 +1,675 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlobjectscriptclass_p.h"
+
+#include "qmlengine_p.h"
+#include "qmlcontext_p.h"
+#include "qmldeclarativedata_p.h"
+#include "qmltypenamescriptclass_p.h"
+#include "qmllistscriptclass_p.h"
+#include "qmlbinding.h"
+#include "qmlguard_p.h"
+#include "qmlvmemetaobject_p.h"
+
+#include <QtCore/qtimer.h>
+#include <QtCore/qvarlengtharray.h>
+
+Q_DECLARE_METATYPE(QScriptValue);
+
+QT_BEGIN_NAMESPACE
+
+struct ObjectData : public QScriptDeclarativeClass::Object {
+ ObjectData(QObject *o, int t) : object(o), type(t) {}
+ QmlGuard<QObject> object;
+ int type;
+};
+
+/*
+ The QmlObjectScriptClass handles property access for QObjects
+ via QtScript. It is also used to provide a more useful API in
+ QtScript for QML.
+ */
+QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
+: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)),
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
+ methods(bindEngine),
+#endif
+ lastData(0), engine(bindEngine)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ m_destroy = scriptEngine->newFunction(destroy);
+ m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
+ m_toString = scriptEngine->newFunction(tostring);
+ m_toStringId = createPersistentIdentifier(QLatin1String("toString"));
+}
+
+QmlObjectScriptClass::~QmlObjectScriptClass()
+{
+}
+
+QScriptValue QmlObjectScriptClass::newQObject(QObject *object, int type)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!object)
+ return newObject(scriptEngine, this, new ObjectData(object, type));
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(object, true);
+
+ if (!ddata->scriptValue.isValid()) {
+ ddata->scriptValue = newObject(scriptEngine, this, new ObjectData(object, type));
+ return ddata->scriptValue;
+ } else if (ddata->scriptValue.engine() == QmlEnginePrivate::getScriptEngine(engine)) {
+ return ddata->scriptValue;
+ } else {
+ return newObject(scriptEngine, this, new ObjectData(object, type));
+ }
+}
+
+QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const
+{
+ return value.toQObject();
+}
+
+int QmlObjectScriptClass::objectType(const QScriptValue &value) const
+{
+ if (scriptClass(value) != this)
+ return QVariant::Invalid;
+
+ Object *o = object(value);
+ return ((ObjectData*)(o))->type;
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ return queryProperty(toQObject(object), name, flags, 0);
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
+ QScriptClass::QueryFlags flags, QmlContext *evalContext,
+ QueryHints hints)
+{
+ Q_UNUSED(flags);
+ lastData = 0;
+ lastTNData = 0;
+
+ if (name == m_destroyId.identifier ||
+ name == m_toStringId.identifier)
+ return QScriptClass::HandlesReadAccess;
+
+ if (!obj)
+ return 0;
+
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+ lastData = QmlPropertyCache::property(engine, obj, name, local);
+
+ if (lastData)
+ return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
+
+ if (!(hints & SkipAttachedProperties)) {
+ if (!evalContext && context()) {
+ // Global object, QScriptContext activation object, QmlContext object
+ QScriptValue scopeNode = scopeChainValue(context(), -3);
+ if (scopeNode.isValid()) {
+ Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);
+
+ evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
+ }
+ }
+
+ if (evalContext) {
+ QmlContextPrivate *cp = QmlContextPrivate::get(evalContext);
+
+ if (cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+ if (data) {
+ lastTNData = data;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ }
+ }
+
+ if (!(hints & ImplicitObject)) {
+ local.coreIndex = -1;
+ lastData = &local;
+ return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
+ }
+
+ return 0;
+}
+
+QmlObjectScriptClass::ScriptValue
+QmlObjectScriptClass::property(Object *object, const Identifier &name)
+{
+ return property(toQObject(object), name);
+}
+
+QmlObjectScriptClass::ScriptValue
+QmlObjectScriptClass::property(QObject *obj, const Identifier &name)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (name == m_destroyId.identifier)
+ return Value(scriptEngine, m_destroy);
+ else if (name == m_toStringId.identifier)
+ return Value(scriptEngine, m_toString);
+
+ if (lastData && !lastData->isValid())
+ return Value();
+
+ Q_ASSERT(obj);
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ if (lastTNData) {
+
+ if (lastTNData->type)
+ return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->type));
+ else
+ return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace));
+
+ } else if (lastData->flags & QmlPropertyCache::Data::IsFunction) {
+ if (lastData->flags & QmlPropertyCache::Data::IsVMEFunction) {
+ return Value(scriptEngine, ((QmlVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
+ } else {
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
+ // Uncomment to use QtScript method call logic
+ // QScriptValue sobj = scriptEngine->newQObject(obj);
+ // return Value(scriptEngine, sobj.property(toString(name)));
+ return Value(scriptEngine, methods.newMethod(obj, lastData));
+#else
+ QScriptValue sobj = scriptEngine->newQObject(obj);
+ return Value(scriptEngine, sobj.property(toString(name)));
+#endif
+ }
+ } else {
+ if (enginePriv->captureProperties && !(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
+ enginePriv->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
+ }
+
+ if ((uint)lastData->propType < QVariant::UserType) {
+ QmlValueType *valueType = enginePriv->valueTypes[lastData->propType];
+ if (valueType)
+ return Value(scriptEngine, enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType));
+ }
+
+ if (lastData->flags & QmlPropertyCache::Data::IsQList) {
+ return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, QmlListScriptClass::QListPtr, lastData->propType));
+ } else if (lastData->flags & QmlPropertyCache::Data::IsQmlList) {
+ return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, QmlListScriptClass::QmlListPtr, lastData->propType));
+ } else if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) {
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, newQObject(rv, lastData->propType));
+ } else if (lastData->flags & QmlPropertyCache::Data::IsQScriptValue) {
+ QScriptValue rv = scriptEngine->nullValue();
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else if (lastData->propType == QMetaType::QReal) {
+ qreal rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else if (lastData->propType == QMetaType::Int) {
+ int rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else if (lastData->propType == QMetaType::Bool) {
+ bool rv = false;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else if (lastData->propType == QMetaType::QString) {
+ QString rv;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else if (lastData->propType == QMetaType::UInt) {
+ uint rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else if (lastData->propType == QMetaType::Float) {
+ float rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else if (lastData->propType == QMetaType::Double) {
+ double rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return Value(scriptEngine, rv);
+ } else {
+ QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
+ return Value(scriptEngine, enginePriv->scriptValueFromVariant(var));
+ }
+
+ }
+}
+
+void QmlObjectScriptClass::setProperty(Object *object,
+ const Identifier &name,
+ const QScriptValue &value)
+{
+ return setProperty(toQObject(object), name, value);
+}
+
+void QmlObjectScriptClass::setProperty(QObject *obj,
+ const Identifier &name,
+ const QScriptValue &value,
+ QmlContext *evalContext)
+{
+ Q_UNUSED(name);
+
+ Q_ASSERT(obj);
+ Q_ASSERT(lastData);
+
+ if (!lastData->isValid()) {
+ QString error = QLatin1String("Cannot assign to non-existant property \"") +
+ toString(name) + QLatin1Char('\"');
+ if (context())
+ context()->throwError(error);
+ return;
+ }
+
+ if (!(lastData->flags & QmlPropertyCache::Data::IsWritable)) {
+ QString error = QLatin1String("Cannot assign to read-only property \"") +
+ toString(name) + QLatin1Char('\"');
+ if (context())
+ context()->throwError(error);
+ return;
+ }
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ if (!evalContext && context()) {
+ // Global object, QScriptContext activation object, QmlContext object
+ QScriptValue scopeNode = scopeChainValue(context(), -3);
+ if (scopeNode.isValid()) {
+ Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);
+
+ evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
+ }
+ }
+
+ QmlAbstractBinding *delBinding = QmlMetaPropertyPrivate::setBinding(obj, *lastData, 0);
+ if (delBinding)
+ delBinding->destroy();
+
+ if (value.isUndefined() && lastData->flags & QmlPropertyCache::Data::IsResettable) {
+ void *a[] = { 0 };
+ QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
+ } else {
+ // ### Can well known types be optimized?
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+ QmlMetaPropertyPrivate::write(obj, *lastData, v, evalContext);
+ }
+}
+
+bool QmlObjectScriptClass::isQObject() const
+{
+ return true;
+}
+
+QObject *QmlObjectScriptClass::toQObject(Object *object, bool *ok)
+{
+ if (ok) *ok = true;
+
+ ObjectData *data = (ObjectData*)object;
+ return data->object.data();
+}
+
+QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *)
+{
+ QObject* obj = context->thisObject().toQObject();
+
+ QString ret;
+ if(obj){
+ QString objectName = obj->objectName();
+
+ ret += QString::fromUtf8(obj->metaObject()->className());
+ ret += QLatin1String("(0x");
+ ret += QString::number((intptr_t)obj,16);
+
+ if (!objectName.isEmpty()) {
+ ret += QLatin1String(", \"");
+ ret += objectName;
+ ret += QLatin1Char('\"');
+ }
+
+ ret += QLatin1Char(')');
+ }else{
+ ret += QLatin1String("null");
+ }
+ return QScriptValue(ret);
+}
+
+QScriptValue QmlObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
+{
+ QObject* obj = context->thisObject().toQObject();
+ if(obj){
+ int delay = 0;
+ if(context->argumentCount() > 0)
+ delay = context->argument(0).toInt32();
+ if (delay > 0)
+ QTimer::singleShot(delay, obj, SLOT(deleteLater()));
+ else
+ obj->deleteLater();
+ }
+ return engine->nullValue();
+}
+
+QStringList QmlObjectScriptClass::propertyNames(Object *object)
+{
+ QObject *obj = toQObject(object);
+ if (!obj)
+ return QStringList();
+
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata)
+ cache = ddata->propertyCache;
+ if (!cache) {
+ cache = enginePrivate->cache(obj);
+ if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; }
+ }
+
+ if (!cache)
+ return QStringList();
+
+ return cache->propertyNames();
+}
+
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
+
+struct MethodData : public QScriptDeclarativeClass::Object {
+ MethodData(QObject *o, const QmlPropertyCache::Data &d) : object(o), data(d) {}
+
+ QmlGuard<QObject> object;
+ QmlPropertyCache::Data data;
+};
+
+QmlObjectMethodScriptClass::QmlObjectMethodScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)),
+ engine(bindEngine)
+{
+ setSupportsCall(true);
+}
+
+QmlObjectMethodScriptClass::~QmlObjectMethodScriptClass()
+{
+}
+
+QScriptValue QmlObjectMethodScriptClass::newMethod(QObject *object, const QmlPropertyCache::Data *method)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new MethodData(object, *method));
+}
+
+namespace {
+struct MetaCallArgument {
+ inline MetaCallArgument();
+ inline ~MetaCallArgument();
+ inline void *dataPtr();
+
+ inline void initAsType(int type, QmlEngine *);
+ void fromScriptValue(int type, QmlEngine *, const QScriptValue &);
+ inline QScriptDeclarativeClass::Value toValue(QmlEngine *);
+
+private:
+ MetaCallArgument(const MetaCallArgument &);
+
+ inline void cleanup();
+
+ char *data[16];
+ int type;
+};
+}
+
+MetaCallArgument::MetaCallArgument()
+: type(QVariant::Invalid)
+{
+}
+
+MetaCallArgument::~MetaCallArgument()
+{
+ cleanup();
+}
+
+void MetaCallArgument::cleanup()
+{
+ if (type == QMetaType::QString) {
+ ((QString *)data)->~QString();
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ ((QVariant *)data)->~QVariant();
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ ((QScriptValue *)data)->~QScriptValue();
+ }
+}
+
+void *MetaCallArgument::dataPtr()
+{
+ if (type == -1)
+ return ((QVariant *)data)->data();
+ else
+ return (void *)data;
+}
+
+void MetaCallArgument::initAsType(int callType, QmlEngine *e)
+{
+ if (type != 0) { cleanup(); type = 0; }
+ if (callType == 0) return;
+
+ QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(e);
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (data) QScriptValue(engine->undefinedValue());
+ type = callType;
+ } else if (callType == QMetaType::Int ||
+ callType == QMetaType::UInt ||
+ callType == QMetaType::Bool ||
+ callType == QMetaType::Double ||
+ callType == QMetaType::Float) {
+ type = callType;
+ } else if (callType == QMetaType::QObjectStar) {
+ *((QObject **)data) = 0;
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ new (data) QString();
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ type = qMetaTypeId<QVariant>();
+ new (data) QVariant();
+ } else {
+ type = -1;
+ new (data) QVariant(callType, (void *)0);
+ }
+}
+
+void MetaCallArgument::fromScriptValue(int callType, QmlEngine *engine, const QScriptValue &value)
+{
+ if (type != 0) { cleanup(); type = 0; }
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (data) QScriptValue(value);
+ type = qMetaTypeId<QScriptValue>();
+ } else if (callType == QMetaType::Int) {
+ *((int *)data) = int(value.toInt32());
+ type = callType;
+ } else if (callType == QMetaType::UInt) {
+ *((uint *)data) = uint(value.toUInt32());
+ type = callType;
+ } else if (callType == QMetaType::Bool) {
+ *((bool *)data) = value.toBool();
+ type = callType;
+ } else if (callType == QMetaType::Double) {
+ *((double *)data) = double(value.toNumber());
+ type = callType;
+ } else if (callType == QMetaType::Float) {
+ *((float *)data) = float(value.toNumber());
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ if (value.isNull() || value.isUndefined())
+ new (data) QString();
+ else
+ new (data) QString(value.toString());
+ type = callType;
+ } else if (callType == QMetaType::QObjectStar) {
+ *((QObject **)data) = value.toQObject();
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ new (data) QVariant(QmlScriptClass::toVariant(engine, value));
+ type = callType;
+ } else {
+ new (data) QVariant();
+ type = -1;
+
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+ if (v.userType() == callType) {
+ *((QVariant *)data) = v;
+ } else if (v.canConvert((QVariant::Type)callType)) {
+ *((QVariant *)data) = v;
+ ((QVariant *)data)->convert((QVariant::Type)callType);
+ } else {
+ *((QVariant *)data) = QVariant(callType, (void *)0);
+ }
+ }
+}
+
+QScriptDeclarativeClass::Value MetaCallArgument::toValue(QmlEngine *e)
+{
+ QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(e);
+
+ if (type == qMetaTypeId<QScriptValue>()) {
+ return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)data));
+ } else if (type == QMetaType::Int) {
+ return QScriptDeclarativeClass::Value(engine, *((int *)data));
+ } else if (type == QMetaType::UInt) {
+ return QScriptDeclarativeClass::Value(engine, *((uint *)data));
+ } else if (type == QMetaType::Bool) {
+ return QScriptDeclarativeClass::Value(engine, *((bool *)data));
+ } else if (type == QMetaType::Double) {
+ return QScriptDeclarativeClass::Value(engine, *((double *)data));
+ } else if (type == QMetaType::Float) {
+ return QScriptDeclarativeClass::Value(engine, *((float *)data));
+ } else if (type == QMetaType::QString) {
+ return QScriptDeclarativeClass::Value(engine, *((QString *)data));
+ } else if (type == QMetaType::QObjectStar) {
+ return QScriptDeclarativeClass::Value(engine, QmlEnginePrivate::get(e)->objectClass->newQObject(*((QObject **)data)));
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ return QScriptDeclarativeClass::Value(engine, QmlEnginePrivate::get(e)->scriptValueFromVariant(*((QVariant *)data)));
+ } else {
+ return QScriptDeclarativeClass::Value();
+ }
+}
+
+QmlObjectMethodScriptClass::Value QmlObjectMethodScriptClass::call(Object *o, QScriptContext *ctxt)
+{
+ MethodData *method = static_cast<MethodData *>(o);
+
+ if (method->data.flags & QmlPropertyCache::Data::HasArguments) {
+
+ QMetaMethod m = method->object->metaObject()->method(method->data.coreIndex);
+ QList<QByteArray> argTypeNames = m.parameterTypes();
+ QVarLengthArray<int, 9> argTypes(argTypeNames.count());
+
+ // ### Cache
+ for (int ii = 0; ii < argTypeNames.count(); ++ii) {
+ argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
+ if (argTypes[ii] == QVariant::Invalid)
+ return Value(ctxt, ctxt->throwError(QString(QLatin1String("Unknown method parameter type: %1")).arg(QLatin1String(argTypeNames.at(ii)))));
+ }
+
+ if (argTypes.count() > ctxt->argumentCount())
+ return Value(ctxt, ctxt->throwError("Insufficient arguments"));
+
+ QVarLengthArray<MetaCallArgument, 9> args(argTypes.count() + 1);
+ args[0].initAsType(method->data.propType, engine);
+
+ for (int ii = 0; ii < argTypes.count(); ++ii)
+ args[ii + 1].fromScriptValue(argTypes[ii], engine, ctxt->argument(ii));
+
+ QVarLengthArray<void *, 9> argData(args.count());
+ for (int ii = 0; ii < args.count(); ++ii)
+ argData[ii] = args[ii].dataPtr();
+
+ QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, argData.data());
+
+ return args[0].toValue(engine);
+
+ } else if (method->data.propType != 0) {
+
+ MetaCallArgument arg;
+ arg.initAsType(method->data.propType, engine);
+
+ void *args[] = { arg.dataPtr() };
+
+ QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args);
+
+ return arg.toValue(engine);
+
+ } else {
+
+ void *args[] = { 0 };
+ QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args);
+ return Value();
+
+ }
+ return Value();
+}
+
+#endif
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
new file mode 100644
index 0000000..470c555
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOBJECTSCRIPTCLASS_P_H
+#define QMLOBJECTSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlpropertycache_p.h"
+#include "qmltypenamecache_p.h"
+
+#include <private/qmlscriptclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QScriptContext;
+class QScriptEngine;
+class QmlContext;
+
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
+class Q_AUTOTEST_EXPORT QmlObjectMethodScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlObjectMethodScriptClass(QmlEngine *);
+ ~QmlObjectMethodScriptClass();
+
+ QScriptValue newMethod(QObject *, const QmlPropertyCache::Data *);
+protected:
+ virtual Value call(Object *, QScriptContext *);
+
+private:
+ QmlEngine *engine;
+};
+#endif
+
+class Q_AUTOTEST_EXPORT QmlObjectScriptClass : public QmlScriptClass
+{
+public:
+ QmlObjectScriptClass(QmlEngine *);
+ ~QmlObjectScriptClass();
+
+ QScriptValue newQObject(QObject *, int type = QMetaType::QObjectStar);
+ QObject *toQObject(const QScriptValue &) const;
+ int objectType(const QScriptValue &) const;
+
+ enum QueryHint {
+ ImplicitObject = 0x01,
+ SkipAttachedProperties = 0x02
+ };
+ Q_DECLARE_FLAGS(QueryHints, QueryHint)
+
+ QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &,
+ QScriptClass::QueryFlags flags,
+ QmlContext *evalContext,
+ QueryHints hints = 0);
+
+ ScriptValue property(QObject *, const Identifier &);
+
+ void setProperty(QObject *, const Identifier &name, const QScriptValue &,
+ QmlContext *evalContext = 0);
+ virtual QStringList propertyNames(Object *);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual ScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ virtual bool isQObject() const;
+ virtual QObject *toQObject(Object *, bool *ok = 0);
+
+private:
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
+ QmlObjectMethodScriptClass methods;
+#endif
+
+ QmlTypeNameCache::Data *lastTNData;
+ QmlPropertyCache::Data *lastData;
+ QmlPropertyCache::Data local;
+
+ PersistentIdentifier m_destroyId;
+ PersistentIdentifier m_toStringId;
+ QScriptValue m_destroy;
+ QScriptValue m_toString;
+
+ static QScriptValue tostring(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine);
+
+ QmlEngine *engine;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlObjectScriptClass::QueryHints);
+
+QT_END_NAMESPACE
+
+#endif // QMLOBJECTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
new file mode 100644
index 0000000..02a9e70
--- /dev/null
+++ b/src/declarative/qml/qmlparser.cpp
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlparser_p.h"
+
+#include "qmlpropertyvaluesource.h"
+#include "qmlvme_p.h"
+#include "qml.h"
+#include "qmlcomponent_p.h"
+#include "qmlcomponent.h"
+#include "qmetaobjectbuilder_p.h"
+#include "qmlvmemetaobject_p.h"
+#include "qmlcompiler_p.h"
+#include "parser/qmljsast_p.h"
+#include "parser/qmljsengine_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QStack>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+using namespace QmlParser;
+
+QmlParser::Object::Object()
+: type(-1), majorVersion(-1), minorVersion(-1), idIndex(-1), metatype(0), defaultProperty(0), parserStatusCast(-1)
+{
+}
+
+QmlParser::Object::~Object()
+{
+ if (defaultProperty) defaultProperty->release();
+ foreach(Property *prop, properties)
+ prop->release();
+ foreach(Property *prop, valueProperties)
+ prop->release();
+ foreach(Property *prop, signalProperties)
+ prop->release();
+ foreach(Property *prop, attachedProperties)
+ prop->release();
+ foreach(Property *prop, groupedProperties)
+ prop->release();
+ foreach(Property *prop, valueTypeProperties)
+ prop->release();
+ typedef QPair<Property *, int> PropPair;
+ foreach(const PropPair &prop, scriptStringProperties)
+ prop.first->release();
+ foreach(const DynamicProperty &prop, dynamicProperties)
+ if (prop.defaultValue) prop.defaultValue->release();
+ foreach(Object *obj, scriptBlockObjects)
+ obj->release();
+}
+
+void Object::setBindingBit(int b)
+{
+ while (bindingBitmask.size() < 4 * (1 + b / 32))
+ bindingBitmask.append(char(0));
+
+ quint32 *bits = (quint32 *)bindingBitmask.data();
+ bits[b / 32] |= (1 << (b % 32));
+}
+
+const QMetaObject *Object::metaObject() const
+{
+ if (!metadata.isEmpty() && metatype)
+ return &extObject;
+ else
+ return metatype;
+}
+
+QmlParser::Property *Object::getDefaultProperty()
+{
+ if (!defaultProperty) {
+ defaultProperty = new Property;
+ defaultProperty->parent = this;
+ }
+ return defaultProperty;
+}
+
+void QmlParser::Object::addValueProperty(Property *p)
+{
+ p->addref();
+ valueProperties << p;
+}
+
+void QmlParser::Object::addSignalProperty(Property *p)
+{
+ p->addref();
+ signalProperties << p;
+}
+
+void QmlParser::Object::addAttachedProperty(Property *p)
+{
+ p->addref();
+ attachedProperties << p;
+}
+
+void QmlParser::Object::addGroupedProperty(Property *p)
+{
+ p->addref();
+ groupedProperties << p;
+}
+
+void QmlParser::Object::addValueTypeProperty(Property *p)
+{
+ p->addref();
+ valueTypeProperties << p;
+}
+
+void QmlParser::Object::addScriptStringProperty(Property *p, int stack)
+{
+ p->addref();
+ scriptStringProperties << qMakePair(p, stack);
+}
+
+
+Property *QmlParser::Object::getProperty(const QByteArray &name, bool create)
+{
+ if (!properties.contains(name)) {
+ if (create) {
+ Property *property = new Property(name);
+ property->parent = this;
+ properties.insert(name, property);
+ } else {
+ return 0;
+ }
+ }
+ return properties[name];
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty()
+: isDefaultProperty(false), type(Variant), defaultValue(0)
+{
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o)
+: isDefaultProperty(o.isDefaultProperty),
+ type(o.type),
+ customType(o.customType),
+ name(o.name),
+ defaultValue(o.defaultValue),
+ location(o.location)
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal()
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
+: name(o.name), parameterTypes(o.parameterTypes),
+ parameterNames(o.parameterNames)
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot()
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o)
+: name(o.name), body(o.body), parameterNames(o.parameterNames)
+{
+}
+
+QmlParser::Property::Property()
+: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false)
+{
+}
+
+QmlParser::Property::Property(const QByteArray &n)
+: parent(0), type(0), index(-1), value(0), name(n), isDefault(false),
+ isDeferred(false)
+{
+}
+
+QmlParser::Property::~Property()
+{
+ foreach(Value *value, values)
+ value->release();
+ if (value) value->release();
+}
+
+Object *QmlParser::Property::getValue()
+{
+ if (!value) value = new Object;
+ return value;
+}
+
+void QmlParser::Property::addValue(Value *v)
+{
+ values << v;
+}
+
+bool QmlParser::Property::isEmpty() const
+{
+ return !value && values.isEmpty();
+}
+
+QmlParser::Value::Value()
+: type(Unknown), object(0)
+{
+}
+
+QmlParser::Value::~Value()
+{
+ if (object) object->release();
+}
+
+QmlParser::Variant::Variant()
+: t(Invalid) {}
+
+QmlParser::Variant::Variant(const Variant &o)
+: t(o.t), d(o.d), s(o.s)
+{
+}
+
+QmlParser::Variant::Variant(bool v)
+: t(Boolean), b(v)
+{
+}
+
+QmlParser::Variant::Variant(double v, const QString &asWritten)
+: t(Number), d(v), s(asWritten)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v)
+: t(String), s(v)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v, QmlJS::AST::Node *n)
+: t(Script), n(n), s(v)
+{
+}
+
+QmlParser::Variant &QmlParser::Variant::operator=(const Variant &o)
+{
+ t = o.t;
+ d = o.d;
+ s = o.s;
+ return *this;
+}
+
+QmlParser::Variant::Type QmlParser::Variant::type() const
+{
+ return t;
+}
+
+bool QmlParser::Variant::asBoolean() const
+{
+ return b;
+}
+
+QString QmlParser::Variant::asString() const
+{
+ return s;
+}
+
+double QmlParser::Variant::asNumber() const
+{
+ return d;
+}
+
+QString QmlParser::Variant::asScript() const
+{
+ switch(type()) {
+ default:
+ case Invalid:
+ return QString();
+ case Boolean:
+ return b?QLatin1String("true"):QLatin1String("false");
+ case Number:
+ if (s.isEmpty())
+ return QString::number(d);
+ else
+ return s;
+ case String:
+ case Script:
+ return s;
+ }
+}
+
+QmlJS::AST::Node *QmlParser::Variant::asAST() const
+{
+ if (type() == Script)
+ return n;
+ else
+ return 0;
+}
+
+bool QmlParser::Variant::isStringList() const
+{
+ if (isString())
+ return true;
+
+ if (type() != Script || !n)
+ return false;
+
+ AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n);
+ if (!array)
+ return false;
+
+ AST::ElementList *elements = array->elements;
+
+ while (elements) {
+
+ if (!AST::cast<AST::StringLiteral *>(elements->expression))
+ return false;
+
+ elements = elements->next;
+ }
+
+ return true;
+}
+
+QStringList QmlParser::Variant::asStringList() const
+{
+ QStringList rv;
+ if (isString()) {
+ rv << asString();
+ return rv;
+ }
+
+ AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n);
+ if (!array)
+ return rv;
+
+ AST::ElementList *elements = array->elements;
+ while (elements) {
+
+ AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(elements->expression);
+ if (!string)
+ return QStringList();
+ rv.append(string->value->asString());
+
+ elements = elements->next;
+ }
+
+ return rv;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
new file mode 100644
index 0000000..aa7a762
--- /dev/null
+++ b/src/declarative/qml/qmlparser_p.h
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPARSER_P_H
+#define QMLPARSER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qml.h"
+#include "qmlrefcount_p.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/qstring.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+namespace QmlJS { namespace AST { class Node; } }
+
+/*
+ XXX
+
+ These types are created (and owned) by the QmlXmlParser and consumed by the
+ QmlCompiler. During the compilation phase the compiler will update some of
+ the fields for both its own use and for the use of the upcoming QmlDom API.
+
+ The types are part of the generic sounding "QmlParser" namespace for legacy
+ reasons (there used to be more in this namespace) and will be cleaned up and
+ migrated into a more appropriate location shortly.
+*/
+namespace QmlParser
+{
+ struct Location
+ {
+ Location() : line(-1), column(-1) {}
+ int line;
+ int column;
+ };
+
+ struct LocationRange
+ {
+ LocationRange() : offset(0), length(0) {}
+ quint32 offset;
+ quint32 length;
+ };
+
+ struct LocationSpan
+ {
+ Location start;
+ Location end;
+ LocationRange range;
+ };
+
+ class Property;
+ class Object : public QmlRefCount
+ {
+ public:
+ Object();
+ virtual ~Object();
+
+ // Type of the object. The integer is an index into the
+ // QmlCompiledData::types array, or -1 if the object is a property
+ // group.
+ int type;
+ // The url of this object if it is an external type. Used by the DOM
+ QUrl url;
+
+ // version information if type is defined in library or C++
+ int majorVersion;
+ int minorVersion;
+
+ // The fully-qualified name of this type
+ QByteArray typeName;
+ // The class name
+ QByteArray className;
+ // The id assigned to the object (if any). Set by the QmlCompiler
+ QString id;
+ // The id index assigned to the object (if any). Set by the QmlCompiler
+ int idIndex;
+ // Custom parsed data
+ QByteArray custom;
+ // Bit mask of the properties assigned bindings
+ QByteArray bindingBitmask;
+ void setBindingBit(int);
+ // Returns the metaobject for this type, or 0 if not available.
+ // Internally selectd between the metatype and extObject variables
+ const QMetaObject *metaObject() const;
+
+ // The compile time metaobject for this type
+ const QMetaObject *metatype;
+ // The synthesized metaobject, if QML added signals or properties to
+ // this type. Otherwise null
+ QAbstractDynamicMetaObject extObject;
+ QByteArray metadata; // Generated by compiler
+ QByteArray synthdata; // Generated by compiler
+
+ Property *getDefaultProperty();
+ Property *getProperty(const QByteArray &name, bool create=true);
+
+ Property *defaultProperty;
+ QHash<QByteArray, Property *> properties;
+
+ QList<Object *> scriptBlockObjects;
+
+ // Output of the compilation phase (these properties continue to exist
+ // in either the defaultProperty or properties members too)
+ void addValueProperty(Property *);
+ void addSignalProperty(Property *);
+ void addAttachedProperty(Property *);
+ void addGroupedProperty(Property *);
+ void addValueTypeProperty(Property *);
+ void addScriptStringProperty(Property *, int = 0);
+ QList<Property *> valueProperties;
+ QList<Property *> signalProperties;
+ QList<Property *> attachedProperties;
+ QList<Property *> groupedProperties;
+ QList<Property *> valueTypeProperties;
+ QList<QPair<Property *, int> > scriptStringProperties;
+
+ // Script blocks that were nested under this object
+ struct ScriptBlock {
+ QStringList codes;
+ QStringList files;
+ QList<int> lineNumbers;
+ };
+ QList<ScriptBlock> scripts;
+
+ // The bytes to cast instances by to get to the QmlParserStatus
+ // interface. -1 indicates the type doesn't support this interface.
+ // Set by the QmlCompiler.
+ int parserStatusCast;
+
+ LocationSpan location;
+
+ struct DynamicProperty {
+ DynamicProperty();
+ DynamicProperty(const DynamicProperty &);
+
+ enum Type { Variant, Int, Bool, Real, String, Url, Color, Date, Alias, Custom, CustomList };
+
+ bool isDefaultProperty;
+ Type type;
+ QByteArray customType;
+ QByteArray name;
+ QmlParser::Property *defaultValue;
+ LocationSpan location;
+ };
+ struct DynamicSignal {
+ DynamicSignal();
+ DynamicSignal(const DynamicSignal &);
+
+ QByteArray name;
+ QList<QByteArray> parameterTypes;
+ QList<QByteArray> parameterNames;
+ };
+ struct DynamicSlot {
+ DynamicSlot();
+ DynamicSlot(const DynamicSlot &);
+
+ QByteArray name;
+ QString body;
+ QList<QByteArray> parameterNames;
+ };
+
+ // The list of dynamic properties
+ QList<DynamicProperty> dynamicProperties;
+ // The list of dynamic signals
+ QList<DynamicSignal> dynamicSignals;
+ // The list of dynamic slots
+ QList<DynamicSlot> dynamicSlots;
+ };
+
+ class Variant
+ {
+ public:
+ enum Type {
+ Invalid,
+ Boolean,
+ Number,
+ String,
+ Script
+ };
+
+ Variant();
+ Variant(const Variant &);
+ Variant(bool);
+ Variant(double, const QString &asWritten=QString());
+ Variant(const QString &);
+ Variant(const QString &, QmlJS::AST::Node *);
+ Variant &operator=(const Variant &);
+
+ Type type() const;
+
+ bool isBoolean() const { return type() == Boolean; }
+ bool isNumber() const { return type() == Number; }
+ bool isString() const { return type() == String; }
+ bool isScript() const { return type() == Script; }
+ bool isStringList() const;
+
+ bool asBoolean() const;
+ QString asString() const;
+ double asNumber() const;
+ QString asScript() const;
+ QmlJS::AST::Node *asAST() const;
+ QStringList asStringList() const;
+
+ private:
+ Type t;
+ union {
+ bool b;
+ double d;
+ QmlJS::AST::Node *n;
+ };
+ QString s;
+ };
+
+ class Value : public QmlRefCount
+ {
+ public:
+ Value();
+ virtual ~Value();
+
+ enum Type {
+ // The type of this value assignment is not yet known
+ Unknown,
+ // This is used as a literal property assignment
+ Literal,
+ // This is used as a property binding assignment
+ PropertyBinding,
+ // This is used as a QmlPropertyValueSource assignment
+ ValueSource,
+ // This is used as a QmlPropertyValueInterceptor assignment
+ ValueInterceptor,
+ // This is used as a property QObject assignment
+ CreatedObject,
+ // This is used as a signal object assignment
+ SignalObject,
+ // This is used as a signal expression assignment
+ SignalExpression,
+ // This is used as an id assignment only
+ Id
+ };
+ Type type;
+
+ // ### Temporary
+ QString primitive() const { return value.asScript(); }
+
+ // Primitive value
+ Variant value;
+ // Object value
+ Object *object;
+
+ LocationSpan location;
+ };
+
+ class Property : public QmlRefCount
+ {
+ public:
+ Property();
+ Property(const QByteArray &n);
+ virtual ~Property();
+
+ // The Object to which this property is attached
+ Object *parent;
+
+ Object *getValue();
+ void addValue(Value *v);
+
+ // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
+ // unknown.
+ int type;
+ // The metaobject index of this property, or -1 if unknown.
+ int index;
+
+ // Returns true if this is an empty property - both value and values
+ // are unset.
+ bool isEmpty() const;
+ // The list of values assigned to this property. Content in values
+ // and value are mutually exclusive
+ QList<Value *> values;
+ // The accessed property. This is used to represent dot properties.
+ // Content in value and values are mutually exclusive.
+ Object *value;
+ // The property name
+ QByteArray name;
+ // True if this property was accessed as the default property.
+ bool isDefault;
+ // True if the setting of this property will be deferred. Set by the
+ // QmlCompiler
+ bool isDeferred;
+
+ LocationSpan location;
+ LocationRange listValueRange;
+ QList<int> listCommaPositions;
+ };
+}
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QmlParser::Variant)
+
+QT_END_HEADER
+
+#endif // QMLPARSER_P_H
diff --git a/src/declarative/qml/qmlparserstatus.cpp b/src/declarative/qml/qmlparserstatus.cpp
new file mode 100644
index 0000000..69ccfda
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlparserstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlParserStatus
+ \brief The QmlParserStatus class provides updates on the parser state.
+*/
+
+/*! \internal */
+QmlParserStatus::QmlParserStatus()
+: d(0)
+{
+}
+
+/*! \internal */
+QmlParserStatus::~QmlParserStatus()
+{
+ if(d)
+ (*d) = 0;
+}
+
+/*!
+ Invoked after class creation, but before any properties have been set.
+*/
+void QmlParserStatus::classBegin()
+{
+}
+
+/*!
+ Invoked after the root component that caused this instantiation has
+ completed construction. At this point all static values and binding values
+ have been assigned to the class.
+*/
+void QmlParserStatus::componentComplete()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h
new file mode 100644
index 0000000..e12c7b5
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPARSERSTATUS_H
+#define QMLPARSERSTATUS_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlParserStatus
+{
+public:
+ QmlParserStatus();
+ virtual ~QmlParserStatus();
+
+ virtual void classBegin();
+ virtual void componentComplete();
+
+private:
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlComponentPrivate;
+ friend class QmlEnginePrivate;
+ QmlParserStatus **d;
+};
+Q_DECLARE_INTERFACE(QmlParserStatus, "com.trolltech.qml.QmlParserStatus")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPARSERSTATUS_H
diff --git a/src/declarative/qml/qmlprivate.cpp b/src/declarative/qml/qmlprivate.cpp
new file mode 100644
index 0000000..01353cc
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlprivate.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlPrivate::InstanceType::InstanceType(int) {}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlprivate.h b/src/declarative/qml/qmlprivate.h
new file mode 100644
index 0000000..dd98110
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.h
@@ -0,0 +1,386 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPRIVATE_H
+#define QMLPRIVATE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef Q_OS_WIN
+#include <stdint.h>
+#endif
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+typedef QObject *(*QmlAttachedPropertiesFunc)(QObject *);
+
+//template<typename T>
+//struct qml_hasAttached { static bool const value = false; };
+
+template <typename TYPE>
+class QmlTypeInfo
+{
+public:
+ enum {
+ hasAttachedProperties = 0
+ };
+};
+
+
+namespace QmlPrivate
+{
+ class ListInterface
+ {
+ public:
+ virtual ~ListInterface() {}
+ virtual int type() const = 0;
+ virtual void append(void *) = 0;
+ virtual void insert(int, void *) = 0;
+ virtual void removeAt(int) = 0;
+ virtual void at(int, void *) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ };
+
+ enum ListOp { Append, Set, Insert, Prepend, Length, FromObject,
+ Object, Create, Value, Clear };
+
+ template<typename T>
+ int list_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_nocreate_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_interface_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<class From, class To, int N>
+ struct StaticCastSelectorClass
+ {
+ static inline int cast() { return -1; }
+ };
+
+ template<class From, class To>
+ struct StaticCastSelectorClass<From, To, sizeof(int)>
+ {
+ static inline int cast() { return (int)((intptr_t)static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+ };
+
+ template<class From, class To>
+ struct StaticCastSelector
+ {
+ typedef int yes_type;
+ typedef char no_type;
+
+ static yes_type check(To *);
+ static no_type check(...);
+
+ static inline int cast()
+ {
+ return StaticCastSelectorClass<From, To, sizeof(check((From *)0))>::cast();
+ }
+ };
+
+ template <typename T>
+ struct has_attachedPropertiesMember
+ {
+ static bool const value = QmlTypeInfo<T>::hasAttachedProperties;
+ };
+
+ template <typename T, bool hasMember>
+ class has_attachedPropertiesMethod
+ {
+ typedef int yes_type;
+ typedef char no_type;
+
+ template<typename ReturnType>
+ static yes_type check(ReturnType *(*)(QObject *));
+ static no_type check(...);
+
+ public:
+ static bool const value = sizeof(check(&T::qmlAttachedProperties)) == sizeof(yes_type);
+ };
+
+ template <typename T>
+ class has_attachedPropertiesMethod<T, false>
+ {
+ public:
+ static bool const value = false;
+ };
+
+ template<typename T, int N>
+ class AttachedPropertySelector
+ {
+ public:
+ static inline QmlAttachedPropertiesFunc func() { return 0; }
+ static inline const QMetaObject *metaObject() { return 0; }
+ };
+ template<typename T>
+ class AttachedPropertySelector<T, 1>
+ {
+ static inline QObject *attachedProperties(QObject *obj) {
+ return T::qmlAttachedProperties(obj);
+ }
+ template<typename ReturnType>
+ static inline const QMetaObject *attachedPropertiesMetaObject(ReturnType *(*)(QObject *)) {
+ return &ReturnType::staticMetaObject;
+ }
+ public:
+ static inline QmlAttachedPropertiesFunc func() {
+ return &attachedProperties;
+ }
+ static inline const QMetaObject *metaObject() {
+ return attachedPropertiesMetaObject(&T::qmlAttachedProperties);
+ }
+ };
+
+ template<typename T>
+ inline QmlAttachedPropertiesFunc attachedPropertiesFunc()
+ {
+ return AttachedPropertySelector<T, has_attachedPropertiesMethod<T, has_attachedPropertiesMember<T>::value>::value>::func();
+ }
+
+ template<typename T>
+ inline const QMetaObject *attachedPropertiesMetaObject()
+ {
+ return AttachedPropertySelector<T, has_attachedPropertiesMethod<T, has_attachedPropertiesMember<T>::value>::value>::metaObject();
+ }
+
+ struct MetaTypeIds {
+ int typeId;
+ int listId;
+ int qmlListId;
+ };
+ typedef int (*Func)(QmlPrivate::ListOp, int, const QVariant &, const QVariant &, void **);
+ typedef QObject *(*CreateFunc)(QObject *);
+
+ template<typename T>
+ struct CreateParent {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+
+ template<typename T>
+ struct CreateNoParent {
+ static QObject *create() {
+ return new T;
+ }
+ };
+
+ struct Q_DECLARATIVE_EXPORT InstanceType {
+ InstanceType(int);
+ };
+
+ template<typename T, int VMAJ, int VMIN>
+ struct Define {
+ static InstanceType instance;
+ };
+
+ template<typename T>
+ struct ExtCreate {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+}
+
+template<typename T>
+int QmlPrivate::list_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ if (op == QmlPrivate::Create) {
+ QObject *obj = static_cast<QObject *>(new T);
+ *((QObject **)out) = obj;
+ return 0;
+ }
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ if (list->count() <= val) *((QVariant *)*out) = QVariant();
+ else *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_nocreate_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_interface_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ break;
+ case QmlPrivate::FromObject:
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPRIVATE_H
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
new file mode 100644
index 0000000..04cffe1
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -0,0 +1,415 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertycache_p.h"
+
+#include "qmlengine_p.h"
+#include "qmlbinding.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_METATYPE(QScriptValue);
+
+void QmlPropertyCache::Data::load(const QMetaProperty &p, QmlEngine *engine)
+{
+ propType = p.userType();
+ if (QVariant::Type(propType) == QVariant::LastType)
+ propType = qMetaTypeId<QVariant>();
+ coreIndex = p.propertyIndex();
+ notifyIndex = p.notifySignalIndex();
+
+ if (p.isConstant())
+ flags |= Data::IsConstant;
+ if (p.isWritable())
+ flags |= Data::IsWritable;
+ if (p.isResettable())
+ flags |= Data::IsResettable;
+
+ if (propType == qMetaTypeId<QmlBinding *>()) {
+ flags |= Data::IsQmlBinding;
+ } else if (propType == qMetaTypeId<QScriptValue>()) {
+ flags |= Data::IsQScriptValue;
+ } else if (p.isEnumType()) {
+ flags |= Data::IsEnumType;
+ } else {
+ QmlMetaType::TypeCategory cat = engine ? QmlEnginePrivate::get(engine)->typeCategory(propType)
+ : QmlMetaType::typeCategory(propType);
+ if (cat == QmlMetaType::Object)
+ flags |= Data::IsQObjectDerived;
+ else if (cat == QmlMetaType::List)
+ flags |= Data::IsQList;
+ else if (cat == QmlMetaType::QmlList)
+ flags |= Data::IsQmlList;
+ }
+}
+
+void QmlPropertyCache::Data::load(const QMetaMethod &m)
+{
+ coreIndex = m.methodIndex();
+ flags |= Data::IsFunction;
+ propType = QVariant::Invalid;
+
+ const char *returnType = m.typeName();
+ if (returnType)
+ propType = QMetaType::type(returnType);
+
+ QList<QByteArray> params = m.parameterTypes();
+ if (!params.isEmpty())
+ flags |= Data::HasArguments;
+}
+
+
+QmlPropertyCache::QmlPropertyCache(QmlEngine *e)
+: QmlCleanup(e), engine(e)
+{
+}
+
+QmlPropertyCache::~QmlPropertyCache()
+{
+ clear();
+}
+
+void QmlPropertyCache::clear()
+{
+ for (int ii = 0; ii < indexCache.count(); ++ii)
+ indexCache.at(ii)->release();
+
+ for (StringCache::ConstIterator iter = stringCache.begin();
+ iter != stringCache.end(); ++iter)
+ (*iter)->release();
+
+ for (IdentifierCache::ConstIterator iter = identifierCache.begin();
+ iter != identifierCache.end(); ++iter)
+ (*iter)->release();
+
+ indexCache.clear();
+ stringCache.clear();
+ identifierCache.clear();
+}
+
+QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject,
+ const QString &property)
+{
+ Q_ASSERT(metaObject);
+
+ QmlPropertyCache::Data rv;
+ int idx = metaObject->indexOfProperty(property.toUtf8());
+ if (idx != -1) {
+ rv.load(metaObject->property(idx));
+ return rv;
+ }
+
+ int methodCount = metaObject->methodCount();
+ for (int ii = methodCount - 1; ii >= 0; --ii) {
+ QMetaMethod m = metaObject->method(ii);
+ if (m.access() == QMetaMethod::Private)
+ continue;
+ QString methodName = QString::fromUtf8(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ if (methodName == property) {
+ rv.load(m);
+ return rv;
+ }
+ }
+
+ return rv;
+}
+
+QmlPropertyCache *QmlPropertyCache::copy() const
+{
+ QmlPropertyCache *cache = new QmlPropertyCache(engine);
+ cache->indexCache = indexCache;
+ cache->stringCache = stringCache;
+ cache->identifierCache = identifierCache;
+
+ for (int ii = 0; ii < indexCache.count(); ++ii)
+ indexCache.at(ii)->addref();
+ for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
+ (*iter)->addref();
+ for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter)
+ (*iter)->addref();
+
+ return cache;
+}
+
+void QmlPropertyCache::append(QmlEngine *engine, const QMetaObject *metaObject,
+ Data::Flag propertyFlags, Data::Flag methodFlags)
+{
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ int propCount = metaObject->propertyCount();
+ int propOffset = metaObject->propertyOffset();
+
+ indexCache.resize(propCount);
+ for (int ii = propOffset; ii < propCount; ++ii) {
+ QMetaProperty p = metaObject->property(ii);
+ QString propName = QString::fromUtf8(p.name());
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
+
+ data->load(p, engine);
+ data->flags |= propertyFlags;
+
+ indexCache[ii] = data;
+
+ if (stringCache.contains(propName)) {
+ stringCache[propName]->release();
+ identifierCache[data->identifier.identifier]->release();
+ }
+
+ stringCache.insert(propName, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ data->addref();
+ }
+
+ int methodCount = metaObject->methodCount();
+ int methodOffset = metaObject->methodOffset();
+ for (int ii = methodOffset; ii < methodCount; ++ii) {
+ QMetaMethod m = metaObject->method(ii);
+ if (m.access() == QMetaMethod::Private)
+ continue;
+ QString methodName = QString::fromUtf8(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
+
+ if (stringCache.contains(methodName)) {
+ stringCache[methodName]->release();
+ identifierCache[data->identifier.identifier]->release();
+ }
+
+ data->load(m);
+ if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method)
+ data->flags |= methodFlags;
+
+ stringCache.insert(methodName, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ }
+}
+
+// ### Optimize - check engine for the parent meta object etc.
+QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(metaObject);
+
+ QmlPropertyCache *cache = new QmlPropertyCache(engine);
+ cache->update(engine, metaObject);
+ return cache;
+}
+
+void QmlPropertyCache::update(QmlEngine *engine, const QMetaObject *metaObject)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(metaObject);
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ clear();
+
+ // ### The properties/methods should probably be spliced on a per-metaobject basis
+ int propCount = metaObject->propertyCount();
+
+ indexCache.resize(propCount);
+ for (int ii = propCount - 1; ii >= 0; --ii) {
+ QMetaProperty p = metaObject->property(ii);
+ QString propName = QString::fromUtf8(p.name());
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
+
+ data->load(p, engine);
+
+ indexCache[ii] = data;
+
+ if (stringCache.contains(propName))
+ continue;
+
+ stringCache.insert(propName, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ data->addref();
+ }
+
+ int methodCount = metaObject->methodCount();
+ for (int ii = methodCount - 1; ii >= 0; --ii) {
+ QMetaMethod m = metaObject->method(ii);
+ if (m.access() == QMetaMethod::Private)
+ continue;
+ QString methodName = QString::fromUtf8(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ if (stringCache.contains(methodName))
+ continue;
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
+
+ data->load(m);
+
+ stringCache.insert(methodName, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ }
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(int index) const
+{
+ if (index < 0 || index >= indexCache.count())
+ return 0;
+
+ return indexCache.at(index);
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(const QString &str) const
+{
+ return stringCache.value(str);
+}
+
+QString QmlPropertyCache::Data::name(QObject *object)
+{
+ if (!object)
+ return QString();
+
+ return name(object->metaObject());
+}
+
+QString QmlPropertyCache::Data::name(const QMetaObject *metaObject)
+{
+ if (!metaObject || coreIndex == -1)
+ return QString();
+
+ if (flags & IsFunction) {
+ QMetaMethod m = metaObject->method(coreIndex);
+
+ QString name = QString::fromUtf8(m.signature());
+ int parenIdx = name.indexOf(QLatin1Char('('));
+ if (parenIdx != -1)
+ name = name.left(parenIdx);
+ return name;
+ } else {
+ QMetaProperty p = metaObject->property(coreIndex);
+ return QString::fromUtf8(p.name());
+ }
+}
+
+QStringList QmlPropertyCache::propertyNames() const
+{
+ return stringCache.keys();
+}
+
+QmlPropertyCache::Data *QmlPropertyCache::property(QmlEngine *engine, QObject *obj,
+ const QScriptDeclarativeClass::Identifier &name, Data &local)
+{
+ QmlPropertyCache::Data *rv = 0;
+
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
+ cache = ddata->propertyCache;
+ if (!cache) {
+ cache = enginePrivate->cache(obj);
+ if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
+ }
+
+ if (cache) {
+ rv = cache->property(name);
+ } else {
+ local = QmlPropertyCache::create(obj->metaObject(), enginePrivate->objectClass->toString(name));
+ if (local.isValid())
+ rv = &local;
+ }
+
+ return rv;
+}
+
+QmlPropertyCache::Data *QmlPropertyCache::property(QmlEngine *engine, QObject *obj,
+ const QString &name, Data &local)
+{
+ QmlPropertyCache::Data *rv = 0;
+
+ if (!engine) {
+ local = QmlPropertyCache::create(obj->metaObject(), name);
+ if (local.isValid())
+ rv = &local;
+ } else {
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
+ cache = ddata->propertyCache;
+ if (!cache) {
+ cache = enginePrivate->cache(obj);
+ if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
+ }
+
+ if (cache) {
+ rv = cache->property(name);
+ } else {
+ local = QmlPropertyCache::create(obj->metaObject(), name);
+ if (local.isValid())
+ rv = &local;
+ }
+ }
+
+ return rv;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
new file mode 100644
index 0000000..efc4643
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYCACHE_P_H
+#define QMLPROPERTYCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlrefcount_p.h"
+#include "qmlcleanup_p.h"
+
+#include <QtCore/qvector.h>
+
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QMetaProperty;
+class QmlPropertyCache : public QmlRefCount, public QmlCleanup
+{
+public:
+ QmlPropertyCache(QmlEngine *);
+ virtual ~QmlPropertyCache();
+
+ struct Data {
+ inline Data();
+ inline bool operator==(const Data &);
+
+ enum Flag {
+ NoFlags = 0x00000000,
+
+ // Can apply to all properties, except IsFunction
+ IsConstant = 0x00000001,
+ IsWritable = 0x00000002,
+ IsResettable = 0x00000004,
+
+ // These are mutualy exclusive
+ IsFunction = 0x00000008,
+ IsQObjectDerived = 0x00000010,
+ IsEnumType = 0x00000020,
+ IsQmlList = 0x00000040,
+ IsQList = 0x00000080,
+ IsQmlBinding = 0x00000100,
+ IsQScriptValue = 0x00000200,
+
+ // Apply only to IsFunctions
+ IsVMEFunction = 0x00000400,
+ HasArguments = 0x00000800
+
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ bool isValid() const { return coreIndex != -1; }
+
+ Flags flags;
+ int propType;
+ int coreIndex;
+ int notifyIndex;
+
+ void load(const QMetaProperty &, QmlEngine *engine = 0);
+ void load(const QMetaMethod &);
+ QString name(QObject *);
+ QString name(const QMetaObject *);
+ };
+
+ struct ValueTypeData {
+ inline ValueTypeData();
+ inline bool operator==(const ValueTypeData &);
+ int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper
+ int valueTypePropType; // The QVariant::Type of access property on the value type wrapper
+ };
+
+ void update(QmlEngine *, const QMetaObject *);
+
+ QmlPropertyCache *copy() const;
+ void append(QmlEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags,
+ Data::Flag methodFlags = Data::NoFlags);
+
+ static QmlPropertyCache *create(QmlEngine *, const QMetaObject *);
+ static Data create(const QMetaObject *, const QString &);
+
+ inline Data *property(const QScriptDeclarativeClass::Identifier &id) const;
+ Data *property(const QString &) const;
+ Data *property(int) const;
+ QStringList propertyNames() const;
+
+ inline QmlEngine *qmlEngine() const;
+ static Data *property(QmlEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &);
+ static Data *property(QmlEngine *, QObject *, const QString &, Data &);
+protected:
+ virtual void clear();
+
+private:
+ struct RData : public Data, public QmlRefCount {
+ QScriptDeclarativeClass::PersistentIdentifier identifier;
+ };
+
+ typedef QVector<RData *> IndexCache;
+ typedef QHash<QString, RData *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+
+ QmlEngine *engine;
+ IndexCache indexCache;
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlPropertyCache::Data::Flags);
+
+QmlPropertyCache::Data::Data()
+: flags(0), propType(0), coreIndex(-1), notifyIndex(-1)
+{
+}
+
+bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data &other)
+{
+ return flags == other.flags &&
+ propType == other.propType &&
+ coreIndex == other.coreIndex &&
+ notifyIndex == other.notifyIndex;
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const
+{
+ return identifierCache.value(id);
+}
+
+QmlPropertyCache::ValueTypeData::ValueTypeData()
+: valueTypeCoreIdx(-1), valueTypePropType(0)
+{
+}
+
+bool QmlPropertyCache::ValueTypeData::operator==(const ValueTypeData &o)
+{
+ return valueTypeCoreIdx == o.valueTypeCoreIdx &&
+ valueTypePropType == o.valueTypePropType;
+}
+
+QmlEngine *QmlPropertyCache::qmlEngine() const
+{
+ return engine;
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLPROPERTYCACHE_P_H
diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.cpp b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp
new file mode 100644
index 0000000..9d0d7f6
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertyvalueinterceptor.h"
+
+#include "qml.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlPropertyValueInterceptor
+ \brief The QmlPropertyValueInterceptor class is inherited by property interceptors such as Behavior.
+ \internal
+
+ This class intercepts property writes, allowing for custom handling. For example, Behavior uses this
+ interception to provide a default animation for all changes to a property's value.
+ */
+
+/*!
+ Constructs a QmlPropertyValueInterceptor.
+*/
+QmlPropertyValueInterceptor::QmlPropertyValueInterceptor()
+{
+}
+
+QmlPropertyValueInterceptor::~QmlPropertyValueInterceptor()
+{
+}
+
+/*!
+ \fn void QmlPropertyValueInterceptor::setTarget(const QmlMetaProperty &property)
+ Set the target \a property for the value interceptor. This method will
+ be called by the QML engine when assigning a value interceptor.
+*/
+
+/*!
+ \fn void QmlPropertyValueInterceptor::write(const QVariant &value)
+ This method will be called when a new \a value is assigned to the property being intercepted.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.h b/src/declarative/qml/qmlpropertyvalueinterceptor.h
new file mode 100644
index 0000000..71cc6c5
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvalueinterceptor.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVALUEINTERCEPTOR_H
+#define QMLPROPERTYVALUEINTERCEPTOR_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueInterceptor
+{
+public:
+ QmlPropertyValueInterceptor();
+ virtual ~QmlPropertyValueInterceptor();
+ virtual void setTarget(const QmlMetaProperty &property) = 0;
+ virtual void write(const QVariant &value) = 0;
+};
+Q_DECLARE_INTERFACE(QmlPropertyValueInterceptor, "com.trolltech.qml.QmlPropertyValueInterceptor")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROPERTYVALUEINTERCEPTOR_H
diff --git a/src/declarative/qml/qmlpropertyvaluesource.cpp b/src/declarative/qml/qmlpropertyvaluesource.cpp
new file mode 100644
index 0000000..50f2f8c
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertyvaluesource.h"
+
+#include "qml.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlPropertyValueSource
+ \brief The QmlPropertyValueSource class is inherited by property value sources such as animations and bindings.
+ \internal
+ */
+
+/*!
+ Constructs a QmlPropertyValueSource.
+*/
+QmlPropertyValueSource::QmlPropertyValueSource()
+{
+}
+
+QmlPropertyValueSource::~QmlPropertyValueSource()
+{
+}
+
+/*!
+ \fn void QmlPropertyValueSource::setTarget(const QmlMetaProperty &property)
+ Set the target \a property for the value source. This method will
+ be called by the QML engine when assigning a value source.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvaluesource.h b/src/declarative/qml/qmlpropertyvaluesource.h
new file mode 100644
index 0000000..2017fb2
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVALUESOURCE_H
+#define QMLPROPERTYVALUESOURCE_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueSource
+{
+public:
+ QmlPropertyValueSource();
+ virtual ~QmlPropertyValueSource();
+ virtual void setTarget(const QmlMetaProperty &) = 0;
+};
+Q_DECLARE_INTERFACE(QmlPropertyValueSource, "com.trolltech.qml.QmlPropertyValueSource")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROPERTYVALUESOURCE_H
diff --git a/src/declarative/qml/qmlproxymetaobject.cpp b/src/declarative/qml/qmlproxymetaobject.cpp
new file mode 100644
index 0000000..983c350
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlproxymetaobject_p.h"
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QmlProxyMetaObject::QmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
+: metaObjects(mList), proxies(0), parent(0), object(obj)
+{
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ qWarning() << "QmlProxyMetaObject" << obj->metaObject()->className();
+#endif
+
+ *static_cast<QMetaObject *>(this) = *metaObjects->first().metaObject;
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+
+ op->metaObject = this;
+
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ const QMetaObject *mo = obj->metaObject();
+ while(mo) {
+ qWarning() << " " << mo->className();
+ mo = mo->superClass();
+ }
+#endif
+}
+
+QmlProxyMetaObject::~QmlProxyMetaObject()
+{
+ if (parent)
+ delete parent;
+ parent = 0;
+
+ if (proxies)
+ delete [] proxies;
+ proxies = 0;
+}
+
+int QmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if ((c == QMetaObject::ReadProperty ||
+ c == QMetaObject::WriteProperty) &&
+ id >= metaObjects->last().propertyOffset) {
+
+ for (int ii = 0; ii < metaObjects->count(); ++ii) {
+ const ProxyData &data = metaObjects->at(ii);
+ if (id >= data.propertyOffset) {
+ if (!proxies) {
+ proxies = new QObject*[metaObjects->count()];
+ ::memset(proxies, 0,
+ sizeof(QObject *) * metaObjects->count());
+ }
+
+ if (!proxies[ii]) {
+ QObject *proxy = data.createFunc(object);
+ const QMetaObject *metaObject = proxy->metaObject();
+ proxies[ii] = proxy;
+
+ int localOffset = data.metaObject->methodOffset();
+ int methodOffset = metaObject->methodOffset();
+ int methods = metaObject->methodCount() - methodOffset;
+
+ // ### - Can this be done more optimally?
+ for (int jj = 0; jj < methods; ++jj) {
+ QMetaMethod method =
+ metaObject->method(jj + methodOffset);
+ if (method.methodType() == QMetaMethod::Signal)
+ QMetaObject::connect(proxy, methodOffset + jj,
+ object, localOffset + jj);
+ }
+ }
+
+ int proxyOffset = proxies[ii]->metaObject()->propertyOffset();
+ int proxyId = id - data.propertyOffset + proxyOffset;
+
+ return proxies[ii]->qt_metacall(c, proxyId, a);
+ }
+ }
+ } else if (c == QMetaObject::InvokeMetaMethod &&
+ id >= metaObjects->last().methodOffset) {
+ QMetaMethod m = object->metaObject()->method(id);
+ if (m.methodType() == QMetaMethod::Signal) {
+ QMetaObject::activate(object, id, a);
+ return -1;
+ }
+ }
+
+ if (parent)
+ return parent->metaCall(c, id, a);
+ else
+ return object->qt_metacall(c, id, a);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlproxymetaobject_p.h b/src/declarative/qml/qmlproxymetaobject_p.h
new file mode 100644
index 0000000..f983030
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROXYMETAOBJECT_P_H
+#define QMLPROXYMETAOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmetaobjectbuilder_p.h"
+#include "qml.h"
+
+#include <QtCore/QMetaObject>
+#include <QtCore/QObject>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlProxyMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ struct ProxyData {
+ typedef QObject *(*CreateFunc)(QObject *);
+ QMetaObject *metaObject;
+ CreateFunc createFunc;
+ int propertyOffset;
+ int methodOffset;
+ };
+
+ QmlProxyMetaObject(QObject *, QList<ProxyData> *);
+ virtual ~QmlProxyMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QList<ProxyData> *metaObjects;
+ QObject **proxies;
+
+ QAbstractDynamicMetaObject *parent;
+ QObject *object;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROXYMETAOBJECT_P_H
+
diff --git a/src/declarative/qml/qmlrefcount.cpp b/src/declarative/qml/qmlrefcount.cpp
new file mode 100644
index 0000000..9422625
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlrefcount_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlRefCount::QmlRefCount()
+: refCount(1)
+{
+}
+
+QmlRefCount::~QmlRefCount()
+{
+}
+
+void QmlRefCount::addref()
+{
+ Q_ASSERT(refCount > 0);
+ ++refCount;
+}
+
+void QmlRefCount::release()
+{
+ Q_ASSERT(refCount > 0);
+ --refCount;
+ if (refCount == 0)
+ delete this;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlrefcount_p.h b/src/declarative/qml/qmlrefcount_p.h
new file mode 100644
index 0000000..7448042
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLREFCOUNT_P_H
+#define QMLREFCOUNT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_AUTOTEST_EXPORT QmlRefCount
+{
+public:
+ QmlRefCount();
+ virtual ~QmlRefCount();
+ void addref();
+ void release();
+
+private:
+ int refCount;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLREFCOUNT_P_H
diff --git a/src/declarative/qml/qmlrewrite.cpp b/src/declarative/qml/qmlrewrite.cpp
new file mode 100644
index 0000000..34bd198
--- /dev/null
+++ b/src/declarative/qml/qmlrewrite.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlrewrite_p.h"
+
+#include "qmlglobal_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP);
+
+namespace QmlRewrite {
+
+bool SharedBindingTester::isSharable(const QString &code)
+{
+ Engine engine;
+ NodePool pool(QString(), &engine);
+ Lexer lexer(&engine);
+ Parser parser(&engine);
+ lexer.setCode(code, 0);
+ parser.parseStatement();
+ if (!parser.statement())
+ return false;
+
+ _sharable = true;
+ AST::Node::acceptChild(parser.statement(), this);
+ return _sharable;
+}
+
+QString RewriteBinding::operator()(const QString &code, bool *ok)
+{
+ Engine engine;
+ NodePool pool(QString(), &engine);
+ Lexer lexer(&engine);
+ Parser parser(&engine);
+ lexer.setCode(code, 0);
+ parser.parseStatement();
+ if (!parser.statement()) {
+ if (ok) *ok = false;
+ return QString();
+ } else {
+ if (ok) *ok = true;
+ }
+ return rewrite(code, 0, parser.statement());
+}
+
+void RewriteBinding::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+QString RewriteBinding::rewrite(QString code, unsigned position,
+ AST::Statement *node)
+{
+ TextWriter w;
+ _writer = &w;
+ _position = position;
+ _inLoop = 0;
+
+ accept(node);
+
+ unsigned startOfStatement = node->firstSourceLocation().begin() - _position;
+ unsigned endOfStatement = node->lastSourceLocation().end() - _position;
+
+ _writer->replace(startOfStatement, 0, QLatin1String("(function() { "));
+ _writer->replace(endOfStatement, 0, QLatin1String(" })"));
+
+ if (rewriteDump()) {
+ qWarning() << "=============================================================";
+ qWarning() << "Rewrote:";
+ qWarning() << qPrintable(code);
+ }
+
+ w.write(&code);
+
+ if (rewriteDump()) {
+ qWarning() << "To:";
+ qWarning() << qPrintable(code);
+ qWarning() << "=============================================================";
+ }
+
+ return code;
+}
+
+bool RewriteBinding::visit(AST::Block *ast)
+{
+ for (AST::StatementList *it = ast->statements; it; it = it->next) {
+ if (! it->next) {
+ // we need to rewrite only the last statement of a block.
+ accept(it->statement);
+ }
+ }
+
+ return false;
+}
+
+bool RewriteBinding::visit(AST::ExpressionStatement *ast)
+{
+ if (! _inLoop) {
+ unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position;
+ _writer->replace(startOfExpressionStatement, 0, QLatin1String("return "));
+ }
+
+ return false;
+}
+
+bool RewriteBinding::visit(AST::DoWhileStatement *)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::DoWhileStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::WhileStatement *)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::WhileStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::ForStatement *)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::ForStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::LocalForStatement *)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::LocalForStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::ForEachStatement *)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::ForEachStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::LocalForEachStatement *)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::LocalForEachStatement *)
+{
+ --_inLoop;
+}
+
+} // namespace QmlRewrite
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlrewrite_p.h b/src/declarative/qml/qmlrewrite_p.h
new file mode 100644
index 0000000..a04a0db
--- /dev/null
+++ b/src/declarative/qml/qmlrewrite_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLREWRITE_P_H
+#define QMLREWRITE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "rewriter/textwriter_p.h"
+#include "parser/qmljslexer_p.h"
+#include "parser/qmljsparser_p.h"
+#include "parser/qmljsnodepool_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlRewrite {
+using namespace QmlJS;
+
+class SharedBindingTester : protected AST::Visitor
+{
+ bool _sharable;
+public:
+ bool isSharable(const QString &code);
+
+ virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; }
+ virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; }
+ virtual bool visit(AST::CallExpression *) { _sharable = false; return false; }
+};
+
+class RewriteBinding: protected AST::Visitor
+{
+ unsigned _position;
+ TextWriter *_writer;
+
+public:
+ QString operator()(const QString &code, bool *ok = 0);
+
+protected:
+ using AST::Visitor::visit;
+
+ void accept(AST::Node *node);
+ QString rewrite(QString code, unsigned position, AST::Statement *node);
+
+ virtual bool visit(AST::Block *ast);
+ virtual bool visit(AST::ExpressionStatement *ast);
+
+ virtual bool visit(AST::DoWhileStatement *ast);
+ virtual void endVisit(AST::DoWhileStatement *ast);
+
+ virtual bool visit(AST::WhileStatement *ast);
+ virtual void endVisit(AST::WhileStatement *ast);
+
+ virtual bool visit(AST::ForStatement *ast);
+ virtual void endVisit(AST::ForStatement *ast);
+
+ virtual bool visit(AST::LocalForStatement *ast);
+ virtual void endVisit(AST::LocalForStatement *ast);
+
+ virtual bool visit(AST::ForEachStatement *ast);
+ virtual void endVisit(AST::ForEachStatement *ast);
+
+ virtual bool visit(AST::LocalForEachStatement *ast);
+ virtual void endVisit(AST::LocalForEachStatement *ast);
+
+private:
+ int _inLoop;
+};
+
+} // namespace QmlRewrite
+
+QT_END_NAMESPACE
+
+#endif // QMLREWRITE_P_H
+
diff --git a/src/declarative/qml/qmlscript.cpp b/src/declarative/qml/qmlscript.cpp
new file mode 100644
index 0000000..10fc9a6
--- /dev/null
+++ b/src/declarative/qml/qmlscript.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This is just a dummy file to include the documentation
+
+/*!
+ \qmlclass Script QmlScript
+ \brief The Script element provides a way to add JavaScript code snippets in QML.
+ \ingroup group_utility
+
+ The Script element is used to add convenient JavaScript "glue" methods to
+ your Qt Declarative application or component.
+
+ An example:
+
+ \qml
+ Script {
+ function debugMyComponent() {
+ console.log(text.text);
+ console.log(otherinterestingitem.property);
+ }
+ }
+ MouseRegion { onClicked: debugMyComponent() }
+ \endqml
+
+ \note While it is possible to use any JavaScript code within a Script element,
+ it is recommended that the code be limited to defining functions. The Script
+ element executes JavaScript as soon as it is specified, so
+ when defining a component, this may be done before the execution context is
+ fully specified. As a result, some properties or items may not be
+ accessible. You can avoid this problem by limiting your JavaScript to
+ defining functions that are only executed later once the context is fully
+ defined.
+
+ \sa {JavaScript Blocks}
+*/
+
+/*!
+ \qmlproperty string Script::script
+ \default
+ The JavaScript code to be executed.
+*/
+
+/*!
+ \qmlproperty url Script::source
+
+ Specifies a source file containing JavaScript code. This can be used instead
+ of providing inline JavaScript code in the Script element.
+*/
diff --git a/src/declarative/qml/qmlscriptclass_p.h b/src/declarative/qml/qmlscriptclass_p.h
new file mode 100644
index 0000000..847ee66
--- /dev/null
+++ b/src/declarative/qml/qmlscriptclass_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSCRIPTCLASS_P_H
+#define QMLSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlScriptClass(QScriptEngine *);
+
+ static QVariant toVariant(QmlEngine *, const QScriptValue &);
+
+#if (QT_VERSION <= QT_VERSION_CHECK(4, 6, 2)) && !defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
+ struct Value : public QScriptValue {
+ Value() : QScriptValue() {}
+ Value(QScriptEngine *engine, int v) : QScriptValue(engine, v) {}
+ Value(QScriptEngine *engine, uint v) : QScriptValue(engine, v) {}
+ Value(QScriptEngine *engine, bool v) : QScriptValue(engine, v) {}
+ Value(QScriptEngine *engine, double v) : QScriptValue(engine, v) {}
+ Value(QScriptEngine *engine, float v) : QScriptValue(engine, v) {}
+ Value(QScriptEngine *engine, const QString &v) : QScriptValue(engine, v) {}
+ Value(QScriptEngine *, const QScriptValue &v) : QScriptValue(v) {}
+ };
+
+ typedef QScriptValue ScriptValue;
+#else
+ typedef Value ScriptValue;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSCRIPTCLASS_P_H
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
new file mode 100644
index 0000000..a24ef51
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -0,0 +1,952 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlscriptparser_p.h"
+
+#include "qmlparser_p.h"
+#include "parser/qmljsengine_p.h"
+#include "parser/qmljsparser_p.h"
+#include "parser/qmljslexer_p.h"
+#include "parser/qmljsnodepool_p.h"
+#include "parser/qmljsastvisitor_p.h"
+#include "parser/qmljsast_p.h"
+#include "qmlrewrite_p.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QStack>
+#include <QCoreApplication>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+using namespace QmlParser;
+
+namespace {
+
+class ProcessAST: protected AST::Visitor
+{
+ struct State {
+ State() : object(0), property(0) {}
+ State(Object *o) : object(o), property(0) {}
+ State(Object *o, Property *p) : object(o), property(p) {}
+
+ Object *object;
+ Property *property;
+ };
+
+ struct StateStack : public QStack<State>
+ {
+ void pushObject(Object *obj)
+ {
+ push(State(obj));
+ }
+
+ void pushProperty(const QString &name, const LocationSpan &location)
+ {
+ const State &state = top();
+ if (state.property) {
+ State s(state.property->getValue(),
+ state.property->getValue()->getProperty(name.toUtf8()));
+ s.property->location = location;
+ push(s);
+ } else {
+ State s(state.object,
+ state.object->getProperty(name.toUtf8()));
+
+ s.property->location = location;
+ push(s);
+ }
+ }
+ };
+
+public:
+ ProcessAST(QmlScriptParser *parser);
+ virtual ~ProcessAST();
+
+ void operator()(const QString &code, AST::Node *node);
+
+protected:
+ Object *defineObjectBinding(AST::UiQualifiedId *propertyName,
+ AST::UiQualifiedId *objectTypeName,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+
+ Object *defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+
+ QmlParser::Variant getVariant(AST::ExpressionNode *expr);
+
+ LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
+ LocationSpan location(AST::UiQualifiedId *);
+
+ using AST::Visitor::visit;
+ using AST::Visitor::endVisit;
+
+ virtual bool visit(AST::UiProgram *node);
+ virtual bool visit(AST::UiImport *node);
+ virtual bool visit(AST::UiObjectDefinition *node);
+ virtual bool visit(AST::UiPublicMember *node);
+ virtual bool visit(AST::UiObjectBinding *node);
+
+ virtual bool visit(AST::UiScriptBinding *node);
+ virtual bool visit(AST::UiArrayBinding *node);
+ virtual bool visit(AST::UiSourceElement *node);
+
+ void accept(AST::Node *node);
+
+ QString asString(AST::UiQualifiedId *node) const;
+
+ const State state() const;
+ Object *currentObject() const;
+ Property *currentProperty() const;
+
+ QString qualifiedNameId() const;
+
+ QString textAt(const AST::SourceLocation &loc) const
+ { return _contents.mid(loc.offset, loc.length); }
+
+
+ QString textAt(const AST::SourceLocation &first,
+ const AST::SourceLocation &last) const
+ { return _contents.mid(first.offset, last.offset + last.length - first.offset); }
+
+ QString asString(AST::ExpressionNode *expr)
+ {
+ if (! expr)
+ return QString();
+
+ return textAt(expr->firstSourceLocation(), expr->lastSourceLocation());
+ }
+
+ QString asString(AST::Statement *stmt)
+ {
+ if (! stmt)
+ return QString();
+
+ QString s = textAt(stmt->firstSourceLocation(), stmt->lastSourceLocation());
+ s += QLatin1Char('\n');
+ return s;
+ }
+
+private:
+ QmlScriptParser *_parser;
+ StateStack _stateStack;
+ QStringList _scope;
+ QString _contents;
+
+ inline bool isSignalProperty(const QByteArray &propertyName) const {
+ return (propertyName.length() >= 3 && propertyName.startsWith("on") &&
+ ('A' <= propertyName.at(2) && 'Z' >= propertyName.at(2)));
+ }
+
+};
+
+ProcessAST::ProcessAST(QmlScriptParser *parser)
+ : _parser(parser)
+{
+}
+
+ProcessAST::~ProcessAST()
+{
+}
+
+void ProcessAST::operator()(const QString &code, AST::Node *node)
+{
+ _contents = code;
+ accept(node);
+}
+
+void ProcessAST::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+const ProcessAST::State ProcessAST::state() const
+{
+ if (_stateStack.isEmpty())
+ return State();
+
+ return _stateStack.back();
+}
+
+Object *ProcessAST::currentObject() const
+{
+ return state().object;
+}
+
+Property *ProcessAST::currentProperty() const
+{
+ return state().property;
+}
+
+QString ProcessAST::qualifiedNameId() const
+{
+ return _scope.join(QLatin1String("/"));
+}
+
+QString ProcessAST::asString(AST::UiQualifiedId *node) const
+{
+ QString s;
+
+ for (AST::UiQualifiedId *it = node; it; it = it->next) {
+ s.append(it->name->asString());
+
+ if (it->next)
+ s.append(QLatin1Char('.'));
+ }
+
+ return s;
+}
+
+Object *
+ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ int lastTypeDot = objectType.lastIndexOf(QLatin1Char('.'));
+ bool isType = !objectType.isEmpty() &&
+ (objectType.at(0).isUpper() ||
+ (lastTypeDot >= 0 && objectType.at(lastTypeDot+1).isUpper()));
+
+ int propertyCount = 0;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ this->location(propertyName));
+ }
+
+ if (!isType) {
+
+ if(propertyCount || !currentObject()) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected type name"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ return 0;
+ }
+
+ LocationSpan loc = ProcessAST::location(typeLocation, typeLocation);
+ if (propertyName)
+ loc = ProcessAST::location(propertyName);
+
+ _stateStack.pushProperty(objectType, loc);
+ accept(initializer);
+ _stateStack.pop();
+
+ return 0;
+
+ } else {
+ // Class
+
+ QString resolvableObjectType = objectType;
+ if (lastTypeDot >= 0)
+ resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/'));
+
+ bool isScript = resolvableObjectType == QLatin1String("Script");
+
+ if (isScript) {
+ if (_stateStack.isEmpty() || _stateStack.top().property) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Invalid use of Script block"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ return 0;
+ }
+ }
+
+ Object *obj = new Object;
+
+ if (!isScript) {
+ QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
+ obj->type = typeRef->id;
+
+ typeRef->refObjects.append(obj);
+ }
+
+ // XXX this doesn't do anything (_scope never builds up)
+ _scope.append(resolvableObjectType);
+ obj->typeName = qualifiedNameId().toUtf8();
+ _scope.removeLast();
+
+ obj->location = location;
+
+ if (isScript) {
+
+ _stateStack.top().object->scriptBlockObjects.append(obj);
+
+ } else if (propertyCount) {
+
+ Property *prop = currentProperty();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ } else {
+
+ if (! _parser->tree()) {
+ _parser->setTree(obj);
+ } else {
+ const State state = _stateStack.top();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ if (state.property) {
+ state.property->addValue(v);
+ } else {
+ Property *defaultProp = state.object->getDefaultProperty();
+ if (defaultProp->location.start.line == -1) {
+ defaultProp->location = v->location;
+ defaultProp->location.end = defaultProp->location.start;
+ defaultProp->location.range.length = 0;
+ }
+ defaultProp->addValue(v);
+ }
+ }
+ }
+
+ _stateStack.pushObject(obj);
+ accept(initializer);
+ _stateStack.pop();
+
+ return obj;
+ }
+}
+
+Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
+ AST::UiQualifiedId *objectTypeName,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ const QString objectType = asString(objectTypeName);
+ const AST::SourceLocation typeLocation = objectTypeName->identifierToken;
+
+ if (objectType == QLatin1String("Script")) {
+
+ AST::UiObjectMemberList *it = initializer->members;
+ for (; it; it = it->next) {
+ AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(it->member);
+ if (! scriptBinding)
+ continue;
+
+ QString propertyName = asString(scriptBinding->qualifiedId);
+ if (propertyName == QLatin1String("source")) {
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) {
+ QmlParser::Variant string = getVariant(stmt->expression);
+ if (string.isStringList()) {
+ QStringList urls = string.asStringList();
+ // We need to add this as a resource
+ for (int ii = 0; ii < urls.count(); ++ii)
+ _parser->_refUrls << QUrl(urls.at(ii));
+ }
+ }
+ }
+ }
+
+ }
+
+ return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer);
+}
+
+LocationSpan ProcessAST::location(AST::UiQualifiedId *id)
+{
+ return location(id->identifierToken, id->identifierToken);
+}
+
+LocationSpan ProcessAST::location(AST::SourceLocation start, AST::SourceLocation end)
+{
+ LocationSpan rv;
+ rv.start.line = start.startLine;
+ rv.start.column = start.startColumn;
+ rv.end.line = end.startLine;
+ rv.end.column = end.startColumn + end.length - 1;
+ rv.range.offset = start.offset;
+ rv.range.length = end.offset + end.length - start.offset;
+ return rv;
+}
+
+// UiProgram: UiImportListOpt UiObjectMemberList ;
+bool ProcessAST::visit(AST::UiProgram *node)
+{
+ accept(node->imports);
+ accept(node->members->member);
+ return false;
+}
+
+// UiImport: T_IMPORT T_STRING_LITERAL ;
+bool ProcessAST::visit(AST::UiImport *node)
+{
+ QString uri;
+ QmlScriptParser::Import import;
+
+ if (node->fileName) {
+ import.type = QmlScriptParser::Import::File;
+ uri = node->fileName->asString();
+ } else {
+ import.type = QmlScriptParser::Import::Library;
+ uri = asString(node->importUri);
+ }
+
+ AST::SourceLocation startLoc = node->importToken;
+ AST::SourceLocation endLoc = node->semicolonToken;
+
+ if (node->importId) {
+ import.qualifier = node->importId->asString();
+ if (!import.qualifier.at(0).isUpper()) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Invalid import qualifier ID"));
+ error.setLine(node->importIdToken.startLine);
+ error.setColumn(node->importIdToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+ }
+ if (node->versionToken.isValid())
+ import.version = textAt(node->versionToken);
+ else if (import.type == QmlScriptParser::Import::Library) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Library import requires a version"));
+ error.setLine(node->importIdToken.startLine);
+ error.setColumn(node->importIdToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ import.location = location(startLoc, endLoc);
+ import.uri = uri;
+
+ _parser->_imports << import;
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiPublicMember *node)
+{
+ const struct TypeNameToType {
+ const char *name;
+ Object::DynamicProperty::Type type;
+ const char *qtName;
+ } propTypeNameToTypes[] = {
+ { "int", Object::DynamicProperty::Int, "int" },
+ { "bool", Object::DynamicProperty::Bool, "bool" },
+ { "double", Object::DynamicProperty::Real, "double" },
+ { "real", Object::DynamicProperty::Real, "qreal" },
+ { "string", Object::DynamicProperty::String, "QString" },
+ { "url", Object::DynamicProperty::Url, "QUrl" },
+ { "color", Object::DynamicProperty::Color, "QColor" },
+ { "date", Object::DynamicProperty::Date, "QDate" },
+ { "var", Object::DynamicProperty::Variant, "QVariant" },
+ { "variant", Object::DynamicProperty::Variant, "QVariant" }
+ };
+ const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
+ sizeof(propTypeNameToTypes[0]);
+
+ if(node->type == AST::UiPublicMember::Signal) {
+ const QString name = node->name->asString();
+
+ Object::DynamicSignal signal;
+ signal.name = name.toUtf8();
+
+ AST::UiParameterList *p = node->parameters;
+ while (p) {
+ const QString memberType = p->type->asString();
+ const char *qtType = 0;
+ for(int ii = 0; !qtType && ii < propTypeNameToTypesCount; ++ii) {
+ if(QLatin1String(propTypeNameToTypes[ii].name) == memberType)
+ qtType = propTypeNameToTypes[ii].qtName;
+ }
+
+ if (!qtType) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected parameter type"));
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ signal.parameterTypes << qtType;
+ signal.parameterNames << p->name->asString().toUtf8();
+ p = p->finish();
+ }
+
+ _stateStack.top().object->dynamicSignals << signal;
+ } else {
+ const QString memberType = node->memberType->asString();
+ const QString name = node->name->asString();
+
+ bool typeFound = false;
+ Object::DynamicProperty::Type type;
+
+ if (memberType == QLatin1String("alias")) {
+ type = Object::DynamicProperty::Alias;
+ typeFound = true;
+ }
+
+ for(int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
+ if(QLatin1String(propTypeNameToTypes[ii].name) == memberType) {
+ type = propTypeNameToTypes[ii].type;
+ typeFound = true;
+ }
+ }
+
+ if (!typeFound && memberType.at(0).isUpper()) {
+ QString typemodifier;
+ if(node->typeModifier)
+ typemodifier = node->typeModifier->asString();
+ if (typemodifier == QString()) {
+ type = Object::DynamicProperty::Custom;
+ } else if(typemodifier == QLatin1String("list")) {
+ type = Object::DynamicProperty::CustomList;
+ } else {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Invalid property type modifier"));
+ error.setLine(node->typeModifierToken.startLine);
+ error.setColumn(node->typeModifierToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+ typeFound = true;
+ } else if (node->typeModifier) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Unexpected property type modifier"));
+ error.setLine(node->typeModifierToken.startLine);
+ error.setColumn(node->typeModifierToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ if(!typeFound) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected property type"));
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ if (node->isReadonlyMember) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Readonly not yet supported"));
+ error.setLine(node->readonlyToken.startLine);
+ error.setColumn(node->readonlyToken.startColumn);
+ _parser->_errors << error;
+ return false;
+
+ }
+ Object::DynamicProperty property;
+ property.isDefaultProperty = node->isDefaultMember;
+ property.type = type;
+ if (type >= Object::DynamicProperty::Custom) {
+ QmlScriptParser::TypeReference *typeRef =
+ _parser->findOrCreateType(memberType);
+ typeRef->refObjects.append(_stateStack.top().object);
+ }
+ property.customType = memberType.toUtf8();
+ property.name = name.toUtf8();
+ property.location = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+
+ if (node->expression) { // default value
+ property.defaultValue = new Property;
+ property.defaultValue->parent = _stateStack.top().object;
+ property.defaultValue->location =
+ location(node->expression->firstSourceLocation(),
+ node->expression->lastSourceLocation());
+ Value *value = new Value;
+ value->location = location(node->expression->firstSourceLocation(),
+ node->expression->lastSourceLocation());
+ value->value = getVariant(node->expression);
+ property.defaultValue->values << value;
+ }
+
+ _stateStack.top().object->dynamicProperties << property;
+ }
+
+ return true;
+}
+
+
+// UiObjectMember: UiQualifiedId UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectDefinition *node)
+{
+ LocationSpan l = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+
+ defineObjectBinding(/*propertyName = */ 0,
+ node->qualifiedTypeNameId,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectBinding *node)
+{
+ LocationSpan l = location(node->qualifiedTypeNameId->identifierToken,
+ node->initializer->rbraceToken);
+
+ defineObjectBinding(node->qualifiedId,
+ node->qualifiedTypeNameId,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+QmlParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr)
+{
+ if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
+ return QmlParser::Variant(lit->value->asString());
+ } else if (expr->kind == AST::Node::Kind_TrueLiteral) {
+ return QmlParser::Variant(true);
+ } else if (expr->kind == AST::Node::Kind_FalseLiteral) {
+ return QmlParser::Variant(false);
+ } else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) {
+ return QmlParser::Variant(lit->value, asString(expr));
+ } else {
+
+ if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
+ if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
+ return QmlParser::Variant(-lit->value, asString(expr));
+ }
+ }
+
+ return QmlParser::Variant(asString(expr), expr);
+ }
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON Statement ;
+bool ProcessAST::visit(AST::UiScriptBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ Property *prop = currentProperty();
+
+ QmlParser::Variant primitive;
+
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) {
+ primitive = getVariant(stmt->expression);
+ } else { // do binding
+ primitive = QmlParser::Variant(asString(node->statement),
+ node->statement);
+ }
+
+ prop->location.range.length = prop->location.range.offset + prop->location.range.length - node->qualifiedId->identifierToken.offset;
+ prop->location.range.offset = node->qualifiedId->identifierToken.offset;
+ Value *v = new Value;
+ v->value = primitive;
+ v->location = location(node->statement->firstSourceLocation(),
+ node->statement->lastSourceLocation());
+
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return true;
+}
+
+static QList<int> collectCommas(AST::UiArrayMemberList *members)
+{
+ QList<int> commas;
+
+ if (members) {
+ for (AST::UiArrayMemberList *it = members->next; it; it = it->next) {
+ commas.append(it->commaToken.offset);
+ }
+ }
+
+ return commas;
+}
+
+// UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
+bool ProcessAST::visit(AST::UiArrayBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ accept(node->members);
+
+ // For the DOM, store the position of the T_LBRACKET upto the T_RBRACKET as the range:
+ Property* prop = currentProperty();
+ prop->listValueRange.offset = node->lbracketToken.offset;
+ prop->listValueRange.length = node->rbracketToken.offset + node->rbracketToken.length - node->lbracketToken.offset;
+
+ // Store the positions of the comma token too, again for the DOM to be able to retreive it.
+ prop->listCommaPositions = collectCommas(node->members);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiSourceElement *node)
+{
+ QmlParser::Object *obj = currentObject();
+
+ bool isScript = (obj && obj->typeName == "Script");
+
+ if (!isScript) {
+
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+
+ Object::DynamicSlot slot;
+
+ AST::FormalParameterList *f = funDecl->formals;
+ while (f) {
+ slot.parameterNames << f->name->asString().toUtf8();
+ f = f->finish();
+ }
+
+ QString body = textAt(funDecl->lbraceToken, funDecl->rbraceToken);
+ slot.name = funDecl->name->asString().toUtf8();
+ slot.body = body;
+ obj->dynamicSlots << slot;
+
+ } else {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","QmlJS declaration outside Script element"));
+ error.setLine(node->firstSourceLocation().startLine);
+ error.setColumn(node->firstSourceLocation().startColumn);
+ _parser->_errors << error;
+ }
+ return false;
+
+ } else {
+ QString source;
+
+ int line = 0;
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+ line = funDecl->functionToken.startLine;
+ source = asString(funDecl);
+ } else if (AST::VariableStatement *varStmt = AST::cast<AST::VariableStatement *>(node->sourceElement)) {
+ // ignore variable declarations
+ line = varStmt->declarationKindToken.startLine;
+
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser", "Variable declarations not allow in inline Script blocks"));
+ error.setLine(node->firstSourceLocation().startLine);
+ error.setColumn(node->firstSourceLocation().startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ Value *value = new Value;
+ value->location = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+ value->value = QmlParser::Variant(source);
+
+ obj->getDefaultProperty()->addValue(value);
+ }
+
+ return false;
+}
+
+} // end of anonymous namespace
+
+
+QmlScriptParser::QmlScriptParser()
+: root(0), data(0)
+{
+
+}
+
+QmlScriptParser::~QmlScriptParser()
+{
+ clear();
+}
+
+class QmlScriptParserJsASTData
+{
+public:
+ QmlScriptParserJsASTData(const QString &filename)
+ : nodePool(filename, &engine) {}
+
+ Engine engine;
+ NodePool nodePool;
+};
+
+bool QmlScriptParser::parse(const QByteArray &qmldata, const QUrl &url)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QmlPerfTimer<QmlPerf::QmlParsing> pt;
+#endif
+ clear();
+
+ const QString fileName = url.toString();
+
+ QTextStream stream(qmldata, QIODevice::ReadOnly);
+ stream.setCodec("UTF-8");
+ const QString code = stream.readAll();
+
+ data = new QmlScriptParserJsASTData(fileName);
+
+ Lexer lexer(&data->engine);
+ lexer.setCode(code, /*line = */ 1);
+
+ Parser parser(&data->engine);
+
+ if (! parser.parse() || !_errors.isEmpty()) {
+
+ // Extract errors from the parser
+ foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
+
+ if (m.isWarning())
+ continue;
+
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription(m.message);
+ error.setLine(m.loc.startLine);
+ error.setColumn(m.loc.startColumn);
+ _errors << error;
+
+ }
+ }
+
+ if (_errors.isEmpty()) {
+ ProcessAST process(this);
+ process(code, parser.ast());
+
+ // Set the url for process errors
+ for(int ii = 0; ii < _errors.count(); ++ii)
+ _errors[ii].setUrl(url);
+ }
+
+ return _errors.isEmpty();
+}
+
+QList<QmlScriptParser::TypeReference*> QmlScriptParser::referencedTypes() const
+{
+ return _refTypes;
+}
+
+QList<QUrl> QmlScriptParser::referencedResources() const
+{
+ return _refUrls;
+}
+
+Object *QmlScriptParser::tree() const
+{
+ return root;
+}
+
+QList<QmlScriptParser::Import> QmlScriptParser::imports() const
+{
+ return _imports;
+}
+
+QList<QmlError> QmlScriptParser::errors() const
+{
+ return _errors;
+}
+
+void QmlScriptParser::clear()
+{
+ if (root) {
+ root->release();
+ root = 0;
+ }
+ _imports.clear();
+ qDeleteAll(_refTypes);
+ _refTypes.clear();
+ _errors.clear();
+
+ if (data) {
+ delete data;
+ data = 0;
+ }
+}
+
+QmlScriptParser::TypeReference *QmlScriptParser::findOrCreateType(const QString &name)
+{
+ TypeReference *type = 0;
+ int i = 0;
+ for (; i < _refTypes.size(); ++i) {
+ if (_refTypes.at(i)->name == name) {
+ type = _refTypes.at(i);
+ break;
+ }
+ }
+ if (!type) {
+ type = new TypeReference(i, name);
+ _refTypes.append(type);
+ }
+
+ return type;
+}
+
+void QmlScriptParser::setTree(Object *tree)
+{
+ Q_ASSERT(! root);
+
+ root = tree;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
new file mode 100644
index 0000000..16888aa
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QMLSCRIPTPARSER_P_H
+#define QMLSCRIPTPARSER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlerror.h"
+#include "qmlparser_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QUrl>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QByteArray;
+
+class QmlScriptParserJsASTData;
+class QmlScriptParser
+{
+public:
+ class Import
+ {
+ public:
+ Import() : type(Library) {}
+
+ enum Type { Library, File };
+ Type type;
+
+ QString uri;
+ QString qualifier;
+ QString version;
+
+ QmlParser::LocationSpan location;
+ };
+
+ class TypeReference
+ {
+ public:
+ TypeReference(int typeId, const QString &typeName) : id(typeId), name(typeName) {}
+
+ int id;
+ // type as it has been referenced in Qml
+ QString name;
+ // objects in parse tree referencing the type
+ QList<QmlParser::Object*> refObjects;
+ };
+
+ QmlScriptParser();
+ ~QmlScriptParser();
+
+ bool parse(const QByteArray &data, const QUrl &url = QUrl());
+
+ QList<TypeReference*> referencedTypes() const;
+ QList<QUrl> referencedResources() const;
+
+ QmlParser::Object *tree() const;
+ QList<Import> imports() const;
+
+ void clear();
+
+ QList<QmlError> errors() const;
+
+// ### private:
+ TypeReference *findOrCreateType(const QString &name);
+ void setTree(QmlParser::Object *tree);
+
+ void setScriptFile(const QString &filename) {_scriptFile = filename; }
+ QString scriptFile() const { return _scriptFile; }
+
+// ### private:
+ QList<QmlError> _errors;
+
+ QmlParser::Object *root;
+ QList<Import> _imports;
+ QList<TypeReference*> _refTypes;
+ QList<QUrl> _refUrls;
+ QString _scriptFile;
+ QmlScriptParserJsASTData *data;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSCRIPTPARSER_P_H
diff --git a/src/declarative/qml/qmlscriptstring.cpp b/src/declarative/qml/qmlscriptstring.cpp
new file mode 100644
index 0000000..1ccad53
--- /dev/null
+++ b/src/declarative/qml/qmlscriptstring.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlscriptstring.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlScriptStringPrivate : public QSharedData
+{
+public:
+ QmlScriptStringPrivate() : context(0), scope(0) {}
+
+ QmlContext *context;
+ QObject *scope;
+ QString script;
+};
+
+/*!
+\class QmlScriptString
+\brief The QmlScriptString class encapsulates a script and its context.
+
+The QmlScriptString is used by properties that want to accept a script "assignment" from QML.
+
+Normally, the following code would result in a binding being established for the \c script
+property. If the property had a type of QmlScriptString, the script - \e {console.log(1921)} - itself
+would be passed to the property and it could choose how to handle it.
+
+\code
+MyType {
+ script: console.log(1921)
+}
+\endcode
+*/
+
+/*!
+Construct an empty instance.
+*/
+QmlScriptString::QmlScriptString()
+: d(new QmlScriptStringPrivate)
+{
+}
+
+/*!
+Copy \a other.
+*/
+QmlScriptString::QmlScriptString(const QmlScriptString &other)
+: d(other.d)
+{
+}
+
+/*!
+\internal
+*/
+QmlScriptString::~QmlScriptString()
+{
+}
+
+/*!
+Assign \a other to this.
+*/
+QmlScriptString &QmlScriptString::operator=(const QmlScriptString &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+Return the context for the script.
+*/
+QmlContext *QmlScriptString::context() const
+{
+ return d->context;
+}
+
+/*!
+Sets the \a context for the script.
+*/
+void QmlScriptString::setContext(QmlContext *context)
+{
+ d->context = context;
+}
+
+/*!
+Returns the scope object for the script.
+*/
+QObject *QmlScriptString::scopeObject() const
+{
+ return d->scope;
+}
+
+/*!
+Sets the scope \a object for the script.
+*/
+void QmlScriptString::setScopeObject(QObject *object)
+{
+ d->scope = object;
+}
+
+/*!
+Returns the script text.
+*/
+QString QmlScriptString::script() const
+{
+ return d->script;
+}
+
+/*!
+Sets the \a script text.
+*/
+void QmlScriptString::setScript(const QString &script)
+{
+ d->script = script;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlscriptstring.h b/src/declarative/qml/qmlscriptstring.h
new file mode 100644
index 0000000..73a473f
--- /dev/null
+++ b/src/declarative/qml/qmlscriptstring.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSCRIPTSTRING_H
+#define QMLSCRIPTSTRING_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlContext;
+class QmlScriptStringPrivate;
+class Q_DECLARATIVE_EXPORT QmlScriptString
+{
+public:
+ QmlScriptString();
+ QmlScriptString(const QmlScriptString &);
+ ~QmlScriptString();
+
+ QmlScriptString &operator=(const QmlScriptString &);
+
+ QmlContext *context() const;
+ void setContext(QmlContext *);
+
+ QObject *scopeObject() const;
+ void setScopeObject(QObject *);
+
+ QString script() const;
+ void setScript(const QString &);
+
+private:
+ QSharedDataPointer<QmlScriptStringPrivate> d;
+};
+
+Q_DECLARE_METATYPE(QmlScriptString);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSCRIPTSTRING_H
+
diff --git a/src/declarative/qml/qmlsqldatabase.cpp b/src/declarative/qml/qmlsqldatabase.cpp
new file mode 100644
index 0000000..684caa2
--- /dev/null
+++ b/src/declarative/qml/qmlsqldatabase.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlsqldatabase_p.h"
+
+#include "qmlengine.h"
+#include "qmlengine_p.h"
+#include "qmlrefcount_p.h"
+#include "qmlengine_p.h"
+
+#include <QtCore/qobject.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptvalueiterator.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptclasspropertyiterator.h>
+#include <QtSql/qsqldatabase.h>
+#include <QtSql/qsqlquery.h>
+#include <QtSql/qsqlerror.h>
+#include <QtSql/qsqlrecord.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qdebug.h>
+
+Q_DECLARE_METATYPE(QSqlDatabase)
+Q_DECLARE_METATYPE(QSqlQuery)
+
+class QmlSqlQueryScriptClass: public QScriptClass {
+public:
+ QmlSqlQueryScriptClass(QScriptEngine *engine) : QScriptClass(engine)
+ {
+ str_length = engine->toStringHandle(QLatin1String("length"));
+ str_forwardOnly = engine->toStringHandle(QLatin1String("forwardOnly")); // not in HTML5 (an optimization)
+ }
+
+ QueryFlags queryProperty(const QScriptValue &,
+ const QScriptString &name,
+ QueryFlags flags, uint *)
+ {
+ if (flags & HandlesReadAccess) {
+ if (name == str_length) {
+ return HandlesReadAccess;
+ } else if (name == str_forwardOnly) {
+ return flags;
+ }
+ }
+ if (flags & HandlesWriteAccess)
+ if (name == str_forwardOnly)
+ return flags;
+ return 0;
+ }
+
+ QScriptValue property(const QScriptValue &object,
+ const QScriptString &name, uint)
+ {
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
+ if (name == str_length) {
+ int s = query.size();
+ if (s<0) {
+ // Inefficient.
+ if (query.last()) {
+ return query.at()+1;
+ } else {
+ return 0;
+ }
+ } else {
+ return s;
+ }
+ } else if (name == str_forwardOnly) {
+ return query.isForwardOnly();
+ }
+ return engine()->undefinedValue();
+ }
+
+ void setProperty(QScriptValue &object,
+ const QScriptString &name, uint, const QScriptValue & value)
+ {
+ if (name == str_forwardOnly) {
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
+ query.setForwardOnly(value.toBool());
+ }
+ }
+
+ QScriptValue::PropertyFlags propertyFlags(const QScriptValue &/*object*/, const QScriptString &name, uint /*id*/)
+ {
+ if (name == str_length) {
+ return QScriptValue::Undeletable
+ | QScriptValue::SkipInEnumeration;
+ }
+ return QScriptValue::Undeletable;
+ }
+
+private:
+ QScriptString str_length;
+ QScriptString str_forwardOnly;
+};
+
+// If the spec changes to allow iteration, check git history...
+// class QmlSqlQueryScriptClassPropertyIterator : public QScriptClassPropertyIterator
+
+
+
+enum SqlException {
+ UNKNOWN_ERR,
+ DATABASE_ERR,
+ VERSION_ERR,
+ TOO_LARGE_ERR,
+ QUOTA_ERR,
+ SYNTAX_ERR,
+ CONSTRAINT_ERR,
+ TIMEOUT_ERR
+};
+
+static const char* sqlerror[] = {
+ "UNKNOWN_ERR",
+ "DATABASE_ERR",
+ "VERSION_ERR",
+ "TOO_LARGE_ERR",
+ "QUOTA_ERR",
+ "SYNTAX_ERR",
+ "CONSTRAINT_ERR",
+ "TIMEOUT_ERR",
+ 0
+};
+
+#define THROW_SQL(error, desc) \
+{ \
+ QScriptValue errorValue = context->throwError(desc); \
+ errorValue.setProperty(QLatin1String("code"), error); \
+ return errorValue; \
+}
+
+
+static QString databaseFile(const QString& connectionName, QScriptEngine *engine)
+{
+ QmlScriptEngine *qmlengine = static_cast<QmlScriptEngine*>(engine);
+ QString basename = qmlengine->offlineStoragePath
+ + QDir::separator() + QLatin1String("Databases") + QDir::separator();
+ basename += connectionName;
+ return basename;
+}
+
+
+
+static QScriptValue qmlsqldatabase_item(QScriptContext *context, QScriptEngine *engine)
+{
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(context->thisObject().data());
+ int i = context->argument(0).toNumber();
+ if (query.at() == i || query.seek(i)) { // Qt 4.6 doesn't optimize seek(at())
+ QSqlRecord r = query.record();
+ QScriptValue row = engine->newObject();
+ for (int j=0; j<r.count(); ++j) {
+ row.setProperty(r.fieldName(j), QScriptValue(engine,r.value(j).toString()));
+ }
+ return row;
+ }
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlsqldatabase_executeSql_outsidetransaction(QScriptContext *context, QScriptEngine * /*engine*/)
+{
+ THROW_SQL(DATABASE_ERR,QmlEngine::tr("executeSql called outside transaction()"));
+}
+
+static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEngine *engine)
+{
+ QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
+ QString sql = context->argument(0).toString();
+ QSqlQuery query(db);
+ bool err = false;
+
+ QScriptValue result;
+
+ if (query.prepare(sql)) {
+ if (context->argumentCount() > 1) {
+ QScriptValue values = context->argument(1);
+ if (values.isObject()) {
+ for (QScriptValueIterator it(values); it.hasNext();) {
+ it.next();
+ query.bindValue(it.name(),it.value().toVariant());
+ }
+ } else {
+ query.bindValue(0,values.toVariant());
+ }
+ }
+ if (query.exec()) {
+ result = engine->newObject();
+ QmlScriptEngine *qmlengine = static_cast<QmlScriptEngine*>(engine);
+ if (!qmlengine->sqlQueryClass)
+ qmlengine->sqlQueryClass = new QmlSqlQueryScriptClass(engine);
+ QScriptValue rows = engine->newObject(qmlengine->sqlQueryClass);
+ rows.setData(engine->newVariant(qVariantFromValue(query)));
+ rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration);
+ result.setProperty(QLatin1String("rows"),rows);
+ result.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected());
+ result.setProperty(QLatin1String("insertId"),query.lastInsertId().toString());
+ } else {
+ err = true;
+ }
+ } else {
+ err = true;
+ }
+ if (err)
+ THROW_SQL(DATABASE_ERR,query.lastError().text());
+ return result;
+}
+
+static QScriptValue qmlsqldatabase_executeSql_readonly(QScriptContext *context, QScriptEngine *engine)
+{
+ QString sql = context->argument(0).toString();
+ if (sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) {
+ return qmlsqldatabase_executeSql(context,engine);
+ } else {
+ THROW_SQL(SYNTAX_ERR,QmlEngine::tr("Read-only Transaction"))
+ }
+}
+
+static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScriptEngine *engine)
+{
+ if (context->argumentCount() < 2)
+ return engine->undefinedValue();
+
+ QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
+ QString from_version = context->argument(0).toString();
+ QString to_version = context->argument(1).toString();
+ QScriptValue callback = context->argument(2);
+
+ QScriptValue instance = engine->newObject();
+ instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,1));
+ QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db));
+
+ QString foundvers = context->thisObject().property(QLatin1String("version")).toString();
+ if (from_version!=foundvers) {
+ THROW_SQL(2,QmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(foundvers));
+ return engine->undefinedValue();
+ }
+
+ bool ok = true;
+ if (callback.isFunction()) {
+ ok = false;
+ db.transaction();
+ callback.call(QScriptValue(), QScriptValueList() << tx);
+ if (engine->hasUncaughtException()) {
+ db.rollback();
+ } else {
+ if (!db.commit()) {
+ db.rollback();
+ THROW_SQL(0,QmlEngine::tr("SQL transaction failed"));
+ } else {
+ ok = true;
+ }
+ }
+ }
+
+ if (ok) {
+ context->thisObject().setProperty(QLatin1String("version"), to_version, QScriptValue::ReadOnly);
+ QSettings ini(databaseFile(db.connectionName(),engine)+QLatin1String(".ini"),QSettings::IniFormat);
+ ini.setValue(QLatin1String("Version"), to_version);
+ }
+
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlsqldatabase_transaction_shared(QScriptContext *context, QScriptEngine *engine, bool readOnly)
+{
+ QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
+ QScriptValue callback = context->argument(0);
+ if (!callback.isFunction())
+ THROW_SQL(UNKNOWN_ERR,QmlEngine::tr("transaction: missing callback"));
+
+ QScriptValue instance = engine->newObject();
+ instance.setProperty(QLatin1String("executeSql"),
+ engine->newFunction(readOnly ? qmlsqldatabase_executeSql_readonly : qmlsqldatabase_executeSql,1));
+ QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db));
+
+ db.transaction();
+ callback.call(QScriptValue(), QScriptValueList() << tx);
+ instance.setProperty(QLatin1String("executeSql"),
+ engine->newFunction(qmlsqldatabase_executeSql_outsidetransaction));
+ if (engine->hasUncaughtException()) {
+ db.rollback();
+ } else {
+ if (!db.commit())
+ db.rollback();
+ }
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlsqldatabase_transaction(QScriptContext *context, QScriptEngine *engine)
+{
+ return qmlsqldatabase_transaction_shared(context,engine,false);
+}
+static QScriptValue qmlsqldatabase_read_transaction(QScriptContext *context, QScriptEngine *engine)
+{
+ return qmlsqldatabase_transaction_shared(context,engine,true);
+}
+
+/*
+ Currently documented in doc/src/declarastive/globalobject.qdoc
+*/
+static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEngine *engine)
+{
+ QSqlDatabase database;
+
+ QString dbname = context->argument(0).toString();
+ QString dbversion = context->argument(1).toString();
+ QString dbdescription = context->argument(2).toString();
+ int dbestimatedsize = context->argument(3).toNumber();
+ QScriptValue dbcreationCallback = context->argument(4);
+
+ QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(dbname.toUtf8());
+ QString dbid(QLatin1String(md5.result().toHex()));
+
+ QString basename = databaseFile(dbid,engine);
+ bool created = false;
+ QString version = dbversion;
+
+ {
+ QSettings ini(basename+QLatin1String(".ini"),QSettings::IniFormat);
+
+ if (QSqlDatabase::connectionNames().contains(dbid)) {
+ database = QSqlDatabase::database(dbid);
+ version = ini.value(QLatin1String("Version")).toString();
+ if (version != dbversion && !dbversion.isEmpty() && !version.isEmpty())
+ THROW_SQL(VERSION_ERR,QmlEngine::tr("SQL: database version mismatch"));
+ } else {
+ created = !QFile::exists(basename+QLatin1String(".sqlite"));
+ database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
+ QDir().mkpath(basename);
+ if (created) {
+ ini.setValue(QLatin1String("Name"), dbname);
+ if (dbcreationCallback.isFunction())
+ version = QString();
+ ini.setValue(QLatin1String("Version"), version);
+ ini.setValue(QLatin1String("Description"), dbdescription);
+ ini.setValue(QLatin1String("EstimatedSize"), dbestimatedsize);
+ ini.setValue(QLatin1String("Driver"), QLatin1String("QSQLITE"));
+ } else {
+ if (!dbversion.isEmpty() && ini.value(QLatin1String("Version")) != dbversion) {
+ // Incompatible
+ THROW_SQL(VERSION_ERR,QmlEngine::tr("SQL: database version mismatch"));
+ }
+ version = ini.value(QLatin1String("Version")).toString();
+ }
+ database.setDatabaseName(basename+QLatin1String(".sqlite"));
+ }
+ if (!database.isOpen())
+ database.open();
+ }
+
+ QScriptValue instance = engine->newObject();
+ instance.setProperty(QLatin1String("transaction"), engine->newFunction(qmlsqldatabase_transaction,1));
+ instance.setProperty(QLatin1String("readTransaction"), engine->newFunction(qmlsqldatabase_read_transaction,1));
+ instance.setProperty(QLatin1String("version"), version, QScriptValue::ReadOnly);
+ instance.setProperty(QLatin1String("changeVersion"), engine->newFunction(qmlsqldatabase_change_version,3));
+
+ QScriptValue result = engine->newVariant(instance,qVariantFromValue(database));
+
+ if (created && dbcreationCallback.isFunction()) {
+ dbcreationCallback.call(QScriptValue(), QScriptValueList() << result);
+ }
+
+ return result;
+}
+
+void qt_add_qmlsqldatabase(QScriptEngine *engine)
+{
+ QScriptValue openDatabase = engine->newFunction(qmlsqldatabase_open_sync, 4);
+ engine->globalObject().setProperty(QLatin1String("openDatabaseSync"), openDatabase);
+
+ QScriptValue sqlExceptionPrototype = engine->newObject();
+ for (int i=0; sqlerror[i]; ++i)
+ sqlExceptionPrototype.setProperty(QLatin1String(sqlerror[i]),
+ i,QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+
+ engine->globalObject().setProperty(QLatin1String("SQLException"), sqlExceptionPrototype);
+}
+
+/*
+HTML5 "spec" says "rs.rows[n]", but WebKit only impelments "rs.rows.item(n)". We do both (and property iterator).
+We add a "forwardOnly" property that stops Qt caching results (code promises to only go forward
+through the data.
+*/
+
diff --git a/src/declarative/qml/qmlsqldatabase_p.h b/src/declarative/qml/qmlsqldatabase_p.h
new file mode 100644
index 0000000..5a38bf0
--- /dev/null
+++ b/src/declarative/qml/qmlsqldatabase_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSQLDATABASE_P_H
+#define QMLSQLDATABASE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+class QScriptEngine;
+void qt_add_qmlsqldatabase(QScriptEngine *engine);
+
+#endif // QMLSQLDATABASE_P_H
+
diff --git a/src/declarative/qml/qmlstringconverters.cpp b/src/declarative/qml/qmlstringconverters.cpp
new file mode 100644
index 0000000..2963ab5
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters.cpp
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlstringconverters_p.h"
+
+#include <QtGui/qcolor.h>
+#include <QtGui/qvector3d.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+static uchar fromHex(const uchar c, const uchar c2)
+{
+ uchar rv = 0;
+ if (c >= '0' && c <= '9')
+ rv += (c - '0') * 16;
+ else if (c >= 'A' && c <= 'F')
+ rv += (c - 'A' + 10) * 16;
+ else if (c >= 'a' && c <= 'f')
+ rv += (c - 'a' + 10) * 16;
+
+ if (c2 >= '0' && c2 <= '9')
+ rv += (c2 - '0');
+ else if (c2 >= 'A' && c2 <= 'F')
+ rv += (c2 - 'A' + 10);
+ else if (c2 >= 'a' && c2 <= 'f')
+ rv += (c2 - 'a' + 10);
+
+ return rv;
+}
+
+static uchar fromHex(const QString &s, int idx)
+{
+ uchar c = s.at(idx).toAscii();
+ uchar c2 = s.at(idx + 1).toAscii();
+ return fromHex(c, c2);
+}
+
+QVariant QmlStringConverters::variantFromString(const QString &s)
+{
+ if (s.isEmpty())
+ return QVariant(s);
+ if (s.startsWith(QLatin1Char('\'')) && s.endsWith(QLatin1Char('\''))) {
+ QString data = s.mid(1, s.length() - 2);
+ return QVariant(data);
+ }
+ bool ok = false;
+ QRectF r = rectFFromString(s, &ok);
+ if (ok) return QVariant(r);
+ QColor c = colorFromString(s, &ok);
+ if (ok) return QVariant(c);
+ QPointF p = pointFFromString(s, &ok);
+ if (ok) return QVariant(p);
+ QSizeF sz = sizeFFromString(s, &ok);
+ if (ok) return QVariant(sz);
+ QVector3D v = vector3DFromString(s, &ok);
+ if (ok) return qVariantFromValue(v);
+
+ return QVariant(s);
+}
+
+QVariant QmlStringConverters::variantFromString(const QString &s, int preferredType, bool *ok)
+{
+ switch (preferredType) {
+ case QMetaType::QColor:
+ return QVariant::fromValue(colorFromString(s, ok));
+ case QMetaType::QDate:
+ return QVariant::fromValue(dateFromString(s, ok));
+ case QMetaType::QTime:
+ return QVariant::fromValue(timeFromString(s, ok));
+ case QMetaType::QDateTime:
+ return QVariant::fromValue(dateTimeFromString(s, ok));
+ case QMetaType::QPointF:
+ return QVariant::fromValue(pointFFromString(s, ok));
+ case QMetaType::QPoint:
+ return QVariant::fromValue(pointFFromString(s, ok).toPoint());
+ case QMetaType::QSizeF:
+ return QVariant::fromValue(sizeFFromString(s, ok));
+ case QMetaType::QSize:
+ return QVariant::fromValue(sizeFFromString(s, ok).toSize());
+ case QMetaType::QRectF:
+ return QVariant::fromValue(rectFFromString(s, ok));
+ case QMetaType::QRect:
+ return QVariant::fromValue(rectFFromString(s, ok).toRect());
+ case QMetaType::QVector3D:
+ return QVariant::fromValue(vector3DFromString(s, ok));
+ default:
+ if (ok) *ok = false;
+ return QVariant();
+ }
+}
+
+QColor QmlStringConverters::colorFromString(const QString &s, bool *ok)
+{
+ if (s.startsWith(QLatin1Char('#')) && s.length() == 9) {
+ uchar a = fromHex(s, 1);
+ uchar r = fromHex(s, 3);
+ uchar g = fromHex(s, 5);
+ uchar b = fromHex(s, 7);
+ if (ok) *ok = true;
+ return QColor(r, g, b, a);
+ } else {
+ QColor rv;
+ if (s.startsWith(QLatin1Char('#')) || QColor::colorNames().contains(s.toLower()))
+ rv = QColor(s);
+ if (ok) *ok = rv.isValid();
+ return rv;
+ }
+}
+
+QDate QmlStringConverters::dateFromString(const QString &s, bool *ok)
+{
+ QDate d = QDate::fromString(s, Qt::ISODate);
+ if (ok) *ok = d.isValid();
+ return d;
+}
+
+QTime QmlStringConverters::timeFromString(const QString &s, bool *ok)
+{
+ QTime t = QTime::fromString(s, Qt::ISODate);
+ if (ok) *ok = t.isValid();
+ return t;
+}
+
+QDateTime QmlStringConverters::dateTimeFromString(const QString &s, bool *ok)
+{
+ QDateTime d = QDateTime::fromString(s, Qt::ISODate);
+ if (ok) *ok = d.isValid();
+ return d;
+}
+
+//expects input of "x,y"
+QPointF QmlStringConverters::pointFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 1) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ bool xGood, yGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1).toDouble(&yGood);
+ if (!xGood || !yGood) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QPointF(xCoord, yCoord);
+}
+
+//expects input of "widthxheight"
+QSizeF QmlStringConverters::sizeFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ bool wGood, hGood;
+ int index = s.indexOf(QLatin1Char('x'));
+ qreal width = s.left(index).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QSizeF(width, height);
+}
+
+//expects input of "x,y,widthxheight" //### use space instead of second comma?
+QRectF QmlStringConverters::rectFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 2 || s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ bool xGood, yGood, wGood, hGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal x = s.left(index).toDouble(&xGood);
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ qreal y = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ index = s.indexOf(QLatin1Char('x'), index2+1);
+ qreal width = s.mid(index2+1, index-index2-1).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!xGood || !yGood || !wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QRectF(x, y, width, height);
+}
+
+//expects input of "x,y,z"
+QVector3D QmlStringConverters::vector3DFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 2) {
+ if (ok)
+ *ok = false;
+ return QVector3D();
+ }
+
+ bool xGood, yGood, zGood;
+ int index = s.indexOf(QLatin1Char(','));
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ qreal zCoord = s.mid(index2+1).toDouble(&zGood);
+ if (!xGood || !yGood || !zGood) {
+ if (ok)
+ *ok = false;
+ return QVector3D();
+ }
+
+ if (ok)
+ *ok = true;
+ return QVector3D(xCoord, yCoord, zCoord);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlstringconverters_p.h b/src/declarative/qml/qmlstringconverters_p.h
new file mode 100644
index 0000000..dfc59ce
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTRINGCONVERTERS_P_H
+#define QMLSTRINGCONVERTERS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+
+class QColor;
+class QPointF;
+class QSizeF;
+class QRectF;
+class QString;
+class QByteArray;
+class QVector3D;
+
+QT_BEGIN_NAMESPACE
+
+// XXX - Bauhaus currently uses these methods which is why they're exported
+namespace QmlStringConverters
+{
+ QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &);
+ QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &, int preferredType, bool *ok = 0);
+
+ QColor Q_DECLARATIVE_EXPORT colorFromString(const QString &, bool *ok = 0);
+ QDate Q_DECLARATIVE_EXPORT dateFromString(const QString &, bool *ok = 0);
+ QTime Q_DECLARATIVE_EXPORT timeFromString(const QString &, bool *ok = 0);
+ QDateTime Q_DECLARATIVE_EXPORT dateTimeFromString(const QString &, bool *ok = 0);
+ QPointF Q_DECLARATIVE_EXPORT pointFFromString(const QString &, bool *ok = 0);
+ QSizeF Q_DECLARATIVE_EXPORT sizeFFromString(const QString &, bool *ok = 0);
+ QRectF Q_DECLARATIVE_EXPORT rectFFromString(const QString &, bool *ok = 0);
+ QVector3D Q_DECLARATIVE_EXPORT vector3DFromString(const QString &, bool *ok = 0);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTRINGCONVERTERS_P_H
diff --git a/src/declarative/qml/qmltypenamecache.cpp b/src/declarative/qml/qmltypenamecache.cpp
new file mode 100644
index 0000000..7e68492
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltypenamecache_p.h"
+
+#include "qmlengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlTypeNameCache::QmlTypeNameCache(QmlEngine *e)
+: QmlCleanup(e), engine(e)
+{
+}
+
+QmlTypeNameCache::~QmlTypeNameCache()
+{
+ clear();
+}
+
+void QmlTypeNameCache::clear()
+{
+ qDeleteAll(stringCache);
+ stringCache.clear();
+ identifierCache.clear();
+ engine = 0;
+}
+
+void QmlTypeNameCache::add(const QString &name, QmlType *type)
+{
+ if (stringCache.contains(name))
+ return;
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ RData *data = new RData;
+ // ### Use typename class
+ data->identifier = ep->objectClass->createPersistentIdentifier(name);
+ data->type = type;
+ stringCache.insert(name, data);
+ identifierCache.insert(data->identifier.identifier, data);
+}
+
+void QmlTypeNameCache::add(const QString &name, QmlTypeNameCache *typeNamespace)
+{
+ if (stringCache.contains(name))
+ return;
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ RData *data = new RData;
+ // ### Use typename class
+ data->identifier = ep->objectClass->createPersistentIdentifier(name);
+ data->typeNamespace = typeNamespace;
+ stringCache.insert(name, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ typeNamespace->addref();
+}
+
+QmlTypeNameCache::Data *QmlTypeNameCache::data(const QString &id) const
+{
+ return stringCache.value(id);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmltypenamecache_p.h b/src/declarative/qml/qmltypenamecache_p.h
new file mode 100644
index 0000000..754399f
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTYPENAMECACHE_P_H
+#define QMLTYPENAMECACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlrefcount_p.h"
+#include "qmlcleanup_p.h"
+
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlTypeNameCache : public QmlRefCount, public QmlCleanup
+{
+public:
+ QmlTypeNameCache(QmlEngine *);
+ virtual ~QmlTypeNameCache();
+
+ struct Data {
+ inline Data();
+ inline ~Data();
+ QmlType *type;
+ QmlTypeNameCache *typeNamespace;
+ };
+
+ void add(const QString &, QmlType *);
+ void add(const QString &, QmlTypeNameCache *);
+
+ Data *data(const QString &) const;
+ inline Data *data(const QScriptDeclarativeClass::Identifier &id) const;
+
+protected:
+ virtual void clear();
+
+private:
+ struct RData : public Data {
+ QScriptDeclarativeClass::PersistentIdentifier identifier;
+ };
+ typedef QHash<QString, RData *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+ QmlEngine *engine;
+};
+
+QmlTypeNameCache::Data::Data()
+: type(0), typeNamespace(0)
+{
+}
+
+QmlTypeNameCache::Data::~Data()
+{
+ if (typeNamespace) typeNamespace->release();
+}
+
+QmlTypeNameCache::Data *QmlTypeNameCache::data(const QScriptDeclarativeClass::Identifier &id) const
+{
+ return identifierCache.value(id);
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLTYPENAMECACHE_P_H
+
diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp
new file mode 100644
index 0000000..14c8652
--- /dev/null
+++ b/src/declarative/qml/qmltypenamescriptclass.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltypenamescriptclass_p.h"
+
+#include "qmlengine_p.h"
+#include "qmltypenamecache_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct TypeNameData : public QScriptDeclarativeClass::Object {
+ TypeNameData(QObject *o, QmlType *t, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(t), typeNamespace(0), mode(m) {}
+ TypeNameData(QObject *o, QmlTypeNameCache *n, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(0), typeNamespace(n), mode(m) {
+ if (typeNamespace) typeNamespace->addref();
+ }
+ ~TypeNameData() {
+ if (typeNamespace) typeNamespace->release();
+ }
+
+ QObject *object;
+ QmlType *type;
+ QmlTypeNameCache *typeNamespace;
+ QmlTypeNameScriptClass::TypeNameMode mode;
+};
+
+QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *bindEngine)
+: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)),
+ engine(bindEngine), object(0), type(0)
+{
+}
+
+QmlTypeNameScriptClass::~QmlTypeNameScriptClass()
+{
+}
+
+QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type, TypeNameMode mode)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type, mode));
+}
+
+QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns, TypeNameMode mode)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns, mode));
+}
+
+QScriptClass::QueryFlags
+QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+
+ TypeNameData *data = (TypeNameData *)obj;
+
+ object = 0;
+ type = 0;
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ if (data->typeNamespace) {
+
+ QmlTypeNameCache::Data *d = data->typeNamespace->data(name);
+ if (d && d->type) {
+ type = d->type;
+ return QScriptClass::HandlesReadAccess;
+ } else {
+ return 0;
+ }
+
+ } else {
+ Q_ASSERT(data->type);
+
+ QString strName = toString(name);
+
+ if (strName.at(0).isUpper()) {
+ // Must be an enum
+ if (data->mode == IncludeEnums) {
+ // ### Optimize
+ QByteArray enumName = strName.toUtf8();
+ const QMetaObject *metaObject = data->type->baseMetaObject();
+ for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
+ QMetaEnum e = metaObject->enumerator(ii);
+ int value = e.keyToValue(enumName.constData());
+ if (value != -1) {
+ enumValue = value;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ }
+ return 0;
+ } else if (data->object) {
+ // Must be an attached property
+ object = qmlAttachedPropertiesObjectById(data->type->index(), data->object);
+ if (!object) return 0;
+ return ep->objectClass->queryProperty(object, name, flags, 0);
+ }
+ }
+
+ return 0;
+}
+
+QmlTypeNameScriptClass::ScriptValue
+QmlTypeNameScriptClass::property(Object *obj, const Identifier &name)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ if (type) {
+ return Value(scriptEngine, newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode));
+ } else if (object) {
+ return ep->objectClass->property(object, name);
+ } else {
+ return Value(scriptEngine, enumValue);
+ }
+}
+
+void QmlTypeNameScriptClass::setProperty(Object *o, const Identifier &n, const QScriptValue &v)
+{
+ Q_ASSERT(object);
+ Q_ASSERT(!type);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h
new file mode 100644
index 0000000..cf8c621
--- /dev/null
+++ b/src/declarative/qml/qmltypenamescriptclass_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTYPENAMESCRIPTCLASS_P_H
+#define QMLTYPENAMESCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+#include "qmlengine_p.h"
+
+#include <QtScript/qscriptclass.h>
+
+#include <private/qmlscriptclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlType;
+class QmlTypeNameCache;
+class QmlTypeNameScriptClass : public QmlScriptClass
+{
+public:
+ QmlTypeNameScriptClass(QmlEngine *);
+ ~QmlTypeNameScriptClass();
+
+ enum TypeNameMode { IncludeEnums, ExcludeEnums };
+ QScriptValue newObject(QObject *, QmlType *, TypeNameMode = IncludeEnums);
+ QScriptValue newObject(QObject *, QmlTypeNameCache *, TypeNameMode = IncludeEnums);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual ScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+
+private:
+ QmlEngine *engine;
+ QObject *object;
+ QmlType *type;
+ quint32 enumValue;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLTYPENAMESCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlvaluetype.cpp b/src/declarative/qml/qmlvaluetype.cpp
new file mode 100644
index 0000000..058fd6e
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetype.cpp
@@ -0,0 +1,636 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvaluetype_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlValueTypeFactory::QmlValueTypeFactory()
+{
+ // ### Optimize
+ for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii)
+ valueTypes[ii] = valueType(ii);
+}
+
+QmlValueTypeFactory::~QmlValueTypeFactory()
+{
+ for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii)
+ delete valueTypes[ii];
+}
+
+QmlValueType *QmlValueTypeFactory::valueType(int t)
+{
+ switch (t) {
+ case QVariant::Point:
+ return new QmlPointValueType;
+ case QVariant::PointF:
+ return new QmlPointFValueType;
+ case QVariant::Size:
+ return new QmlSizeValueType;
+ case QVariant::SizeF:
+ return new QmlSizeFValueType;
+ case QVariant::Rect:
+ return new QmlRectValueType;
+ case QVariant::RectF:
+ return new QmlRectFValueType;
+ case QVariant::Vector3D:
+ return new QmlVector3DValueType;
+ case QVariant::Font:
+ return new QmlFontValueType;
+ default:
+ return 0;
+ }
+}
+
+QmlValueType::QmlValueType(QObject *parent)
+: QObject(parent)
+{
+}
+
+QmlPointFValueType::QmlPointFValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlPointFValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &point, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlPointFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &point, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlPointFValueType::value()
+{
+ return QVariant(point);
+}
+
+void QmlPointFValueType::setValue(QVariant value)
+{
+ point = qvariant_cast<QPointF>(value);
+}
+
+qreal QmlPointFValueType::x() const
+{
+ return point.x();
+}
+
+qreal QmlPointFValueType::y() const
+{
+ return point.y();
+}
+
+void QmlPointFValueType::setX(qreal x)
+{
+ point.setX(x);
+}
+
+void QmlPointFValueType::setY(qreal y)
+{
+ point.setY(y);
+}
+
+QmlPointValueType::QmlPointValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlPointValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &point, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlPointValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &point, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlPointValueType::value()
+{
+ return QVariant(point);
+}
+
+void QmlPointValueType::setValue(QVariant value)
+{
+ point = qvariant_cast<QPoint>(value);
+}
+
+int QmlPointValueType::x() const
+{
+ return point.x();
+}
+
+int QmlPointValueType::y() const
+{
+ return point.y();
+}
+
+void QmlPointValueType::setX(int x)
+{
+ point.setX(x);
+}
+
+void QmlPointValueType::setY(int y)
+{
+ point.setY(y);
+}
+
+QmlSizeFValueType::QmlSizeFValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlSizeFValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &size, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlSizeFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &size, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlSizeFValueType::value()
+{
+ return QVariant(size);
+}
+
+void QmlSizeFValueType::setValue(QVariant value)
+{
+ size = qvariant_cast<QSizeF>(value);
+}
+
+qreal QmlSizeFValueType::width() const
+{
+ return size.width();
+}
+
+qreal QmlSizeFValueType::height() const
+{
+ return size.height();
+}
+
+void QmlSizeFValueType::setWidth(qreal w)
+{
+ size.setWidth(w);
+}
+
+void QmlSizeFValueType::setHeight(qreal h)
+{
+ size.setHeight(h);
+}
+
+QmlSizeValueType::QmlSizeValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlSizeValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &size, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlSizeValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &size, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlSizeValueType::value()
+{
+ return QVariant(size);
+}
+
+void QmlSizeValueType::setValue(QVariant value)
+{
+ size = qvariant_cast<QSize>(value);
+}
+
+int QmlSizeValueType::width() const
+{
+ return size.width();
+}
+
+int QmlSizeValueType::height() const
+{
+ return size.height();
+}
+
+void QmlSizeValueType::setWidth(int w)
+{
+ size.setWidth(w);
+}
+
+void QmlSizeValueType::setHeight(int h)
+{
+ size.setHeight(h);
+}
+
+QmlRectFValueType::QmlRectFValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlRectFValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &rect, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlRectFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &rect, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlRectFValueType::value()
+{
+ return QVariant(rect);
+}
+
+void QmlRectFValueType::setValue(QVariant value)
+{
+ rect = qvariant_cast<QRectF>(value);
+}
+
+qreal QmlRectFValueType::x() const
+{
+ return rect.x();
+}
+
+qreal QmlRectFValueType::y() const
+{
+ return rect.y();
+}
+
+void QmlRectFValueType::setX(qreal x)
+{
+ rect.moveLeft(x);
+}
+
+void QmlRectFValueType::setY(qreal y)
+{
+ rect.moveTop(y);
+}
+
+qreal QmlRectFValueType::width() const
+{
+ return rect.width();
+}
+
+qreal QmlRectFValueType::height() const
+{
+ return rect.height();
+}
+
+void QmlRectFValueType::setWidth(qreal w)
+{
+ rect.setWidth(w);
+}
+
+void QmlRectFValueType::setHeight(qreal h)
+{
+ rect.setHeight(h);
+}
+
+QmlRectValueType::QmlRectValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlRectValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &rect, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlRectValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &rect, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlRectValueType::value()
+{
+ return QVariant(rect);
+}
+
+void QmlRectValueType::setValue(QVariant value)
+{
+ rect = qvariant_cast<QRect>(value);
+}
+
+int QmlRectValueType::x() const
+{
+ return rect.x();
+}
+
+int QmlRectValueType::y() const
+{
+ return rect.y();
+}
+
+void QmlRectValueType::setX(int x)
+{
+ rect.moveLeft(x);
+}
+
+void QmlRectValueType::setY(int y)
+{
+ rect.moveTop(y);
+}
+
+int QmlRectValueType::width() const
+{
+ return rect.width();
+}
+
+int QmlRectValueType::height() const
+{
+ return rect.height();
+}
+
+void QmlRectValueType::setWidth(int w)
+{
+ rect.setWidth(w);
+}
+
+void QmlRectValueType::setHeight(int h)
+{
+ rect.setHeight(h);
+}
+
+QmlVector3DValueType::QmlVector3DValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlVector3DValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &vector, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlVector3DValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &vector, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlVector3DValueType::value()
+{
+ return QVariant(vector);
+}
+
+void QmlVector3DValueType::setValue(QVariant value)
+{
+ vector = qvariant_cast<QVector3D>(value);
+}
+
+qreal QmlVector3DValueType::x() const
+{
+ return vector.x();
+}
+
+qreal QmlVector3DValueType::y() const
+{
+ return vector.y();
+}
+
+qreal QmlVector3DValueType::z() const
+{
+ return vector.z();
+}
+
+void QmlVector3DValueType::setX(qreal x)
+{
+ vector.setX(x);
+}
+
+void QmlVector3DValueType::setY(qreal y)
+{
+ vector.setY(y);
+}
+
+void QmlVector3DValueType::setZ(qreal z)
+{
+ vector.setZ(z);
+}
+
+QmlFontValueType::QmlFontValueType(QObject *parent)
+: QmlValueType(parent), hasPixelSize(false)
+{
+}
+
+void QmlFontValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &font, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlFontValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &font, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlFontValueType::value()
+{
+ return QVariant(font);
+}
+
+void QmlFontValueType::setValue(QVariant value)
+{
+ font = qvariant_cast<QFont>(value);
+}
+
+
+QString QmlFontValueType::family() const
+{
+ return font.family();
+}
+
+void QmlFontValueType::setFamily(const QString &family)
+{
+ font.setFamily(family);
+}
+
+bool QmlFontValueType::bold() const
+{
+ return font.bold();
+}
+
+void QmlFontValueType::setBold(bool b)
+{
+ font.setBold(b);
+}
+
+QmlFontValueType::FontWeight QmlFontValueType::weight() const
+{
+ return (QmlFontValueType::FontWeight)font.weight();
+}
+
+void QmlFontValueType::setWeight(QmlFontValueType::FontWeight w)
+{
+ font.setWeight((QFont::Weight)w);
+}
+
+bool QmlFontValueType::italic() const
+{
+ return font.italic();
+}
+
+void QmlFontValueType::setItalic(bool b)
+{
+ font.setItalic(b);
+}
+
+bool QmlFontValueType::underline() const
+{
+ return font.underline();
+}
+
+void QmlFontValueType::setUnderline(bool b)
+{
+ font.setUnderline(b);
+}
+
+bool QmlFontValueType::overline() const
+{
+ return font.overline();
+}
+
+void QmlFontValueType::setOverline(bool b)
+{
+ font.setOverline(b);
+}
+
+bool QmlFontValueType::strikeout() const
+{
+ return font.strikeOut();
+}
+
+void QmlFontValueType::setStrikeout(bool b)
+{
+ font.setStrikeOut(b);
+}
+
+qreal QmlFontValueType::pointSize() const
+{
+ return font.pointSizeF();
+}
+
+void QmlFontValueType::setPointSize(qreal size)
+{
+ if (hasPixelSize) {
+ qWarning() << "Both point size and pixel size set. Using pixel size.";
+ return;
+ }
+
+ if (size >= 0.0)
+ font.setPointSizeF(size);
+}
+
+int QmlFontValueType::pixelSize() const
+{
+ return font.pixelSize();
+}
+
+void QmlFontValueType::setPixelSize(int size)
+{
+ if (size >=0) {
+ font.setPixelSize(size);
+ hasPixelSize = true;
+ } else {
+ hasPixelSize = false;
+ }
+}
+
+QmlFontValueType::Capitalization QmlFontValueType::capitalization() const
+{
+ return (QmlFontValueType::Capitalization)font.capitalization();
+}
+
+void QmlFontValueType::setCapitalization(QmlFontValueType::Capitalization c)
+{
+ font.setCapitalization((QFont::Capitalization)c);
+}
+
+qreal QmlFontValueType::letterSpacing() const
+{
+ return font.letterSpacing();
+}
+
+void QmlFontValueType::setLetterSpacing(qreal size)
+{
+ font.setLetterSpacing(QFont::PercentageSpacing, size);
+}
+
+qreal QmlFontValueType::wordSpacing() const
+{
+ return font.wordSpacing();
+}
+
+void QmlFontValueType::setWordSpacing(qreal size)
+{
+ font.setWordSpacing(size);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h
new file mode 100644
index 0000000..800edee
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetype_p.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVALUETYPE_P_H
+#define QMLVALUETYPE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlmetaproperty.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qfont.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_DECLARATIVE_EXPORT QmlValueType : public QObject
+{
+ Q_OBJECT
+public:
+ QmlValueType(QObject *parent = 0);
+ virtual void read(QObject *, int) = 0;
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags flags) = 0;
+ virtual QVariant value() = 0;
+ virtual void setValue(QVariant) = 0;
+};
+
+class Q_DECLARATIVE_EXPORT QmlValueTypeFactory
+{
+public:
+ QmlValueTypeFactory();
+ ~QmlValueTypeFactory();
+ static QmlValueType *valueType(int);
+
+ QmlValueType *valueTypes[QVariant::UserType - 1];
+ QmlValueType *operator[](int idx) const { return valueTypes[idx]; }
+};
+
+class Q_AUTOTEST_EXPORT QmlPointFValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_OBJECT
+public:
+ QmlPointFValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal x() const;
+ qreal y() const;
+ void setX(qreal);
+ void setY(qreal);
+
+private:
+ QPointF point;
+};
+
+class Q_AUTOTEST_EXPORT QmlPointValueType : public QmlValueType
+{
+ Q_PROPERTY(int x READ x WRITE setX)
+ Q_PROPERTY(int y READ y WRITE setY)
+ Q_OBJECT
+public:
+ QmlPointValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ int x() const;
+ int y() const;
+ void setX(int);
+ void setY(int);
+
+private:
+ QPoint point;
+};
+
+class Q_AUTOTEST_EXPORT QmlSizeFValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal width READ width WRITE setWidth)
+ Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlSizeFValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal width() const;
+ qreal height() const;
+ void setWidth(qreal);
+ void setHeight(qreal);
+
+private:
+ QSizeF size;
+};
+
+class Q_AUTOTEST_EXPORT QmlSizeValueType : public QmlValueType
+{
+ Q_PROPERTY(int width READ width WRITE setWidth)
+ Q_PROPERTY(int height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlSizeValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ int width() const;
+ int height() const;
+ void setWidth(int);
+ void setHeight(int);
+
+private:
+ QSize size;
+};
+
+class Q_AUTOTEST_EXPORT QmlRectFValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal width READ width WRITE setWidth)
+ Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlRectFValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal x() const;
+ qreal y() const;
+ void setX(qreal);
+ void setY(qreal);
+
+ qreal width() const;
+ qreal height() const;
+ void setWidth(qreal);
+ void setHeight(qreal);
+
+private:
+ QRectF rect;
+};
+
+class Q_AUTOTEST_EXPORT QmlRectValueType : public QmlValueType
+{
+ Q_PROPERTY(int x READ x WRITE setX)
+ Q_PROPERTY(int y READ y WRITE setY)
+ Q_PROPERTY(int width READ width WRITE setWidth)
+ Q_PROPERTY(int height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlRectValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ int x() const;
+ int y() const;
+ void setX(int);
+ void setY(int);
+
+ int width() const;
+ int height() const;
+ void setWidth(int);
+ void setHeight(int);
+
+private:
+ QRect rect;
+};
+
+class Q_AUTOTEST_EXPORT QmlVector3DValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal z READ z WRITE setZ)
+ Q_OBJECT
+public:
+ QmlVector3DValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ void setX(qreal);
+ void setY(qreal);
+ void setZ(qreal);
+
+private:
+ QVector3D vector;
+};
+
+class Q_AUTOTEST_EXPORT QmlFontValueType : public QmlValueType
+{
+ Q_OBJECT
+ Q_ENUMS(FontWeight)
+ Q_ENUMS(Capitalization)
+
+ Q_PROPERTY(QString family READ family WRITE setFamily)
+ Q_PROPERTY(bool bold READ bold WRITE setBold)
+ Q_PROPERTY(FontWeight weight READ weight WRITE setWeight)
+ Q_PROPERTY(bool italic READ italic WRITE setItalic)
+ Q_PROPERTY(bool underline READ underline WRITE setUnderline)
+ Q_PROPERTY(bool overline READ overline WRITE setOverline)
+ Q_PROPERTY(bool strikeout READ strikeout WRITE setStrikeout)
+ Q_PROPERTY(qreal pointSize READ pointSize WRITE setPointSize)
+ Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize)
+ Q_PROPERTY(Capitalization capitalization READ capitalization WRITE setCapitalization)
+ Q_PROPERTY(qreal letterSpacing READ letterSpacing WRITE setLetterSpacing)
+ Q_PROPERTY(qreal wordSpacing READ wordSpacing WRITE setWordSpacing)
+
+public:
+ enum FontWeight { Light = QFont::Light,
+ Normal = QFont::Normal,
+ DemiBold = QFont::DemiBold,
+ Bold = QFont::Bold,
+ Black = QFont::Black };
+ enum Capitalization { MixedCase = QFont::MixedCase,
+ AllUppercase = QFont::AllUppercase,
+ AllLowercase = QFont::AllLowercase,
+ SmallCaps = QFont::SmallCaps,
+ Capitalize = QFont::Capitalize };
+
+ QmlFontValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ QString family() const;
+ void setFamily(const QString &);
+
+ bool bold() const;
+ void setBold(bool b);
+
+ FontWeight weight() const;
+ void setWeight(FontWeight);
+
+ bool italic() const;
+ void setItalic(bool b);
+
+ bool underline() const;
+ void setUnderline(bool b);
+
+ bool overline() const;
+ void setOverline(bool b);
+
+ bool strikeout() const;
+ void setStrikeout(bool b);
+
+ qreal pointSize() const;
+ void setPointSize(qreal size);
+
+ int pixelSize() const;
+ void setPixelSize(int size);
+
+ Capitalization capitalization() const;
+ void setCapitalization(Capitalization);
+
+ qreal letterSpacing() const;
+ void setLetterSpacing(qreal spacing);
+
+ qreal wordSpacing() const;
+ void setWordSpacing(qreal spacing);
+
+private:
+ QFont font;
+ bool hasPixelSize;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVALUETYPE_P_H
diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp
new file mode 100644
index 0000000..5e222a1
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvaluetypescriptclass_p.h"
+
+#include "qmlengine_p.h"
+#include "qmlguard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QmlValueTypeReference : public QScriptDeclarativeClass::Object {
+ QmlValueType *type;
+ QmlGuard<QObject> object;
+ int property;
+};
+
+QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine)
+: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
+{
+}
+
+QmlValueTypeScriptClass::~QmlValueTypeScriptClass()
+{
+}
+
+QScriptValue QmlValueTypeScriptClass::newObject(QObject *object, int coreIndex, QmlValueType *type)
+{
+ QmlValueTypeReference *ref = new QmlValueTypeReference;
+ ref->type = type;
+ ref->object = object;
+ ref->property = coreIndex;
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ return QScriptDeclarativeClass::newObject(scriptEngine, this, ref);
+}
+
+QScriptClass::QueryFlags
+QmlValueTypeScriptClass::queryProperty(Object *obj, const Identifier &name,
+ QScriptClass::QueryFlags)
+{
+ QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj);
+
+ m_lastIndex = -1;
+
+ if (!ref->object)
+ return 0;
+
+ QByteArray propName = toString(name).toUtf8();
+
+ m_lastIndex = ref->type->metaObject()->indexOfProperty(propName.constData());
+ if (m_lastIndex == -1)
+ return 0;
+
+ QMetaProperty prop = ref->object->metaObject()->property(m_lastIndex);
+
+ QScriptClass::QueryFlags rv =
+ QScriptClass::HandlesReadAccess;
+ if (prop.isWritable())
+ rv |= QScriptClass::HandlesWriteAccess;
+
+ return rv;
+}
+
+QmlValueTypeScriptClass::ScriptValue QmlValueTypeScriptClass::property(Object *obj, const Identifier &)
+{
+ QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj);
+
+ QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
+ ref->type->read(ref->object, ref->property);
+ QVariant rv = p.read(ref->type);
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ return Value(scriptEngine, static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv));
+}
+
+void QmlValueTypeScriptClass::setProperty(Object *obj, const Identifier &,
+ const QScriptValue &value)
+{
+ QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj);
+
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+
+ ref->type->read(ref->object, ref->property);
+ QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
+ p.write(ref->type, v);
+ ref->type->write(ref->object, ref->property, 0);
+}
+
+QVariant QmlValueTypeScriptClass::toVariant(Object *obj, bool *ok)
+{
+ QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj);
+
+ if (ok) *ok = true;
+
+ if (ref->object) {
+ ref->type->read(ref->object, ref->property);
+ return ref->type->value();
+ } else {
+ return QVariant();
+ }
+}
+
+QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &value)
+{
+ Q_ASSERT(scriptClass(value) == this);
+
+ return toVariant(object(value), 0);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlvaluetypescriptclass_p.h b/src/declarative/qml/qmlvaluetypescriptclass_p.h
new file mode 100644
index 0000000..09af967
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetypescriptclass_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVALUETYPESCRIPTCLASS_P_H
+#define QMLVALUETYPESCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <private/qmlscriptclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlValueType;
+class QmlValueTypeScriptClass : public QmlScriptClass
+{
+public:
+ QmlValueTypeScriptClass(QmlEngine *);
+ ~QmlValueTypeScriptClass();
+
+ QScriptValue newObject(QObject *object, int coreIndex, QmlValueType *);
+
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ virtual ScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+
+ virtual QVariant toVariant(Object *, bool *ok = 0);
+ QVariant toVariant(const QScriptValue &);
+private:
+ QmlEngine *engine;
+ int m_lastIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVALUETYPESCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
new file mode 100644
index 0000000..e9a0449
--- /dev/null
+++ b/src/declarative/qml/qmlvme.cpp
@@ -0,0 +1,891 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvme_p.h"
+
+#include "qmlcompiler_p.h"
+#include "qmlboundsignal_p.h"
+#include "qmlstringconverters_p.h"
+#include "qmetaobjectbuilder_p.h"
+#include "qmldeclarativedata_p.h"
+#include "qml.h"
+#include "qmlcustomparser_p.h"
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qmlcomponent.h"
+#include "qmlbinding.h"
+#include "qmlengine_p.h"
+#include "qmlcomponent_p.h"
+#include "qmlvmemetaobject_p.h"
+#include "qmlbinding_p.h"
+#include "qmlcontext_p.h"
+#include "qmlcompiledbindings_p.h"
+#include "qmlglobal_p.h"
+#include "qmlscriptstring.h"
+
+#include <qfxperf_p_p.h>
+
+#include <QStack>
+#include <QWidget>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlVME::QmlVME()
+{
+}
+
+#define VME_EXCEPTION(desc) \
+ { \
+ QmlError error; \
+ error.setDescription(desc.trimmed()); \
+ error.setLine(instr.line); \
+ error.setUrl(comp->url); \
+ vmeErrors << error; \
+ break; \
+ }
+
+struct ListInstance
+{
+ ListInstance() {}
+ ListInstance(QList<void *> *q, int t)
+ : type(t), qListInterface(q), qmlListInterface(0) {}
+ ListInstance(QmlPrivate::ListInterface *q, int t)
+ : type(t), qListInterface(0), qmlListInterface(q) {}
+
+ int type;
+ QList<void *> *qListInterface;
+ QmlPrivate::ListInterface *qmlListInterface;
+};
+
+QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledData *comp,
+ int start, int count,
+ const QBitField &bindingSkipList)
+{
+ QmlVMEStack<QObject *> stack;
+
+ if (start == -1) start = 0;
+ if (count == -1) count = comp->bytecode.count();
+
+ return run(stack, ctxt, comp, start, count, bindingSkipList);
+}
+
+void QmlVME::runDeferred(QObject *object)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object);
+
+ if (!data || !data->context || !data->deferredComponent)
+ return;
+
+ QmlContext *ctxt = data->context;
+ QmlCompiledData *comp = data->deferredComponent;
+ int start = data->deferredIdx + 1;
+ int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount;
+ QmlVMEStack<QObject *> stack;
+ stack.push(object);
+
+ run(stack, ctxt, comp, start, count, QBitField());
+}
+
+QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt,
+ QmlCompiledData *comp,
+ int start, int count,
+ const QBitField &bindingSkipList)
+{
+ Q_ASSERT(comp);
+ Q_ASSERT(ctxt);
+ const QList<QmlCompiledData::TypeReference> &types = comp->types;
+ const QList<QString> &primitives = comp->primitives;
+ const QList<QByteArray> &datas = comp->datas;
+ const QList<QmlCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
+ const QList<int> &intData = comp->intData;
+ const QList<float> &floatData = comp->floatData;
+ const QList<QmlPropertyCache *> &propertyCaches = comp->propertyCaches;
+ const QList<QmlParser::Object::ScriptBlock> &scripts = comp->scripts;
+ const QList<QUrl> &urls = comp->urls;
+
+ QmlEnginePrivate::SimpleList<QmlAbstractBinding> bindValues;
+ QmlEnginePrivate::SimpleList<QmlParserStatus> parserStatus;
+
+ QmlVMEStack<ListInstance> qliststack;
+
+ vmeErrors.clear();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine());
+ QmlContextPrivate *cp = (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+
+ int status = -1; //for dbus
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::BypassInterceptor;
+
+ for (int ii = start; !isError() && ii < (start + count); ++ii) {
+ const QmlInstruction &instr = comp->bytecode.at(ii);
+
+ switch(instr.type) {
+ case QmlInstruction::Init:
+ {
+ if (instr.init.bindingsSize)
+ bindValues = QmlEnginePrivate::SimpleList<QmlAbstractBinding>(instr.init.bindingsSize);
+ if (instr.init.parserStatusSize)
+ parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
+ if (instr.init.contextCache != -1)
+ cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
+ if (instr.init.compiledBinding != -1)
+ cp->optimizedBindings = new QmlCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt);
+ }
+ break;
+
+ case QmlInstruction::CreateObject:
+ {
+ QBitField bindings;
+ if (instr.create.bindingBits != -1) {
+ const QByteArray &bits = datas.at(instr.create.bindingBits);
+ bindings = QBitField((const quint32*)bits.constData(),
+ bits.size() * 8);
+ }
+ if (stack.isEmpty())
+ bindings = bindings.united(bindingSkipList);
+
+ QObject *o =
+ types.at(instr.create.type).createInstance(ctxt, bindings);
+ if (!o) {
+ if(types.at(instr.create.type).component)
+ vmeErrors << types.at(instr.create.type).component->errors();
+
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)));
+ }
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(o);
+ Q_ASSERT(ddata);
+ ddata->outerContext = ctxt;
+ ddata->lineNumber = instr.line;
+ ddata->columnNumber = instr.create.column;
+
+ if (instr.create.data != -1) {
+ QmlCustomParser *customParser =
+ types.at(instr.create.type).type->customParser();
+ customParser->setCustomData(o, datas.at(instr.create.data));
+ }
+ if (!stack.isEmpty()) {
+ QObject *parent = stack.top();
+ if (o->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget*>(o);
+ if (parent->isWidgetType()) {
+ QWidget *parentWidget = static_cast<QWidget*>(parent);
+ widget->setParent(parentWidget);
+ } else {
+ // TODO: parent might be a layout
+ }
+ } else {
+ QmlGraphics_setParent_noEvent(o, parent);
+ // o->setParent(parent);
+ }
+ }
+ stack.push(o);
+ }
+ break;
+
+ case QmlInstruction::SetId:
+ {
+ QObject *target = stack.top();
+ cp->setIdProperty(instr.setId.index, target);
+ }
+ break;
+
+
+ case QmlInstruction::SetDefault:
+ {
+ QObject *target = stack.top();
+ ctxt->addDefaultObject(target);
+ }
+ break;
+
+ case QmlInstruction::CreateComponent:
+ {
+ QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top());
+
+ QmlEngine::setContextForObject(qcomp, ctxt);
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(qcomp);
+ Q_ASSERT(ddata);
+ ddata->outerContext = ctxt;
+ ddata->lineNumber = instr.line;
+ ddata->columnNumber = instr.create.column;
+
+ stack.push(qcomp);
+ ii += instr.createComponent.count;
+ }
+ break;
+
+ case QmlInstruction::StoreMetaObject:
+ {
+ QObject *target = stack.top();
+
+ QMetaObject mo;
+ const QByteArray &metadata = datas.at(instr.storeMeta.data);
+ QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
+
+ const QmlVMEMetaData *data =
+ (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
+
+ (void)new QmlVMEMetaObject(target, &mo, data, comp);
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(target, true);
+ if (ddata->propertyCache) ddata->propertyCache->release();
+ ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache);
+ ddata->propertyCache->addref();
+ }
+ break;
+
+ case QmlInstruction::StoreVariant:
+ {
+ QObject *target = stack.top();
+ // XXX - can be more efficient
+ QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value));
+ void *a[] = { &v, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreString:
+ {
+ QObject *target = stack.top();
+ void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreUrl:
+ {
+ QObject *target = stack.top();
+ void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeUrl.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreFloat:
+ {
+ QObject *target = stack.top();
+ float f = instr.storeFloat.value;
+ void *a[] = { &f, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeFloat.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDouble:
+ {
+ QObject *target = stack.top();
+ double d = instr.storeDouble.value;
+ void *a[] = { &d, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDouble.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreBool:
+ {
+ QObject *target = stack.top();
+ void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeBool.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInteger:
+ {
+ QObject *target = stack.top();
+ void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeInteger.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreColor:
+ {
+ QObject *target = stack.top();
+ QColor c = QColor::fromRgba(instr.storeColor.value);
+ void *a[] = { &c, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeColor.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDate:
+ {
+ QObject *target = stack.top();
+ QDate d = QDate::fromJulianDay(instr.storeDate.value);
+ void *a[] = { &d, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDate.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreTime:
+ {
+ QObject *target = stack.top();
+ QTime t;
+ t.setHMS(intData.at(instr.storeTime.valueIndex),
+ intData.at(instr.storeTime.valueIndex+1),
+ intData.at(instr.storeTime.valueIndex+2),
+ intData.at(instr.storeTime.valueIndex+3));
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDateTime:
+ {
+ QObject *target = stack.top();
+ QTime t;
+ t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
+ intData.at(instr.storeDateTime.valueIndex+2),
+ intData.at(instr.storeDateTime.valueIndex+3),
+ intData.at(instr.storeDateTime.valueIndex+4));
+ QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
+ void *a[] = { &dt, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDateTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePoint:
+ {
+ QObject *target = stack.top();
+ QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePointF:
+ {
+ QObject *target = stack.top();
+ QPointF p(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSize:
+ {
+ QObject *target = stack.top();
+ QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSizeF:
+ {
+ QObject *target = stack.top();
+ QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ void *a[] = { &s, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRect:
+ {
+ QObject *target = stack.top();
+ QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3)).toRect();
+ void *a[] = { &r, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRectF:
+ {
+ QObject *target = stack.top();
+ QRectF r(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3));
+ void *a[] = { &r, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreVector3D:
+ {
+ QObject *target = stack.top();
+ QVector3D p(floatData.at(instr.storeVector3D.valueIndex),
+ floatData.at(instr.storeVector3D.valueIndex+1),
+ floatData.at(instr.storeVector3D.valueIndex+2));
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeVector3D.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreObject:
+ {
+ QObject *assignObj = stack.pop();
+ QObject *target = stack.top();
+
+ void *a[] = { (void *)&assignObj, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+
+
+ case QmlInstruction::AssignCustomType:
+ {
+ QObject *target = stack.top();
+ QmlCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
+ const QString &primitive = primitives.at(data.index);
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(data.type);
+ QVariant v = (*converter)(primitive);
+
+ QMetaProperty prop =
+ target->metaObject()->property(instr.assignCustomType.propertyIndex);
+ if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())));
+
+ void *a[] = { (void *)v.data(), 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.assignCustomType.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::AssignSignalObject:
+ {
+ // XXX optimize
+
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+ int sigIdx = instr.assignSignalObject.signal;
+ const QByteArray &pr = datas.at(sigIdx);
+
+ QmlMetaProperty prop(target, QString::fromUtf8(pr));
+ if (prop.type() & QmlMetaProperty::SignalProperty) {
+
+ QMetaMethod method = QmlMetaType::defaultMethod(assign);
+ if (method.signature() == 0)
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())));
+
+ if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())));
+
+ QMetaObject::connect(target, prop.coreIndex(), assign, method.methodIndex());
+
+ } else {
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)));
+ }
+
+
+ }
+ break;
+
+ case QmlInstruction::StoreSignal:
+ {
+ QObject *target = stack.top();
+ // XXX scope
+ QMetaMethod signal =
+ target->metaObject()->method(instr.storeSignal.signalIndex);
+
+ QmlBoundSignal *bs = new QmlBoundSignal(target, signal, target);
+ QmlExpression *expr =
+ new QmlExpression(ctxt, primitives.at(instr.storeSignal.value), target);
+ expr->setSourceLocation(comp->name, instr.line);
+ bs->setExpression(expr);
+ }
+ break;
+
+ case QmlInstruction::StoreScript:
+ {
+ QObject *target = stack.top();
+ cp->addScript(scripts.at(instr.storeScript.value), target);
+ }
+ break;
+
+ case QmlInstruction::StoreScriptString:
+ {
+ QObject *target = stack.top();
+ QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope);
+ QmlScriptString ss;
+ ss.setContext(ctxt);
+ ss.setScopeObject(scope);
+ ss.setScript(primitives.at(instr.storeScriptString.value));
+
+ void *a[] = { &ss, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeScriptString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::BeginObject:
+ {
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
+ parserStatus.append(status);
+ status->d = &parserStatus.values[parserStatus.count - 1];
+
+ status->classBegin();
+ }
+ break;
+
+ case QmlInstruction::StoreBinding:
+ {
+ QObject *target =
+ stack.at(stack.count() - 1 - instr.assignBinding.owner);
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp =
+ QmlMetaPropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt);
+
+ int coreIndex = mp.coreIndex();
+
+ if (stack.count() == 1 && bindingSkipList.testBit(coreIndex))
+ break;
+
+ QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
+ bindValues.append(bind);
+ bind->m_mePtr = &bindValues.values[bindValues.count - 1];
+ bind->setTarget(mp);
+ bind->addToObject(target);
+ }
+ break;
+
+ case QmlInstruction::StoreCompiledBinding:
+ {
+ QObject *target =
+ stack.at(stack.count() - 1 - instr.assignBinding.owner);
+ QObject *scope =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ int property = instr.assignBinding.property;
+ if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
+ break;
+
+ QmlAbstractBinding *binding =
+ cp->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property);
+ bindValues.append(binding);
+ binding->m_mePtr = &bindValues.values[bindValues.count - 1];
+ binding->addToObject(target);
+ }
+ break;
+
+ case QmlInstruction::StoreValueSource:
+ {
+ QObject *obj = stack.pop();
+ QmlPropertyValueSource *vs = reinterpret_cast<QmlPropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue);
+ QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner);
+
+ QmlMetaProperty prop =
+ QmlMetaPropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt);
+ obj->setParent(target);
+ vs->setTarget(prop);
+ }
+ break;
+
+ case QmlInstruction::StoreValueInterceptor:
+ {
+ QObject *obj = stack.pop();
+ QmlPropertyValueInterceptor *vi = reinterpret_cast<QmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue);
+ QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner);
+ QmlMetaProperty prop =
+ QmlMetaPropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt);
+ obj->setParent(target);
+ vi->setTarget(prop);
+ QmlVMEMetaObject *mo = static_cast<QmlVMEMetaObject *>((QMetaObject*)target->metaObject());
+ mo->registerInterceptor(prop.coreIndex(), prop.valueTypeCoreIndex(), vi);
+ }
+ break;
+
+ case QmlInstruction::StoreObjectQmlList:
+ {
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+
+ void *d = (void *)&assign;
+ list.qmlListInterface->append(d);
+ }
+ break;
+
+ case QmlInstruction::StoreObjectQList:
+ {
+ QObject *assign = stack.pop();
+
+ const ListInstance &list = qliststack.top();
+ list.qListInterface->append((void *)assign);
+ }
+ break;
+
+ case QmlInstruction::AssignObjectList:
+ {
+ // This is only used for assigning interfaces
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+
+ int type = list.type;
+
+ void *ptr = 0;
+
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if (iid)
+ ptr = assign->qt_metacast(iid);
+ if (!ptr)
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign object to list"));
+
+
+ if (list.qmlListInterface) {
+ void *d = (void *)&ptr;
+ list.qmlListInterface->append(d);
+ } else {
+ list.qListInterface->append(ptr);
+ }
+ }
+ break;
+
+ case QmlInstruction::StoreVariantObject:
+ {
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ QVariant v = QVariant::fromValue(assign);
+ void *a[] = { &v, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInterface:
+ {
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ int coreIdx = instr.storeObject.propertyIndex;
+ QMetaProperty prop = target->metaObject()->property(coreIdx);
+ int t = prop.userType();
+ const char *iid = QmlMetaType::interfaceIId(t);
+ bool ok = false;
+ if (iid) {
+ void *ptr = assign->qt_metacast(iid);
+ if (ptr) {
+ void *a[] = { &ptr, 0, &status, &flags };
+ QMetaObject::metacall(target,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ ok = true;
+ }
+ }
+
+ if (!ok)
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign object to interface property"));
+ }
+ break;
+
+ case QmlInstruction::FetchAttached:
+ {
+ QObject *target = stack.top();
+
+ QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
+
+ if (!qmlObject)
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Unable to create attached object"));
+
+ stack.push(qmlObject);
+ }
+ break;
+
+ case QmlInstruction::FetchQmlList:
+ {
+ QObject *target = stack.top();
+
+ void *a[1];
+ // We know that QmlList<*> can be converted to
+ // QmlPrivate::ListInterface
+ QmlPrivate::ListInterface *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if (!list)
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign to null list"));
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
+ }
+ break;
+
+ case QmlInstruction::FetchQList:
+ {
+ QObject *target = stack.top();
+
+ void *a[1];
+ // We know that QList<T *>* can be converted to
+ // QList<void *>*
+ QList<void *> *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if (!list)
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign to null list"));
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
+ }
+ break;
+
+ case QmlInstruction::FetchObject:
+ {
+ QObject *target = stack.top();
+
+ QObject *obj = 0;
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = &obj;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+
+ if (!obj)
+ VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())));
+
+ stack.push(obj);
+ }
+ break;
+
+ case QmlInstruction::PopQList:
+ {
+ qliststack.pop();
+ }
+ break;
+
+ case QmlInstruction::Defer:
+ {
+ if (instr.defer.deferCount) {
+ QObject *target = stack.top();
+ QmlDeclarativeData *data =
+ QmlDeclarativeData::get(target, true);
+ comp->addref();
+ data->deferredComponent = comp;
+ data->deferredIdx = ii;
+ ii += instr.defer.deferCount;
+ }
+ }
+ break;
+
+ case QmlInstruction::PopFetchedObject:
+ {
+ stack.pop();
+ }
+ break;
+
+ case QmlInstruction::FetchValueType:
+ {
+ QObject *target = stack.top();
+ QmlValueType *valueHandler =
+ ep->valueTypes[instr.fetchValue.type];
+ valueHandler->read(target, instr.fetchValue.property);
+ stack.push(valueHandler);
+ }
+ break;
+
+ case QmlInstruction::PopValueType:
+ {
+ QmlValueType *valueHandler =
+ static_cast<QmlValueType *>(stack.pop());
+ QObject *target = stack.top();
+ valueHandler->write(target, instr.fetchValue.property, QmlMetaProperty::BypassInterceptor);
+ }
+ break;
+
+ default:
+ qFatal("QmlCompiledData: Internal error - unknown instruction %d", instr.type);
+ break;
+ }
+ }
+
+ if (isError()) {
+ if (!stack.isEmpty()) {
+ delete stack.at(0);
+ }
+
+ QmlEnginePrivate::clear(bindValues);
+ QmlEnginePrivate::clear(parserStatus);
+ return 0;
+ }
+
+ if (bindValues.count)
+ ep->bindValues << bindValues;
+ if (parserStatus.count)
+ ep->parserStatus << parserStatus;
+
+ if (stack.isEmpty())
+ return 0;
+ else
+ return stack.top();
+ return 0;
+}
+
+bool QmlVME::isError() const
+{
+ return !vmeErrors.isEmpty();
+}
+
+QList<QmlError> QmlVME::errors() const
+{
+ return vmeErrors;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h
new file mode 100644
index 0000000..9c45dc1
--- /dev/null
+++ b/src/declarative/qml/qmlvme_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVME_P_H
+#define QMLVME_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlerror.h"
+#include "qbitfield_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStack>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QmlInstruction;
+class QmlCompiledData;
+class QmlCompiledData;
+class QmlContext;
+
+template<typename T, int N = 128>
+class QmlVMEStack {
+public:
+ QmlVMEStack() : index(-1), maxSize(N), data(fixedData) {}
+ ~QmlVMEStack() { if (data != fixedData) qFree(fixedData); }
+
+ bool isEmpty() const { return index == -1; }
+ const T &top() const { return data[index]; }
+ void push(const T &i) { ++index; if (index == maxSize) realloc(); data[index] = i; }
+ const T &pop() { --index; return data[index + 1]; }
+ int count() const { return index + 1; }
+ const T &at(int idx) { return data[idx]; }
+
+private:
+ void realloc() {
+ maxSize += N;
+ if (data != fixedData) {
+ data = (T*)qRealloc(data, maxSize * sizeof(T));
+ } else {
+ data = (T*)qMalloc(maxSize * sizeof(T));
+ }
+ }
+ int index;
+ int maxSize;
+ T *data;
+ T fixedData[N];
+};
+
+class QmlVME
+{
+public:
+ QmlVME();
+
+ QObject *run(QmlContext *, QmlCompiledData *,
+ int start = -1, int count = -1,
+ const QBitField & = QBitField());
+ void runDeferred(QObject *);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+private:
+ QObject *run(QmlVMEStack<QObject *> &, QmlContext *, QmlCompiledData *,
+ int start, int count, const QBitField &);
+ QList<QmlError> vmeErrors;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVME_P_H
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
new file mode 100644
index 0000000..8faa922
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvmemetaobject_p.h"
+
+#include "qml.h"
+#include "qmlrefcount_p.h"
+#include "qmlexpression.h"
+#include "qmlexpression_p.h"
+#include "qmlcontext_p.h"
+
+#include <QColor>
+#include <QDate>
+#include <QtCore/qlist.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj,
+ const QMetaObject *other,
+ const QmlVMEMetaData *meta,
+ QmlCompiledData *cdata)
+: object(obj), compiledData(cdata), ctxt(qmlContext(obj)), metaData(meta), methods(0),
+ parent(0)
+{
+ compiledData->addref();
+
+ *static_cast<QMetaObject *>(this) = *other;
+ this->d.superdata = obj->metaObject();
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+ op->metaObject = this;
+
+ propOffset = QAbstractDynamicMetaObject::propertyOffset();
+ methodOffset = QAbstractDynamicMetaObject::methodOffset();
+
+ data = new QVariant[metaData->propertyCount];
+ aConnected.resize(metaData->aliasCount);
+
+ int list_type = qMetaTypeId<QmlList<QObject*>* >();
+ // ### Optimize
+ for (int ii = 0; ii < metaData->propertyCount; ++ii) {
+ int t = (metaData->propertyData() + ii)->propertyType;
+ if (t == list_type) {
+ listProperties.append(new List(this, ii));
+ data[ii] = QVariant::fromValue((QmlList<QObject *>*)listProperties.last());
+ } else if (t != -1) {
+ data[ii] = QVariant((QVariant::Type)t);
+ }
+ }
+}
+
+QmlVMEMetaObject::~QmlVMEMetaObject()
+{
+ compiledData->release();
+ delete parent;
+ qDeleteAll(listProperties);
+ delete [] data;
+ delete [] methods;
+}
+
+int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
+{
+ int id = _id;
+ if(c == QMetaObject::WriteProperty) {
+ int flags = *reinterpret_cast<int*>(a[3]);
+ if (!(flags & QmlMetaProperty::BypassInterceptor)
+ && !aInterceptors.isEmpty()
+ && aInterceptors.testBit(id)) {
+ QPair<int, QmlPropertyValueInterceptor*> pair = interceptors.value(id);
+ int valueIndex = pair.first;
+ QmlPropertyValueInterceptor *vi = pair.second;
+ int type = property(id).userType();
+
+ if (type != QVariant::Invalid) {
+ if (valueIndex != -1) {
+ QmlEnginePrivate *ep = ctxt?QmlEnginePrivate::get(ctxt->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[type];
+ else valueType = QmlValueTypeFactory::valueType(type);
+ Q_ASSERT(valueType);
+
+ valueType->setValue(QVariant(type, a[0]));
+ QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
+ vi->write(valueProp.read(valueType));
+
+ if (!ep) delete valueType;
+ return -1;
+ } else {
+ vi->write(QVariant(type, a[0]));
+ return -1;
+ }
+ }
+ }
+ }
+ if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
+ if (id >= propOffset) {
+ id -= propOffset;
+
+ if (id < metaData->propertyCount) {
+ int t = (metaData->propertyData() + id)->propertyType;
+ bool needActivate = false;
+
+ if (t == -1) {
+
+ if (c == QMetaObject::ReadProperty) {
+ *reinterpret_cast<QVariant *>(a[0]) = data[id];
+ } else if (c == QMetaObject::WriteProperty) {
+ needActivate =
+ (data[id] != *reinterpret_cast<QVariant *>(a[0]));
+ data[id] = *reinterpret_cast<QVariant *>(a[0]);
+ }
+
+ } else {
+
+ if (c == QMetaObject::ReadProperty) {
+ switch(t) {
+ case QVariant::Int:
+ *reinterpret_cast<int *>(a[0]) = data[id].toInt();
+ break;
+ case QVariant::Bool:
+ *reinterpret_cast<bool *>(a[0]) = data[id].toBool();
+ break;
+ case QVariant::Double:
+ *reinterpret_cast<double *>(a[0]) = data[id].toDouble();
+ break;
+ case QVariant::String:
+ *reinterpret_cast<QString *>(a[0]) = data[id].toString();
+ break;
+ case QVariant::Url:
+ *reinterpret_cast<QUrl *>(a[0]) = data[id].toUrl();
+ break;
+ case QVariant::Color:
+ *reinterpret_cast<QColor *>(a[0]) = data[id].value<QColor>();
+ break;
+ case QVariant::Date:
+ *reinterpret_cast<QDate *>(a[0]) = data[id].toDate();
+ break;
+ case QMetaType::QObjectStar:
+ *reinterpret_cast<QObject **>(a[0]) = data[id].value<QObject*>();
+ break;
+ default:
+ break;
+ }
+ if (t == qMetaTypeId<QmlList<QObject*>* >()) {
+ *reinterpret_cast<QmlList<QObject *> **>(a[0]) = data[id].value<QmlList<QObject*>*>();
+ }
+
+ } else if (c == QMetaObject::WriteProperty) {
+
+ QVariant value = QVariant((QVariant::Type)data[id].type(), a[0]);
+ needActivate = (data[id] != value);
+ data[id] = value;
+ }
+
+ }
+
+ if (c == QMetaObject::WriteProperty && needActivate) {
+ activate(object, methodOffset + id, 0);
+ }
+
+ return -1;
+ }
+
+ id -= metaData->propertyCount;
+
+ if (id < metaData->aliasCount) {
+
+ QmlVMEMetaData::AliasData *d = metaData->aliasData() + id;
+
+ if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty)
+ *reinterpret_cast<void **>(a[0]) = 0;
+
+ if (!ctxt) return -1;
+ QmlContextPrivate *ctxtPriv =
+ (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+
+ QObject *target = ctxtPriv->idValues[d->contextIdx].data();
+ if (!target)
+ return -1;
+
+ if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) {
+ int sigIdx = methodOffset + id + metaData->propertyCount;
+ QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx);
+
+ if (d->propertyIdx != -1) {
+ QMetaProperty prop =
+ target->metaObject()->property(d->propertyIdx);
+ if (prop.hasNotifySignal())
+ QMetaObject::connect(target, prop.notifySignalIndex(),
+ object, sigIdx);
+ }
+ aConnected.setBit(id);
+ }
+
+ if (d->propertyIdx == -1) {
+ *reinterpret_cast<QObject **>(a[0]) = target;
+ return -1;
+ } else {
+ return QMetaObject::metacall(target, c, d->propertyIdx, a);
+ }
+
+ }
+ return -1;
+
+ }
+
+ } else if(c == QMetaObject::InvokeMetaMethod) {
+
+ if (id >= methodOffset) {
+
+ id -= methodOffset;
+ int plainSignals = metaData->signalCount + metaData->propertyCount +
+ metaData->aliasCount;
+ if (id < plainSignals) {
+ QMetaObject::activate(object, _id, a);
+ return -1;
+ }
+
+ id -= plainSignals;
+
+ if (id < metaData->methodCount) {
+ if (!ctxt->engine())
+ return -1; // We can't run the method
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine());
+
+ QScriptValue function = method(id);
+
+ QScriptValueList args;
+ QmlVMEMetaData::MethodData *data = metaData->methodData() + id;
+ if (data->parameterCount) {
+ for (int ii = 0; ii < data->parameterCount; ++ii) {
+ args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]);
+ }
+ }
+ QScriptValue rv = function.call(ep->objectClass->newQObject(object), args);
+
+ if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv);
+
+ return -1;
+ }
+ return -1;
+ }
+ }
+
+ if (parent)
+ return parent->metaCall(c, _id, a);
+ else
+ return object->qt_metacall(c, _id, a);
+}
+
+QScriptValue QmlVMEMetaObject::method(int index)
+{
+ if (!methods)
+ methods = new QScriptValue[metaData->methodCount];
+
+ if (!methods[index].isValid()) {
+ QmlVMEMetaData::MethodData *data = metaData->methodData() + index;
+
+ const QChar *body =
+ (const QChar *)(((const char*)metaData) + data->bodyOffset);
+
+ QString code = QString::fromRawData(body, data->bodyLength);
+
+ // XXX Use QScriptProgram
+ // XXX We should evaluate all methods in a single big script block to
+ // improve the call time between dynamic methods defined on the same
+ // object
+ methods[index] = QmlExpressionPrivate::evalInObjectScope(ctxt, object, code);
+ }
+
+ return methods[index];
+}
+
+void QmlVMEMetaObject::listChanged(int id)
+{
+ activate(object, methodOffset + id, 0);
+}
+
+void QmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor)
+{
+ if (aInterceptors.isEmpty())
+ aInterceptors.resize(propertyCount() + metaData->propertyCount);
+ aInterceptors.setBit(index);
+ interceptors.insert(index, qMakePair(valueIndex, interceptor));
+}
+
+QScriptValue QmlVMEMetaObject::vmeMethod(int index)
+{
+ if (index < methodOffset) {
+ Q_ASSERT(parent);
+ return static_cast<QmlVMEMetaObject *>(parent)->vmeMethod(index);
+ }
+ int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
+ Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+ return method(index - methodOffset - plainSignals);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
new file mode 100644
index 0000000..497d8f6
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVMEMETAOBJECT_P_H
+#define QMLVMEMETAOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qml.h"
+
+#include <QtCore/QMetaObject>
+#include <QtCore/QBitArray>
+#include <QtCore/QPair>
+
+#include <private/qobject_p.h>
+
+#include "qmlguard_p.h"
+#include "qmlcompiler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#define QML_ALIAS_FLAG_PTR 0x00000001
+
+struct QmlVMEMetaData
+{
+ short propertyCount;
+ short aliasCount;
+ short signalCount;
+ short methodCount;
+
+ struct AliasData {
+ int contextIdx;
+ int propertyIdx;
+ int flags;
+ };
+
+ struct PropertyData {
+ int propertyType;
+ };
+
+ struct MethodData {
+ int parameterCount;
+ int bodyOffset;
+ int bodyLength;
+ int scriptProgram;
+ };
+
+ PropertyData *propertyData() const {
+ return (PropertyData *)(((const char *)this) + sizeof(QmlVMEMetaData));
+ }
+
+ AliasData *aliasData() const {
+ return (AliasData *)(propertyData() + propertyCount);
+ }
+
+ MethodData *methodData() const {
+ return (MethodData *)(aliasData() + aliasCount);
+ }
+};
+
+class QmlRefCount;
+class QmlVMEMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlVMEMetaObject(QObject *obj, const QMetaObject *other, const QmlVMEMetaData *data,
+ QmlCompiledData *compiledData);
+ ~QmlVMEMetaObject();
+
+ void registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor);
+ QScriptValue vmeMethod(int index);
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QObject *object;
+ QmlCompiledData *compiledData;
+ QmlGuard<QmlContext> ctxt;
+
+ const QmlVMEMetaData *metaData;
+ int propOffset;
+ int methodOffset;
+
+ QVariant *data;
+ QBitArray aConnected;
+ QBitArray aInterceptors;
+ QHash<int, QPair<int, QmlPropertyValueInterceptor*> > interceptors;
+
+ QScriptValue *methods;
+ QScriptValue method(int);
+
+ QAbstractDynamicMetaObject *parent;
+
+ void listChanged(int);
+ class List : public QmlConcreteList<QObject*>
+ {
+ public:
+ List(QmlVMEMetaObject *p, int propIdx)
+ : parent(p), parentProperty(propIdx) { }
+
+ virtual void append(QObject *v) {
+ QmlConcreteList<QObject*>::append(v);
+ parent->listChanged(parentProperty);
+ }
+ virtual void insert(int i, QObject *v) {
+ QmlConcreteList<QObject*>::insert(i, v);
+ parent->listChanged(parentProperty);
+ }
+ virtual void clear() {
+ QmlConcreteList<QObject*>::clear();
+ parent->listChanged(parentProperty);
+ }
+ virtual void removeAt(int i) {
+ QmlConcreteList<QObject*>::removeAt(i);
+ parent->listChanged(parentProperty);
+ }
+ private:
+ QmlVMEMetaObject *parent;
+ int parentProperty;
+ };
+ QList<List *> listProperties;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVMEMETAOBJECT_P_H
diff --git a/src/declarative/qml/qmlwatcher.cpp b/src/declarative/qml/qmlwatcher.cpp
new file mode 100644
index 0000000..507c11d
--- /dev/null
+++ b/src/declarative/qml/qmlwatcher.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlwatcher_p.h"
+
+#include "qmlexpression.h"
+#include "qmlcontext.h"
+#include "qml.h"
+
+#include <qmldebugservice_p.h>
+
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QmlWatchProxy : public QObject
+{
+ Q_OBJECT
+public:
+ QmlWatchProxy(int id,
+ QObject *object,
+ int debugId,
+ const QMetaProperty &prop,
+ QmlWatcher *parent = 0);
+
+ QmlWatchProxy(int id,
+ QmlExpression *exp,
+ int debugId,
+ QmlWatcher *parent = 0);
+
+public slots:
+ void notifyValueChanged();
+
+private:
+ friend class QmlWatcher;
+ int m_id;
+ QmlWatcher *m_watch;
+ QObject *m_object;
+ int m_debugId;
+ QMetaProperty m_property;
+
+ QmlExpression *m_expr;
+};
+
+QmlWatchProxy::QmlWatchProxy(int id,
+ QmlExpression *exp,
+ int debugId,
+ QmlWatcher *parent)
+: QObject(parent), m_id(id), m_watch(parent), m_object(0), m_debugId(debugId), m_expr(exp)
+{
+ QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(notifyValueChanged()));
+}
+
+QmlWatchProxy::QmlWatchProxy(int id,
+ QObject *object,
+ int debugId,
+ const QMetaProperty &prop,
+ QmlWatcher *parent)
+: QObject(parent), m_id(id), m_watch(parent), m_object(object), m_debugId(debugId), m_property(prop), m_expr(0)
+{
+ static int refreshIdx = -1;
+ if(refreshIdx == -1)
+ refreshIdx = QmlWatchProxy::staticMetaObject.indexOfMethod("notifyValueChanged()");
+
+ if (prop.hasNotifySignal())
+ QMetaObject::connect(m_object, prop.notifySignalIndex(), this, refreshIdx);
+}
+
+void QmlWatchProxy::notifyValueChanged()
+{
+ QVariant v;
+ if (m_expr)
+ v = m_expr->value();
+ else
+ v = m_property.read(m_object);
+
+ emit m_watch->propertyChanged(m_id, m_debugId, m_property, v);
+}
+
+
+QmlWatcher::QmlWatcher(QObject *parent)
+ : QObject(parent)
+{
+}
+
+bool QmlWatcher::addWatch(int id, quint32 debugId)
+{
+ QObject *object = QmlDebugService::objectForId(debugId);
+ if (object) {
+ int propCount = object->metaObject()->propertyCount();
+ for (int ii=0; ii<propCount; ii++)
+ addPropertyWatch(id, object, debugId, object->metaObject()->property(ii));
+ return true;
+ }
+ return false;
+}
+
+bool QmlWatcher::addWatch(int id, quint32 debugId, const QByteArray &property)
+{
+ QObject *object = QmlDebugService::objectForId(debugId);
+ if (object) {
+ int index = object->metaObject()->indexOfProperty(property.constData());
+ if (index >= 0) {
+ addPropertyWatch(id, object, debugId, object->metaObject()->property(index));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QmlWatcher::addWatch(int id, quint32 objectId, const QString &expr)
+{
+ QObject *object = QmlDebugService::objectForId(objectId);
+ QmlContext *context = qmlContext(object);
+ if (context) {
+ QmlExpression *exprObj = new QmlExpression(context, expr, object);
+ QmlWatchProxy *proxy = new QmlWatchProxy(id, exprObj, objectId, this);
+ exprObj->setParent(proxy);
+ m_proxies[id].append(proxy);
+ proxy->notifyValueChanged();
+ return true;
+ }
+ return false;
+}
+
+void QmlWatcher::removeWatch(int id)
+{
+ if (!m_proxies.contains(id))
+ return;
+
+ QList<QPointer<QmlWatchProxy> > proxies = m_proxies.take(id);
+ qDeleteAll(proxies);
+}
+
+void QmlWatcher::addPropertyWatch(int id, QObject *object, quint32 debugId, const QMetaProperty &property)
+{
+ QmlWatchProxy *proxy = new QmlWatchProxy(id, object, debugId, property, this);
+ m_proxies[id].append(proxy);
+
+ proxy->notifyValueChanged();
+}
+
+QT_END_NAMESPACE
+
+#include <qmlwatcher.moc>
diff --git a/src/declarative/qml/qmlwatcher_p.h b/src/declarative/qml/qmlwatcher_p.h
new file mode 100644
index 0000000..5050949
--- /dev/null
+++ b/src/declarative/qml/qmlwatcher_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLWATCHER_P_H
+#define QMLWATCHER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qset.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlWatchProxy;
+class QmlExpression;
+class QmlContext;
+class QMetaProperty;
+
+class QmlWatcher : public QObject
+{
+ Q_OBJECT
+public:
+ QmlWatcher(QObject * = 0);
+
+ bool addWatch(int id, quint32 objectId);
+ bool addWatch(int id, quint32 objectId, const QByteArray &property);
+ bool addWatch(int id, quint32 objectId, const QString &expr);
+
+ void removeWatch(int id);
+
+Q_SIGNALS:
+ void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
+
+private:
+ friend class QmlWatchProxy;
+ void addPropertyWatch(int id, QObject *object, quint32 objectId, const QMetaProperty &property);
+
+ QHash<int, QList<QPointer<QmlWatchProxy> > > m_proxies;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLWATCHER_P_H
diff --git a/src/declarative/qml/qmlworkerscript.cpp b/src/declarative/qml/qmlworkerscript.cpp
new file mode 100644
index 0000000..5e39eaf
--- /dev/null
+++ b/src/declarative/qml/qmlworkerscript.cpp
@@ -0,0 +1,1037 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlworkerscript_p.h"
+
+#include "qmlengine_p.h"
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptengine.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtScript/qscriptvalueiterator.h>
+#include <QtCore/qfile.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtDeclarative/qmlinfo.h>
+#include "qmlnetworkaccessmanagerfactory.h"
+
+QT_BEGIN_NAMESPACE
+
+class WorkerDataEvent : public QEvent
+{
+public:
+ enum Type { WorkerData = QEvent::User };
+
+ WorkerDataEvent(int workerId, const QVariant &data);
+ virtual ~WorkerDataEvent();
+
+ int workerId() const;
+ QVariant data() const;
+
+private:
+ int m_id;
+ QVariant m_data;
+};
+
+class WorkerLoadEvent : public QEvent
+{
+public:
+ enum Type { WorkerLoad = WorkerDataEvent::WorkerData + 1 };
+
+ WorkerLoadEvent(int workerId, const QUrl &url);
+
+ int workerId() const;
+ QUrl url() const;
+
+private:
+ int m_id;
+ QUrl m_url;
+};
+
+class WorkerRemoveEvent : public QEvent
+{
+public:
+ enum Type { WorkerRemove = WorkerLoadEvent::WorkerLoad + 1 };
+
+ WorkerRemoveEvent(int workerId);
+
+ int workerId() const;
+
+private:
+ int m_id;
+};
+
+class QmlWorkerScriptEnginePrivate : public QObject
+{
+public:
+ QmlWorkerScriptEnginePrivate(QmlEngine *eng);
+
+ struct ScriptEngine : public QmlScriptEngine
+ {
+ ScriptEngine(QmlWorkerScriptEnginePrivate *parent) : QmlScriptEngine(0), p(parent), accessManager(0) {}
+ ~ScriptEngine() { delete accessManager; }
+ QmlWorkerScriptEnginePrivate *p;
+ QNetworkAccessManager *accessManager;
+
+ virtual QNetworkAccessManager *networkAccessManager() {
+ if (!accessManager) {
+ if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
+ accessManager = p->qmlengine->networkAccessManagerFactory()->create(this);
+ } else {
+ accessManager = new QNetworkAccessManager(this);
+ }
+ }
+ return accessManager;
+ }
+ };
+ ScriptEngine *workerEngine;
+ static QmlWorkerScriptEnginePrivate *get(QScriptEngine *e) {
+ return static_cast<ScriptEngine *>(e)->p;
+ }
+
+ QmlEngine *qmlengine;
+
+ QMutex m_lock;
+ QWaitCondition m_wait;
+
+ struct WorkerScript {
+ WorkerScript();
+
+ int id;
+ bool initialized;
+ QmlWorkerScript *owner;
+ QScriptValue object;
+
+ QScriptValue callback;
+ };
+
+ QHash<int, WorkerScript *> workers;
+ QScriptValue getWorker(int);
+
+ int m_nextId;
+
+ static QVariant scriptValueToVariant(const QScriptValue &);
+ static QScriptValue variantToScriptValue(const QVariant &, QScriptEngine *);
+
+ static QScriptValue onMessage(QScriptContext *ctxt, QScriptEngine *engine);
+ static QScriptValue sendMessage(QScriptContext *ctxt, QScriptEngine *engine);
+
+protected:
+ virtual bool event(QEvent *);
+
+private:
+ void processMessage(int, const QVariant &);
+ void processLoad(int, const QUrl &);
+};
+
+// Currently this will leak as no-one releases it in the worker thread
+class QmlWorkerListModelAgent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count);
+
+public:
+ QmlWorkerListModelAgent(QmlWorkerListModel *);
+ ~QmlWorkerListModelAgent();
+
+ void addref();
+ void release();
+
+ int count() const;
+
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void remove(int index);
+ Q_INVOKABLE void append(const QScriptValue &);
+ Q_INVOKABLE void insert(int index, const QScriptValue&);
+ Q_INVOKABLE QScriptValue get(int index) const;
+ Q_INVOKABLE void set(int index, const QScriptValue &);
+ Q_INVOKABLE void sync();
+
+ struct VariantRef
+ {
+ VariantRef() : a(0) {}
+ VariantRef(const VariantRef &r) : a(r.a) { if (a) a->addref(); }
+ VariantRef(QmlWorkerListModelAgent *_a) : a(_a) { if (a) a->addref(); }
+ ~VariantRef() { if (a) a->release(); }
+
+ VariantRef &operator=(const VariantRef &o) {
+ if (o.a) o.a->addref();
+ if (a) a->release(); a = o.a;
+ return *this;
+ }
+
+ QmlWorkerListModelAgent *a;
+ };
+protected:
+ virtual bool event(QEvent *);
+
+private:
+ friend class QmlWorkerScriptEnginePrivate;
+ friend class QmlWorkerListModel;
+ QScriptEngine *m_engine;
+
+ struct Change {
+ enum { Inserted, Removed, Moved, Changed } type;
+ int index; // Inserted/Removed/Moved/Changed
+ int count; // Inserted/Removed/Moved/Changed
+ int to; // Moved
+ };
+
+ struct Data {
+ QHash<int, QString> roles;
+ QHash<QString, int> strings;
+ QList<QHash<int, QVariant> > values;
+ QList<Change> changes;
+
+ void clearChange();
+ void insertChange(int index, int count);
+ void removeChange(int index, int count);
+ void changedChange(int index, int count);
+ };
+ Data data;
+
+ struct Sync : public QEvent {
+ Sync() : QEvent(QEvent::User) {}
+ Data data;
+ };
+
+ QAtomicInt m_ref;
+ QmlWorkerListModel *m_model;
+};
+Q_DECLARE_METATYPE(QmlWorkerListModelAgent::VariantRef);
+
+QmlWorkerScriptEnginePrivate::QmlWorkerScriptEnginePrivate(QmlEngine *engine)
+: workerEngine(0), qmlengine(engine), m_nextId(0)
+{
+}
+
+QScriptValue QmlWorkerScriptEnginePrivate::onMessage(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ QmlWorkerScriptEnginePrivate *p = QmlWorkerScriptEnginePrivate::get(engine);
+
+ int id = ctxt->thisObject().data().toVariant().toInt();
+
+ WorkerScript *script = p->workers.value(id);
+ if (!script)
+ return engine->undefinedValue();
+
+ if (ctxt->argumentCount() >= 1)
+ script->callback = ctxt->argument(0);
+
+ return script->callback;
+}
+
+QScriptValue QmlWorkerScriptEnginePrivate::sendMessage(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if (!ctxt->argumentCount())
+ return engine->undefinedValue();
+
+ QmlWorkerScriptEnginePrivate *p = QmlWorkerScriptEnginePrivate::get(engine);
+
+ int id = ctxt->thisObject().data().toVariant().toInt();
+
+ WorkerScript *script = p->workers.value(id);
+ if (!script)
+ return engine->undefinedValue();
+
+ p->m_lock.lock();
+ if (script->owner)
+ QCoreApplication::postEvent(script->owner,
+ new WorkerDataEvent(0, scriptValueToVariant(ctxt->argument(0))));
+ p->m_lock.unlock();
+
+ return engine->undefinedValue();
+}
+
+QScriptValue QmlWorkerScriptEnginePrivate::getWorker(int id)
+{
+ QHash<int, WorkerScript *>::ConstIterator iter = workers.find(id);
+
+ if (iter == workers.end())
+ return workerEngine->nullValue();
+
+ WorkerScript *script = *iter;
+ if (!script->initialized) {
+
+ script->initialized = true;
+ script->object = workerEngine->newObject();
+
+ QScriptValue api = workerEngine->newObject();
+ api.setData(script->id);
+
+ api.setProperty(QLatin1String("onMessage"), workerEngine->newFunction(onMessage),
+ QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ api.setProperty(QLatin1String("sendMessage"), workerEngine->newFunction(sendMessage));
+
+ script->object.setProperty(QLatin1String("WorkerScript"), api);
+ }
+
+ return script->object;
+}
+
+bool QmlWorkerScriptEnginePrivate::event(QEvent *event)
+{
+ if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
+ WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
+ processMessage(workerEvent->workerId(), workerEvent->data());
+ return true;
+ } else if (event->type() == (QEvent::Type)WorkerLoadEvent::WorkerLoad) {
+ WorkerLoadEvent *workerEvent = static_cast<WorkerLoadEvent *>(event);
+ processLoad(workerEvent->workerId(), workerEvent->url());
+ return true;
+ } else {
+ return QObject::event(event);
+ }
+}
+
+void QmlWorkerScriptEnginePrivate::processMessage(int id, const QVariant &data)
+{
+ WorkerScript *script = workers.value(id);
+ if (!script)
+ return;
+
+ if (script->callback.isFunction()) {
+ QScriptValue args = workerEngine->newArray(1);
+ args.setProperty(0, variantToScriptValue(data, workerEngine));
+
+ script->callback.call(script->object, args);
+ }
+}
+
+void QmlWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
+{
+ if (url.isRelative() || url.scheme() != QLatin1String("file"))
+ return;
+
+ QString fileName = url.toLocalFile();
+
+ QFile f(fileName);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QString script = QString::fromUtf8(data);
+
+ QScriptValue activation = getWorker(id);
+
+ QScriptContext *ctxt = workerEngine->pushContext();
+ ctxt->setActivationObject(activation);
+
+ workerEngine->baseUrl = url;
+ workerEngine->evaluate(script);
+
+ workerEngine->popContext();
+ }
+}
+
+QVariant QmlWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value)
+{
+ if (value.isBool()) {
+ return QVariant(value.toBool());
+ } else if (value.isString()) {
+ return QVariant(value.toString());
+ } else if (value.isNumber()) {
+ return QVariant((qreal)value.toNumber());
+ } else if (value.isArray()) {
+ QVariantList list;
+
+ quint32 length = (quint32)value.property(QLatin1String("length")).toNumber();
+
+ for (quint32 ii = 0; ii < length; ++ii) {
+ QVariant v = scriptValueToVariant(ii);
+ list << v;
+ }
+
+ return QVariant(list);
+ } else if (value.isQObject()) {
+ QmlWorkerListModel *lm = qobject_cast<QmlWorkerListModel *>(value.toQObject());
+ if (lm) {
+ QmlWorkerListModelAgent::VariantRef v(lm->agent());
+ return qVariantFromValue(v);
+ } else {
+ // No other QObject's are allowed to be sent
+ return QVariant();
+ }
+ } else if (value.isObject()) {
+ QVariantHash hash;
+
+ QScriptValueIterator iter(value);
+
+ while (iter.hasNext()) {
+ iter.next();
+ hash.insert(iter.name(), scriptValueToVariant(iter.value()));
+ }
+
+ return QVariant(hash);
+ }
+
+ return QVariant();
+
+}
+
+QScriptValue QmlWorkerScriptEnginePrivate::variantToScriptValue(const QVariant &value, QScriptEngine *engine)
+{
+ if (value.userType() == QVariant::Bool) {
+ return QScriptValue(value.toBool());
+ } else if (value.userType() == QVariant::String) {
+ return QScriptValue(value.toString());
+ } else if (value.userType() == QMetaType::QReal) {
+ return QScriptValue(value.toReal());
+ } else if (value.userType() == qMetaTypeId<QmlWorkerListModelAgent::VariantRef>()) {
+ QmlWorkerListModelAgent::VariantRef vr = qvariant_cast<QmlWorkerListModelAgent::VariantRef>(value);
+ if (vr.a->m_engine == 0)
+ vr.a->m_engine = engine;
+ else if (vr.a->m_engine != engine)
+ return engine->nullValue();
+ QScriptValue o = engine->newQObject(vr.a);
+ o.setData(engine->newVariant(value)); // Keeps the agent ref so that it is cleaned up on gc
+ return o;
+ } else if (value.userType() == QMetaType::QVariantList) {
+ QVariantList list = qvariant_cast<QVariantList>(value);
+ QScriptValue rv = engine->newArray(list.count());
+
+ for (quint32 ii = 0; ii < quint32(list.count()); ++ii)
+ rv.setProperty(ii, variantToScriptValue(list.at(ii), engine));
+
+ return rv;
+ } else if (value.userType() == QMetaType::QVariantHash) {
+
+ QVariantHash hash = qvariant_cast<QVariantHash>(value);
+
+ QScriptValue rv = engine->newObject();
+
+ for (QVariantHash::ConstIterator iter = hash.begin(); iter != hash.end(); ++iter)
+ rv.setProperty(iter.key(), variantToScriptValue(iter.value(), engine));
+
+ return rv;
+ } else {
+ return engine->nullValue();
+ }
+}
+
+WorkerDataEvent::WorkerDataEvent(int workerId, const QVariant &data)
+: QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data)
+{
+}
+
+WorkerDataEvent::~WorkerDataEvent()
+{
+}
+
+int WorkerDataEvent::workerId() const
+{
+ return m_id;
+}
+
+QVariant WorkerDataEvent::data() const
+{
+ return m_data;
+}
+
+WorkerLoadEvent::WorkerLoadEvent(int workerId, const QUrl &url)
+: QEvent((QEvent::Type)WorkerLoad), m_id(workerId), m_url(url)
+{
+}
+
+int WorkerLoadEvent::workerId() const
+{
+ return m_id;
+}
+
+QUrl WorkerLoadEvent::url() const
+{
+ return m_url;
+}
+
+WorkerRemoveEvent::WorkerRemoveEvent(int workerId)
+: QEvent((QEvent::Type)WorkerRemove), m_id(workerId)
+{
+}
+
+int WorkerRemoveEvent::workerId() const
+{
+ return m_id;
+}
+
+QmlWorkerScriptEngine::QmlWorkerScriptEngine(QmlEngine *parent)
+: QThread(parent), d(new QmlWorkerScriptEnginePrivate(parent))
+{
+ d->m_lock.lock();
+ start(QThread::LowPriority);
+ d->m_wait.wait(&d->m_lock);
+ d->moveToThread(this);
+ d->m_lock.unlock();
+}
+
+QmlWorkerScriptEngine::~QmlWorkerScriptEngine()
+{
+ qDeleteAll(d->workers);
+ delete d; d = 0;
+}
+
+QmlWorkerScriptEnginePrivate::WorkerScript::WorkerScript()
+: id(-1), initialized(false), owner(0)
+{
+}
+
+int QmlWorkerScriptEngine::registerWorkerScript(QmlWorkerScript *owner)
+{
+ QmlWorkerScriptEnginePrivate::WorkerScript *script = new QmlWorkerScriptEnginePrivate::WorkerScript;
+ script->id = d->m_nextId++;
+ script->owner = owner;
+
+ d->m_lock.lock();
+ d->workers.insert(script->id, script);
+ d->m_lock.unlock();
+
+ return script->id;
+}
+
+void QmlWorkerScriptEngine::removeWorkerScript(int id)
+{
+ QCoreApplication::postEvent(d, new WorkerRemoveEvent(id));
+}
+
+void QmlWorkerScriptEngine::executeUrl(int id, const QUrl &url)
+{
+ QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url));
+}
+
+void QmlWorkerScriptEngine::sendMessage(int id, const QVariant &data)
+{
+ QCoreApplication::postEvent(d, new WorkerDataEvent(id, data));
+}
+
+void QmlWorkerScriptEngine::run()
+{
+ d->m_lock.lock();
+
+ d->workerEngine = new QmlWorkerScriptEnginePrivate::ScriptEngine(d);
+
+ d->m_wait.wakeAll();
+
+ d->m_lock.unlock();
+
+ exec();
+
+ delete d->workerEngine; d->workerEngine = 0;
+}
+
+QmlWorkerScript::QmlWorkerScript(QObject *parent)
+: QObject(parent), m_engine(0), m_scriptId(-1)
+{
+}
+
+QmlWorkerScript::~QmlWorkerScript()
+{
+ if (m_scriptId != -1) m_engine->removeWorkerScript(m_scriptId);
+}
+
+QUrl QmlWorkerScript::source() const
+{
+ return m_source;
+}
+
+void QmlWorkerScript::setSource(const QUrl &source)
+{
+ if (m_source == source)
+ return;
+
+ m_source = source;
+
+ if (m_engine)
+ m_engine->executeUrl(m_scriptId, m_source);
+
+ emit sourceChanged();
+}
+
+void QmlWorkerScript::sendMessage(const QScriptValue &message)
+{
+ if (!m_engine) {
+ qWarning("QmlWorkerScript: Attempt to send message before WorkerScript establishment");
+ return;
+ }
+
+ m_engine->sendMessage(m_scriptId, QmlWorkerScriptEnginePrivate::scriptValueToVariant(message));
+}
+
+void QmlWorkerScript::componentComplete()
+{
+ if (!m_engine) {
+ QmlEngine *engine = qmlEngine(this);
+ if (!engine) {
+ qWarning("QmlWorkerScript: componentComplete() called without qmlEngine() set");
+ return;
+ }
+
+ m_engine = QmlEnginePrivate::get(engine)->getWorkerScriptEngine();
+ m_scriptId = m_engine->registerWorkerScript(this);
+
+ if (m_source.isValid())
+ m_engine->executeUrl(m_scriptId, m_source);
+ }
+}
+
+bool QmlWorkerScript::event(QEvent *event)
+{
+ if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
+ QmlEngine *engine = qmlEngine(this);
+ if (engine) {
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
+ QScriptValue value =
+ QmlWorkerScriptEnginePrivate::variantToScriptValue(workerEvent->data(), scriptEngine);
+ emit message(value);
+ }
+ return true;
+ } else {
+ return QObject::event(event);
+ }
+}
+
+QML_DEFINE_TYPE(Qt, 4, 6, WorkerScript, QmlWorkerScript);
+
+void QmlWorkerListModelAgent::Data::clearChange()
+{
+ changes.clear();
+}
+
+void QmlWorkerListModelAgent::Data::insertChange(int index, int count)
+{
+ Change c = { Change::Inserted, index, count, 0 };
+ changes << c;
+}
+
+void QmlWorkerListModelAgent::Data::removeChange(int index, int count)
+{
+ Change c = { Change::Removed, index, count, 0 };
+ changes << c;
+}
+
+void QmlWorkerListModelAgent::Data::changedChange(int index, int count)
+{
+ Change c = { Change::Changed, index, count, 0 };
+ changes << c;
+}
+
+QmlWorkerListModelAgent::QmlWorkerListModelAgent(QmlWorkerListModel *m)
+: m_engine(0), m_ref(1), m_model(m)
+{
+ data.roles = m_model->m_roles;
+ data.strings = m_model->m_strings;
+ data.values = m_model->m_values;
+}
+
+QmlWorkerListModelAgent::~QmlWorkerListModelAgent()
+{
+}
+
+void QmlWorkerListModelAgent::addref()
+{
+ m_ref.ref();
+}
+
+void QmlWorkerListModelAgent::release()
+{
+ bool del = !m_ref.deref();
+
+ if (del)
+ delete this;
+}
+
+int QmlWorkerListModelAgent::count() const
+{
+ return data.values.count();
+}
+
+void QmlWorkerListModelAgent::clear()
+{
+ data.clearChange();
+ data.removeChange(0, data.values.count());
+ data.values.clear();
+}
+
+void QmlWorkerListModelAgent::remove(int index)
+{
+ if (data.values.count() <= index)
+ return;
+
+ data.values.removeAt(index);
+ data.removeChange(index, 1);
+}
+
+void QmlWorkerListModelAgent::append(const QScriptValue &value)
+{
+ QHash<int, QVariant> row;
+
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ QString name = it.name();
+ QVariant v = it.value().toVariant();
+
+ QHash<QString, int>::Iterator iter = data.strings.find(name);
+ if (iter == data.strings.end()) {
+ int role = data.roles.count();
+ data.roles.insert(role, name);
+ iter = data.strings.insert(name, role);
+ }
+ row.insert(*iter, v);
+ }
+
+ data.values.append(row);
+ data.insertChange(data.values.count() - 1, 1);
+}
+
+void QmlWorkerListModelAgent::insert(int index, const QScriptValue &value)
+{
+ if (index > data.values.count())
+ return;
+
+ QHash<int, QVariant> row;
+
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ QString name = it.name();
+ QVariant v = it.value().toVariant();
+
+ QHash<QString, int>::Iterator iter = data.strings.find(name);
+ if (iter == data.strings.end()) {
+ int role = data.roles.count();
+ data.roles.insert(role, name);
+ iter = data.strings.insert(name, role);
+ }
+ row.insert(*iter, v);
+ }
+
+ data.values.insert(index, row);
+ data.insertChange(index, 1);
+}
+
+void QmlWorkerListModelAgent::set(int index, const QScriptValue &value)
+{
+ if (data.values.count() <= index)
+ return;
+
+ QHash<int, QVariant> row;
+
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ QString name = it.name();
+ QVariant v = it.value().toVariant();
+
+ QHash<QString, int>::Iterator iter = data.strings.find(name);
+ if (iter == data.strings.end()) {
+ int role = data.roles.count();
+ data.roles.insert(role, name);
+ iter = data.strings.insert(name, role);
+ }
+ row.insert(*iter, v);
+ }
+
+ if (data.values.at(index) != row) {
+ data.values[index] = row;
+ data.changedChange(index, 1);
+ }
+}
+
+QScriptValue QmlWorkerListModelAgent::get(int index) const
+{
+ if (data.values.count() <= index)
+ return m_engine->undefinedValue();
+
+ QScriptValue rv = m_engine->newObject();
+
+ QHash<int, QVariant> row = data.values.at(index);
+ for (QHash<int, QVariant>::ConstIterator iter = row.begin(); iter != row.end(); ++iter)
+ rv.setProperty(data.roles.value(iter.key()), qScriptValueFromValue(m_engine, iter.value()));
+
+ return rv;
+}
+
+void QmlWorkerListModelAgent::sync()
+{
+ Sync *s = new Sync;
+ s->data = data;
+ data.changes.clear();
+ QCoreApplication::postEvent(this, s);
+}
+
+bool QmlWorkerListModelAgent::event(QEvent *e)
+{
+ if (e->type() == QEvent::User) {
+ Sync *s = static_cast<Sync *>(e);
+
+ const QList<Change> &changes = s->data.changes;
+
+ if (m_model) {
+ bool cc = m_model->m_values.count() != s->data.values.count();
+
+ m_model->m_roles = s->data.roles;
+ m_model->m_strings = s->data.strings;
+ m_model->m_values = s->data.values;
+
+ for (int ii = 0; ii < changes.count(); ++ii) {
+ const Change &change = changes.at(ii);
+ switch (change.type) {
+ case Change::Inserted:
+ emit m_model->itemsInserted(change.index, change.count);
+ break;
+ case Change::Removed:
+ emit m_model->itemsRemoved(change.index, change.count);
+ break;
+ case Change::Moved:
+ emit m_model->itemsMoved(change.index, change.to, change.count);
+ break;
+ case Change::Changed:
+ emit m_model->itemsMoved(change.index, change.to, change.count);
+ break;
+ }
+ }
+
+ if (cc)
+ emit m_model->countChanged();
+ }
+ }
+
+ return QObject::event(e);
+}
+
+QmlWorkerListModel::QmlWorkerListModel(QObject *parent)
+: QListModelInterface(parent), m_agent(0)
+{
+}
+
+QmlWorkerListModel::~QmlWorkerListModel()
+{
+ if (m_agent) {
+ m_agent->m_model = 0;
+ m_agent->release();
+ }
+}
+
+void QmlWorkerListModel::clear()
+{
+ if (m_agent) {
+ qmlInfo(this) << "List can only be modified from a WorkerScript";
+ return;
+ }
+
+ int count = m_values.count();
+ m_values.clear();
+ if (count) {
+ emit itemsRemoved(0, count);
+ emit countChanged();
+ }
+}
+
+void QmlWorkerListModel::remove(int index)
+{
+ if (m_agent) {
+ qmlInfo(this) << "List can only be modified from a WorkerScript";
+ return;
+ }
+
+ if (m_values.count() <= index)
+ return;
+
+ m_values.removeAt(index);
+ emit itemsRemoved(index, 1);
+ emit countChanged();
+}
+
+void QmlWorkerListModel::append(const QScriptValue &value)
+{
+ if (m_agent) {
+ qmlInfo(this) << "List can only be modified from a WorkerScript";
+ return;
+ }
+
+ QHash<int, QVariant> data;
+
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ QString name = it.name();
+ QVariant v = it.value().toVariant();
+
+ QHash<QString, int>::Iterator iter = m_strings.find(name);
+ if (iter == m_strings.end()) {
+ int role = m_roles.count();
+ m_roles.insert(role, name);
+ iter = m_strings.insert(name, role);
+ }
+ data.insert(*iter, v);
+ }
+
+ m_values.append(data);
+
+ emit itemsInserted(m_values.count() - 1, 1);
+ emit countChanged();
+}
+
+void QmlWorkerListModel::insert(int index, const QScriptValue &value)
+{
+ if (m_agent) {
+ qmlInfo(this) << "List can only be modified from a WorkerScript";
+ return;
+ }
+
+ if (index > m_values.count())
+ return;
+
+ QHash<int, QVariant> data;
+
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ QString name = it.name();
+ QVariant v = it.value().toVariant();
+
+ QHash<QString, int>::Iterator iter = m_strings.find(name);
+ if (iter == m_strings.end()) {
+ int role = m_roles.count();
+ m_roles.insert(role, name);
+ iter = m_strings.insert(name, role);
+ }
+ data.insert(*iter, v);
+ }
+
+ m_values.insert(index, data);
+ emit itemsInserted(index, 1);
+ emit countChanged();
+}
+
+QScriptValue QmlWorkerListModel::get(int index) const
+{
+ QmlEngine *engine = qmlEngine(this);
+ if (!engine || m_values.count() <= index)
+ return QScriptValue();
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QScriptValue rv = scriptEngine->newObject();
+
+ QHash<int, QVariant> data = m_values.at(index);
+ for (QHash<int, QVariant>::ConstIterator iter = data.begin(); iter != data.end(); ++iter)
+ rv.setProperty(m_roles.value(iter.key()), qScriptValueFromValue(scriptEngine, iter.value()));
+
+ return rv;
+}
+
+void QmlWorkerListModel::set(int index, const QScriptValue &value)
+{
+ if (m_agent) {
+ qmlInfo(this) << "List can only be modified from a WorkerScript";
+ return;
+ }
+
+ if (m_values.count() <= index)
+ return;
+
+ QHash<int, QVariant> data;
+
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ QString name = it.name();
+ QVariant v = it.value().toVariant();
+
+ QHash<QString, int>::Iterator iter = m_strings.find(name);
+ if (iter == m_strings.end()) {
+ int role = m_roles.count();
+ m_roles.insert(role, name);
+ iter = m_strings.insert(name, role);
+ }
+ data.insert(*iter, v);
+ }
+
+ if (m_values.at(index) != data) {
+ m_values[index] = data;
+ emit itemsChanged(index, 1, m_roles.keys());
+ }
+}
+
+QmlWorkerListModelAgent *QmlWorkerListModel::agent()
+{
+ if (!m_agent)
+ m_agent = new QmlWorkerListModelAgent(this);
+
+ return m_agent;
+}
+
+QList<int> QmlWorkerListModel::roles() const
+{
+ return m_roles.keys();
+}
+
+QString QmlWorkerListModel::toString(int role) const
+{
+ return m_roles.value(role);
+}
+
+int QmlWorkerListModel::count() const
+{
+ return m_values.count();
+}
+
+QHash<int,QVariant> QmlWorkerListModel::data(int index, const QList<int> &) const
+{
+ if (m_values.count() <= index)
+ return QHash<int, QVariant>();
+ else
+ return m_values.at(index);
+}
+
+QVariant QmlWorkerListModel::data(int index, int role) const
+{
+ if (m_values.count() <= index)
+ return QVariant();
+ else
+ return m_values.at(index).value(role);
+}
+
+QML_DEFINE_TYPE(Qt,4,6,WorkerListModel,QmlWorkerListModel)
+
+#include "qmlworkerscript.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlworkerscript_p.h b/src/declarative/qml/qmlworkerscript_p.h
new file mode 100644
index 0000000..3a29498
--- /dev/null
+++ b/src/declarative/qml/qmlworkerscript_p.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLWORKERSCRIPT_P_H
+#define QMLWORKERSCRIPT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qml.h"
+#include "qmlparserstatus.h"
+#include <private/qlistmodelinterface_p.h>
+
+#include <QtCore/qthread.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlWorkerScript;
+class QmlWorkerScriptEnginePrivate;
+class QmlWorkerScriptEngine : public QThread
+{
+Q_OBJECT
+public:
+ QmlWorkerScriptEngine(QmlEngine *parent = 0);
+ virtual ~QmlWorkerScriptEngine();
+
+ int registerWorkerScript(QmlWorkerScript *);
+ void removeWorkerScript(int);
+ void executeUrl(int, const QUrl &);
+ void sendMessage(int, const QVariant &);
+
+protected:
+ virtual void run();
+
+private:
+ QmlWorkerScriptEnginePrivate *d;
+};
+
+class QmlWorkerScript : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+
+ Q_INTERFACES(QmlParserStatus)
+public:
+ QmlWorkerScript(QObject *parent = 0);
+ virtual ~QmlWorkerScript();
+
+ QUrl source() const;
+ void setSource(const QUrl &);
+
+public slots:
+ void sendMessage(const QScriptValue &);
+
+signals:
+ void sourceChanged();
+ void message(const QScriptValue &messageObject);
+
+protected:
+ virtual void componentComplete();
+ virtual bool event(QEvent *);
+
+private:
+ QmlWorkerScriptEngine *m_engine;
+ int m_scriptId;
+ QUrl m_source;
+};
+
+class QmlWorkerListModelAgent;
+class QmlWorkerListModel : public QListModelInterface
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ QmlWorkerListModel(QObject * = 0);
+ virtual ~QmlWorkerListModel();
+
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void remove(int index);
+ Q_INVOKABLE void append(const QScriptValue &);
+ Q_INVOKABLE void insert(int index, const QScriptValue&);
+ Q_INVOKABLE QScriptValue get(int index) const;
+ Q_INVOKABLE void set(int index, const QScriptValue &);
+
+ QmlWorkerListModelAgent *agent();
+
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+ virtual int count() const;
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual QVariant data(int index, int role) const;
+
+Q_SIGNALS:
+ void countChanged();
+
+private:
+ friend class QmlWorkerListModelAgent;
+
+ QHash<int, QString> m_roles;
+ QHash<QString, int> m_strings;
+ QList<QHash<int, QVariant> > m_values;
+
+ QmlWorkerListModelAgent *m_agent;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlWorkerScript);
+QML_DECLARE_TYPE(QmlWorkerListModel);
+
+#endif // QMLWORKERSCRIPT_P_H
diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp
new file mode 100644
index 0000000..1883d1b
--- /dev/null
+++ b/src/declarative/qml/qmlxmlhttprequest.cpp
@@ -0,0 +1,1627 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlxmlhttprequest_p.h"
+
+#include "qmlengine.h"
+#include "qmlengine_p.h"
+#include "qmlrefcount_p.h"
+#include "qmlengine_p.h"
+#include "qmlexpression_p.h"
+
+#include <QtCore/qobject.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtCore/qxmlstream.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qdebug.h>
+
+// From DOM-Level-3-Core spec
+// http://www.w3.org/TR/DOM-Level-3-Core/core.html
+#define INDEX_SIZE_ERR 1
+#define DOMSTRING_SIZE_ERR 2
+#define HIERARCHY_REQUEST_ERR 3
+#define WRONG_DOCUMENT_ERR 4
+#define INVALID_CHARACTER_ERR 5
+#define NO_DATA_ALLOWED_ERR 6
+#define NO_MODIFICATION_ALLOWED_ERR 7
+#define NOT_FOUND_ERR 8
+#define NOT_SUPPORTED_ERR 9
+#define INUSE_ATTRIBUTE_ERR 10
+#define INVALID_STATE_ERR 11
+#define SYNTAX_ERR 12
+#define INVALID_MODIFICATION_ERR 13
+#define NAMESPACE_ERR 14
+#define INVALID_ACCESS_ERR 15
+#define VALIDATION_ERR 16
+#define TYPE_MISMATCH_ERR 17
+
+#define THROW_DOM(error, desc) \
+{ \
+ QScriptValue errorValue = context->throwError(QLatin1String(desc)); \
+ errorValue.setProperty(QLatin1String("code"), error); \
+ return errorValue; \
+}
+
+#define THROW_SYNTAX(desc) \
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String(desc));
+#define THROW_REFERENCE(desc) \
+ return context->throwError(QScriptContext::ReferenceError, QLatin1String(desc));
+
+#define D(arg) (arg)->release()
+#define A(arg) (arg)->addref()
+
+namespace {
+
+class DocumentImpl;
+class NodeImpl
+{
+public:
+ NodeImpl() : type(Element), document(0), parent(0) {}
+ virtual ~NodeImpl() {
+ for (int ii = 0; ii < children.count(); ++ii)
+ delete children.at(ii);
+ for (int ii = 0; ii < attributes.count(); ++ii)
+ delete attributes.at(ii);
+ }
+
+ // These numbers are copied from the Node IDL definition
+ enum Type {
+ Attr = 2,
+ CDATA = 4,
+ Comment = 8,
+ Document = 9,
+ DocumentFragment = 11,
+ DocumentType = 10,
+ Element = 1,
+ Entity = 6,
+ EntityReference = 5,
+ Notation = 12,
+ ProcessingInstruction = 7,
+ Text = 3
+ };
+ Type type;
+
+ QString namespaceUri;
+ QString name;
+
+ QString data;
+
+ void addref();
+ void release();
+
+ DocumentImpl *document;
+ NodeImpl *parent;
+
+ QList<NodeImpl *> children;
+ QList<NodeImpl *> attributes;
+};
+
+class DocumentImpl : public QmlRefCount, public NodeImpl
+{
+public:
+ DocumentImpl() : root(0) { type = Document; }
+ virtual ~DocumentImpl() {
+ if (root) delete root;
+ }
+
+ QString version;
+ QString encoding;
+ bool isStandalone;
+
+ NodeImpl *root;
+
+ void addref() { QmlRefCount::addref(); }
+ void release() { QmlRefCount::release(); }
+};
+
+class NamedNodeMap
+{
+public:
+ // JS API
+ static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue create(QScriptEngine *, NodeImpl *, QList<NodeImpl *> *);
+
+ NamedNodeMap();
+ NamedNodeMap(const NamedNodeMap &);
+ ~NamedNodeMap();
+ bool isNull();
+
+ NodeImpl *d;
+ QList<NodeImpl *> *list;
+private:
+ NamedNodeMap &operator=(const NamedNodeMap &);
+};
+
+class NamedNodeMapClass : public QScriptClass
+{
+public:
+ NamedNodeMapClass(QScriptEngine *engine) : QScriptClass(engine) {}
+
+ virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+};
+
+class NodeList
+{
+public:
+ // JS API
+ static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue create(QScriptEngine *, NodeImpl *);
+
+ NodeList();
+ NodeList(const NodeList &);
+ ~NodeList();
+ bool isNull();
+
+ NodeImpl *d;
+private:
+ NodeList &operator=(const NodeList &);
+};
+
+class NodeListClass : public QScriptClass
+{
+public:
+ NodeListClass(QScriptEngine *engine) : QScriptClass(engine) {}
+ virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+};
+
+class Node
+{
+public:
+ // JS API
+ static QScriptValue nodeName(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue nodeValue(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue nodeType(QScriptContext *context, QScriptEngine *engine);
+
+ static QScriptValue parentNode(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue childNodes(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue firstChild(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue lastChild(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue previousSibling(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue nextSibling(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue attributes(QScriptContext *context, QScriptEngine *engine);
+
+ //static QScriptValue ownerDocument(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue namespaceURI(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue prefix(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue localName(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue baseURI(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue textContent(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue create(QScriptEngine *, NodeImpl *);
+
+ Node();
+ Node(const Node &o);
+ ~Node();
+ bool isNull() const;
+
+ NodeImpl *d;
+
+private:
+ Node &operator=(const Node &);
+};
+
+class Element : public Node
+{
+public:
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class Attr : public Node
+{
+public:
+ // JS API
+ static QScriptValue name(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue specified(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue value(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue ownerElement(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue schemaTypeInfo(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue isId(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class CharacterData : public Node
+{
+public:
+ // JS API
+ static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class Text : public CharacterData
+{
+public:
+ // JS API
+ static QScriptValue isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue wholeText(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class CDATA : public Text
+{
+public:
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class Document : public Node
+{
+public:
+ // JS API
+ static QScriptValue xmlVersion(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue xmlEncoding(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue xmlStandalone(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue documentElement(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue load(QScriptEngine *engine, const QString &data);
+};
+
+}; // namespace
+
+Q_DECLARE_METATYPE(Node);
+Q_DECLARE_METATYPE(NodeList);
+Q_DECLARE_METATYPE(NamedNodeMap);
+
+void NodeImpl::addref()
+{
+ A(document);
+}
+
+void NodeImpl::release()
+{
+ D(document);
+}
+
+QScriptValue Node::nodeName(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ switch (node.d->type) {
+ case NodeImpl::Document:
+ return QScriptValue(QLatin1String("#document"));
+ case NodeImpl::CDATA:
+ return QScriptValue(QLatin1String("#cdata-section"));
+ case NodeImpl::Text:
+ return QScriptValue(QLatin1String("#text"));
+ default:
+ return QScriptValue(node.d->name);
+ }
+}
+
+QScriptValue Node::nodeValue(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->type == NodeImpl::Document ||
+ node.d->type == NodeImpl::DocumentFragment ||
+ node.d->type == NodeImpl::DocumentType ||
+ node.d->type == NodeImpl::Element ||
+ node.d->type == NodeImpl::Entity ||
+ node.d->type == NodeImpl::EntityReference ||
+ node.d->type == NodeImpl::Notation)
+ return engine->nullValue();
+
+ return QScriptValue(node.d->data);
+}
+
+QScriptValue Node::nodeType(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+ return QScriptValue(node.d->type);
+}
+
+QScriptValue Node::parentNode(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->parent) return Node::create(engine, node.d->parent);
+ else return engine->nullValue();
+}
+
+QScriptValue Node::childNodes(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return NodeList::create(engine, node.d);
+}
+
+QScriptValue Node::firstChild(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->children.isEmpty()) return engine->nullValue();
+ else return Node::create(engine, node.d->children.first());
+}
+
+QScriptValue Node::lastChild(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->children.isEmpty()) return engine->nullValue();
+ else return Node::create(engine, node.d->children.last());
+}
+
+QScriptValue Node::previousSibling(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (!node.d->parent) return engine->nullValue();
+
+ for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
+ if (node.d->parent->children.at(ii) == node.d) {
+ if (ii == 0) return engine->nullValue();
+ else return Node::create(engine, node.d->parent->children.at(ii - 1));
+ }
+ }
+
+ return engine->nullValue();
+}
+
+QScriptValue Node::nextSibling(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (!node.d->parent) return engine->nullValue();
+
+ for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
+ if (node.d->parent->children.at(ii) == node.d) {
+ if ((ii + 1) == node.d->parent->children.count()) return engine->nullValue();
+ else return Node::create(engine, node.d->parent->children.at(ii + 1));
+ }
+ }
+
+ return engine->nullValue();
+}
+
+QScriptValue Node::attributes(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->type != NodeImpl::Element)
+ return engine->nullValue();
+ else
+ return NamedNodeMap::create(engine, node.d, &node.d->attributes);
+}
+
+QScriptValue Node::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+
+ proto.setProperty(QLatin1String("nodeName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("nodeValue"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("nodeType"), engine->newFunction(nodeType), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("parentNode"), engine->newFunction(parentNode), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("childNodes"), engine->newFunction(childNodes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("firstChild"), engine->newFunction(firstChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("lastChild"), engine->newFunction(lastChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("previousSibling"), engine->newFunction(previousSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("nextSibling"), engine->newFunction(nextSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("attributes"), engine->newFunction(attributes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
+{
+ QScriptValue instance = engine->newObject();
+
+ switch (data->type) {
+ case NodeImpl::Attr:
+ instance.setPrototype(Attr::prototype(engine));
+ break;
+ case NodeImpl::Comment:
+ case NodeImpl::Document:
+ case NodeImpl::DocumentFragment:
+ case NodeImpl::DocumentType:
+ case NodeImpl::Entity:
+ case NodeImpl::EntityReference:
+ case NodeImpl::Notation:
+ case NodeImpl::ProcessingInstruction:
+ return QScriptValue();
+ case NodeImpl::CDATA:
+ instance.setPrototype(CDATA::prototype(engine));
+ break;
+ case NodeImpl::Text:
+ instance.setPrototype(Text::prototype(engine));
+ break;
+ case NodeImpl::Element:
+ instance.setPrototype(Element::prototype(engine));
+ break;
+ }
+
+ Node node;
+ node.d = data;
+ if (data) A(data);
+
+ return engine->newVariant(instance, qVariantFromValue(node));
+}
+
+QScriptValue Element::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Node::prototype(engine));
+
+ proto.setProperty(QLatin1String("tagName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Attr::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Node::prototype(engine));
+
+ proto.setProperty(QLatin1String("name"), engine->newFunction(name), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("value"), engine->newFunction(value), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("ownerElement"), engine->newFunction(ownerElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Attr::name(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(node.d->name);
+}
+
+QScriptValue Attr::value(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(node.d->data);
+}
+
+QScriptValue Attr::ownerElement(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return Node::create(engine, node.d->parent);
+}
+
+QScriptValue CharacterData::length(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(node.d->data.length());
+}
+
+QScriptValue CharacterData::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Node::prototype(engine));
+
+ proto.setProperty(QLatin1String("data"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Text::isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return node.d->data.trimmed().isEmpty();
+}
+
+QScriptValue Text::wholeText(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return node.d->data;
+}
+
+QScriptValue Text::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(CharacterData::prototype(engine));
+
+ proto.setProperty(QLatin1String("isElementContentWhitespace"), engine->newFunction(isElementContentWhitespace), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("wholeText"), engine->newFunction(wholeText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue CDATA::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Text::prototype(engine));
+ return proto;
+}
+
+QScriptValue Document::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Node::prototype(engine));
+
+ proto.setProperty(QLatin1String("xmlVersion"), engine->newFunction(xmlVersion), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("xmlEncoding"), engine->newFunction(xmlEncoding), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("xmlStandalone"), engine->newFunction(xmlStandalone), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("documentElement"), engine->newFunction(documentElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Document::load(QScriptEngine *engine, const QString &data)
+{
+ Q_ASSERT(engine);
+
+ DocumentImpl *document = 0;
+ QStack<NodeImpl *> nodeStack;
+
+ QXmlStreamReader reader(data);
+
+ while (!reader.atEnd()) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::NoToken:
+ break;
+ case QXmlStreamReader::Invalid:
+ break;
+ case QXmlStreamReader::StartDocument:
+ Q_ASSERT(!document);
+ document = new DocumentImpl;
+ document->document = document;
+ document->version = reader.documentVersion().toString();
+ document->encoding = reader.documentEncoding().toString();
+ document->isStandalone = reader.isStandaloneDocument();
+ break;
+ case QXmlStreamReader::EndDocument:
+ break;
+ case QXmlStreamReader::StartElement:
+ {
+ Q_ASSERT(document);
+ NodeImpl *node = new NodeImpl;
+ node->document = document;
+ node->namespaceUri = reader.namespaceUri().toString();
+ node->name = reader.name().toString();
+ if (nodeStack.isEmpty()) {
+ document->root = node;
+ } else {
+ node->parent = nodeStack.top();
+ node->parent->children.append(node);
+ }
+ nodeStack.append(node);
+
+ foreach (const QXmlStreamAttribute &a, reader.attributes()) {
+ NodeImpl *attr = new NodeImpl;
+ attr->document = document;
+ attr->type = NodeImpl::Attr;
+ attr->namespaceUri = a.namespaceUri().toString();
+ attr->name = a.name().toString();
+ attr->data = a.value().toString();
+ attr->parent = node;
+ node->attributes.append(attr);
+ }
+ }
+ break;
+ case QXmlStreamReader::EndElement:
+ nodeStack.pop();
+ break;
+ case QXmlStreamReader::Characters:
+ {
+ NodeImpl *node = new NodeImpl;
+ node->document = document;
+ node->type = reader.isCDATA()?NodeImpl::CDATA:NodeImpl::Text;
+ node->parent = nodeStack.top();
+ node->parent->children.append(node);
+ node->data = reader.text().toString();
+ }
+ break;
+ case QXmlStreamReader::Comment:
+ break;
+ case QXmlStreamReader::DTD:
+ break;
+ case QXmlStreamReader::EntityReference:
+ break;
+ case QXmlStreamReader::ProcessingInstruction:
+ break;
+ }
+ }
+
+ if (!document || reader.hasError()) {
+ if (document) D(document);
+ return engine->nullValue();
+ }
+
+ QScriptValue instance = engine->newObject();
+ instance.setPrototype(Document::prototype(engine));
+ Node documentNode;
+ documentNode.d = document;
+ return engine->newVariant(instance, qVariantFromValue(documentNode));
+}
+
+Node::Node()
+: d(0)
+{
+}
+
+Node::Node(const Node &o)
+: d(o.d)
+{
+ if (d) A(d);
+}
+
+Node::~Node()
+{
+ if (d) D(d);
+}
+
+bool Node::isNull() const
+{
+ return d == 0;
+}
+
+QScriptValue NamedNodeMap::length(QScriptContext *context, QScriptEngine *engine)
+{
+ NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(context->thisObject().data());
+ if (map.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(map.list->count());
+}
+
+QScriptValue NamedNodeMap::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+
+ proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<NodeImpl *> *list)
+{
+ QScriptValue instance = engine->newObject();
+ instance.setPrototype(NamedNodeMap::prototype(engine));
+
+ NamedNodeMap map;
+ map.d = data;
+ map.list = list;
+ if (data) A(data);
+
+ instance.setData(engine->newVariant(qVariantFromValue(map)));
+
+ if (!QmlScriptEngine::get(engine)->namedNodeMapClass)
+ QmlScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine);
+
+ instance.setScriptClass(QmlScriptEngine::get(engine)->namedNodeMapClass);
+
+ return instance;
+}
+
+NamedNodeMap::NamedNodeMap()
+: d(0), list(0)
+{
+}
+
+NamedNodeMap::NamedNodeMap(const NamedNodeMap &o)
+: d(o.d), list(o.list)
+{
+ if (d) A(d);
+}
+
+NamedNodeMap::~NamedNodeMap()
+{
+ if (d) D(d);
+}
+
+bool NamedNodeMap::isNull()
+{
+ return d == 0;
+}
+
+QScriptValue NodeList::length(QScriptContext *context, QScriptEngine *engine)
+{
+ NodeList list = qscriptvalue_cast<NodeList>(context->thisObject().data());
+ if (list.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(list.d->children.count());
+}
+
+QScriptValue NodeList::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+
+ proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data)
+{
+ QScriptValue instance = engine->newObject();
+ instance.setPrototype(NodeList::prototype(engine));
+
+ NodeList list;
+ list.d = data;
+ if (data) A(data);
+
+ instance.setData(engine->newVariant(qVariantFromValue(list)));
+
+ if (!QmlScriptEngine::get(engine)->nodeListClass)
+ QmlScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine);
+
+ instance.setScriptClass(QmlScriptEngine::get(engine)->nodeListClass);
+
+ return instance;
+}
+
+NodeList::NodeList()
+: d(0)
+{
+}
+
+NodeList::NodeList(const NodeList &o)
+: d(o.d)
+{
+ if (d) A(d);
+}
+
+NodeList::~NodeList()
+{
+ if (d) D(d);
+}
+
+bool NodeList::isNull()
+{
+ return d == 0;
+}
+
+NamedNodeMapClass::QueryFlags NamedNodeMapClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
+{
+ if (!(flags & HandlesReadAccess))
+ return 0;
+
+ NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
+ Q_ASSERT(!map.isNull());
+
+ bool ok = false;
+ QString nameString = name.toString();
+ uint index = nameString.toUInt(&ok);
+ if (ok) {
+ if ((uint)map.list->count() <= index)
+ return 0;
+
+ *id = index;
+ return HandlesReadAccess;
+ } else {
+ for (int ii = 0; ii < map.list->count(); ++ii) {
+ if (map.list->at(ii) && map.list->at(ii)->name == nameString) {
+ *id = ii;
+ return HandlesReadAccess;
+ }
+ }
+ }
+
+ return 0;
+}
+
+QScriptValue NamedNodeMapClass::property(const QScriptValue &object, const QScriptString &, uint id)
+{
+ NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
+ return Node::create(engine(), map.list->at(id));
+}
+
+NodeListClass::QueryFlags NodeListClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
+{
+ if (!(flags & HandlesReadAccess))
+ return 0;
+
+ bool ok = false;
+ uint index = name.toString().toUInt(&ok);
+ if (!ok)
+ return 0;
+
+ NodeList list = qscriptvalue_cast<NodeList>(object.data());
+ if (list.isNull() || (uint)list.d->children.count() <= index)
+ return 0; // ### I think we're meant to raise an exception
+
+ *id = index;
+ return HandlesReadAccess;
+}
+
+QScriptValue NodeListClass::property(const QScriptValue &object, const QScriptString &, uint id)
+{
+ NodeList list = qscriptvalue_cast<NodeList>(object.data());
+ return Node::create(engine(), list.d->children.at(id));
+}
+
+QScriptValue Document::documentElement(QScriptContext *context, QScriptEngine *engine)
+{
+ Node document = qscriptvalue_cast<Node>(context->thisObject());
+ if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+
+ return Node::create(engine, static_cast<DocumentImpl *>(document.d)->root);
+}
+
+QScriptValue Document::xmlStandalone(QScriptContext *context, QScriptEngine *engine)
+{
+ Node document = qscriptvalue_cast<Node>(context->thisObject());
+ if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+
+ return QScriptValue(static_cast<DocumentImpl *>(document.d)->isStandalone);
+}
+
+QScriptValue Document::xmlVersion(QScriptContext *context, QScriptEngine *engine)
+{
+ Node document = qscriptvalue_cast<Node>(context->thisObject());
+ if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+
+ return QScriptValue(static_cast<DocumentImpl *>(document.d)->version);
+}
+
+QScriptValue Document::xmlEncoding(QScriptContext *context, QScriptEngine *engine)
+{
+ Node document = qscriptvalue_cast<Node>(context->thisObject());
+ if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+
+ return QScriptValue(static_cast<DocumentImpl *>(document.d)->encoding);
+}
+
+class QmlXMLHttpRequest : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Unsent = 0,
+ Opened = 1, HeadersReceived = 2,
+ Loading = 3, Done = 4 };
+
+ QmlXMLHttpRequest(QNetworkAccessManager *manager);
+ virtual ~QmlXMLHttpRequest();
+
+ bool sendFlag() const;
+ bool errorFlag() const;
+ quint32 readyState() const;
+ int replyStatus() const;
+ QString replyStatusText() const;
+
+ QScriptValue open(QScriptValue *me, const QString &, const QUrl &);
+
+ void addHeader(const QString &, const QString &);
+ QString header(const QString &name);
+ QString headers();
+ QScriptValue send(QScriptValue *me, const QByteArray &);
+ QScriptValue abort(QScriptValue *me);
+
+ QString responseBody() const;
+private slots:
+ void downloadProgress(qint64);
+ void error(QNetworkReply::NetworkError);
+ void finished();
+
+private:
+ void requestFromUrl(const QUrl &url);
+
+ State m_state;
+ bool m_errorFlag;
+ bool m_sendFlag;
+ QString m_method;
+ QUrl m_url;
+ QByteArray m_responseEntityBody;
+ QByteArray m_data;
+ int m_redirectCount;
+
+ typedef QPair<QByteArray, QByteArray> HeaderPair;
+ typedef QList<HeaderPair> HeadersList;
+ HeadersList m_headersList;
+ void fillHeadersList();
+
+ QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback)
+
+ QScriptValue dispatchCallback(QScriptValue *me);
+ void printError(const QScriptValue&);
+
+ int m_status;
+ QString m_statusText;
+ QNetworkRequest m_request;
+ QNetworkReply *m_network;
+ void destroyNetwork();
+
+ QNetworkAccessManager *m_nam;
+ QNetworkAccessManager *networkAccessManager() { return m_nam; }
+};
+
+QmlXMLHttpRequest::QmlXMLHttpRequest(QNetworkAccessManager *manager)
+: m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
+ m_redirectCount(0), m_network(0), m_nam(manager)
+{
+}
+
+QmlXMLHttpRequest::~QmlXMLHttpRequest()
+{
+ destroyNetwork();
+}
+
+bool QmlXMLHttpRequest::sendFlag() const
+{
+ return m_sendFlag;
+}
+
+bool QmlXMLHttpRequest::errorFlag() const
+{
+ return m_errorFlag;
+}
+
+quint32 QmlXMLHttpRequest::readyState() const
+{
+ return m_state;
+}
+
+int QmlXMLHttpRequest::replyStatus() const
+{
+ return m_status;
+}
+
+QString QmlXMLHttpRequest::replyStatusText() const
+{
+ return m_statusText;
+}
+
+QScriptValue QmlXMLHttpRequest::open(QScriptValue *me, const QString &method, const QUrl &url)
+{
+ destroyNetwork();
+ m_sendFlag = false;
+ m_errorFlag = false;
+ m_responseEntityBody = QByteArray();
+ m_method = method;
+ m_url = url;
+ m_state = Opened;
+ return dispatchCallback(me);
+}
+
+void QmlXMLHttpRequest::addHeader(const QString &name, const QString &value)
+{
+ QByteArray utfname = name.toUtf8();
+
+ if (m_request.hasRawHeader(utfname)) {
+ m_request.setRawHeader(utfname, m_request.rawHeader(utfname) + ',' + value.toUtf8());
+ } else {
+ m_request.setRawHeader(utfname, value.toUtf8());
+ }
+}
+
+QString QmlXMLHttpRequest::header(const QString &name)
+{
+ QByteArray utfname = name.toLower().toUtf8();
+
+ foreach (const HeaderPair &header, m_headersList) {
+ if (header.first == utfname)
+ return QString::fromUtf8(header.second);
+ }
+ return QString();
+}
+
+QString QmlXMLHttpRequest::headers()
+{
+ QString ret;
+
+ foreach (const HeaderPair &header, m_headersList) {
+ if (ret.length())
+ ret.append(QString::fromUtf8("\r\n"));
+ ret.append(QString::fromUtf8(header.first));
+ ret.append(QString::fromUtf8(": "));
+ ret.append(QString::fromUtf8(header.second));
+ }
+ return ret;
+}
+
+void QmlXMLHttpRequest::fillHeadersList()
+{
+ QList<QByteArray> headerList = m_network->rawHeaderList();
+
+ m_headersList.clear();
+ foreach (const QByteArray &header, headerList) {
+ HeaderPair pair (header.toLower(), m_network->rawHeader(header));
+ if (pair.first == "set-cookie" ||
+ pair.first == "set-cookie2")
+ continue;
+
+ m_headersList << pair;
+ }
+}
+
+void QmlXMLHttpRequest::requestFromUrl(const QUrl &url)
+{
+ QNetworkRequest request = m_request;
+ request.setUrl(url);
+ if(m_method == QLatin1String("POST") ||
+ m_method == QLatin1String("PUT")) {
+ QVariant var = request.header(QNetworkRequest::ContentTypeHeader);
+ if (var.isValid()) {
+ QString str = var.toString();
+ int charsetIdx = str.indexOf(QLatin1String("charset="));
+ if (charsetIdx == -1) {
+ // No charset - append
+ if (!str.isEmpty()) str.append(QLatin1Char(';'));
+ str.append(QLatin1String("charset=UTF-8"));
+ } else {
+ charsetIdx += 8;
+ int n = 0;
+ int semiColon = str.indexOf(QLatin1Char(';'), charsetIdx);
+ if (semiColon == -1) {
+ n = str.length() - charsetIdx;
+ } else {
+ n = semiColon - charsetIdx;
+ }
+
+ str.replace(charsetIdx, n, QLatin1String("UTF-8"));
+ }
+ request.setHeader(QNetworkRequest::ContentTypeHeader, str);
+ } else {
+ request.setHeader(QNetworkRequest::ContentTypeHeader,
+ QLatin1String("text/plain;charset=UTF-8"));
+ }
+ }
+
+ if (m_method == QLatin1String("GET"))
+ m_network = networkAccessManager()->get(request);
+ else if (m_method == QLatin1String("HEAD"))
+ m_network = networkAccessManager()->head(request);
+ else if(m_method == QLatin1String("POST"))
+ m_network = networkAccessManager()->post(request, m_data);
+ else if(m_method == QLatin1String("PUT"))
+ m_network = networkAccessManager()->put(request, m_data);
+
+ QObject::connect(m_network, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(downloadProgress(qint64)));
+ QObject::connect(m_network, SIGNAL(error(QNetworkReply::NetworkError)),
+ this, SLOT(error(QNetworkReply::NetworkError)));
+ QObject::connect(m_network, SIGNAL(finished()),
+ this, SLOT(finished()));
+}
+
+QScriptValue QmlXMLHttpRequest::send(QScriptValue *me, const QByteArray &data)
+{
+ m_errorFlag = false;
+ m_sendFlag = true;
+ m_redirectCount = 0;
+ m_data = data;
+ m_me = *me;
+
+ requestFromUrl(m_url);
+
+ return QScriptValue();
+}
+
+QScriptValue QmlXMLHttpRequest::abort(QScriptValue *me)
+{
+ destroyNetwork();
+ m_responseEntityBody = QByteArray();
+ m_errorFlag = true;
+ m_request = QNetworkRequest();
+
+ if (!(m_state == Unsent ||
+ (m_state == Opened && !m_sendFlag) ||
+ m_state == Done)) {
+
+ m_state = Done;
+ m_sendFlag = false;
+ QScriptValue cbv = dispatchCallback(me);
+ if (cbv.isError()) return cbv;
+ }
+
+ m_state = Unsent;
+ return QScriptValue();
+}
+
+void QmlXMLHttpRequest::downloadProgress(qint64 bytes)
+{
+ Q_UNUSED(bytes)
+ m_status =
+ m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ m_statusText =
+ QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
+
+ // ### We assume if this is called the headers are now available
+ if (m_state < HeadersReceived) {
+ m_state = HeadersReceived;
+ fillHeadersList ();
+ QScriptValue cbv = dispatchCallback(&m_me);
+ if (cbv.isError()) printError(cbv);
+ }
+
+ bool wasEmpty = m_responseEntityBody.isEmpty();
+ m_responseEntityBody.append(m_network->readAll());
+ if (wasEmpty && !m_responseEntityBody.isEmpty()) {
+ m_state = Loading;
+ QScriptValue cbv = dispatchCallback(&m_me);
+ if (cbv.isError()) printError(cbv);
+ }
+}
+
+void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
+{
+ Q_UNUSED(error)
+ m_status =
+ m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ m_statusText =
+ QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
+
+ m_responseEntityBody = QByteArray();
+
+ m_request = QNetworkRequest();
+ m_data.clear();
+ destroyNetwork();
+
+ if (error == QNetworkReply::ContentAccessDenied ||
+ error == QNetworkReply::ContentOperationNotPermittedError ||
+ error == QNetworkReply::ContentNotFoundError ||
+ error == QNetworkReply::AuthenticationRequiredError ||
+ error == QNetworkReply::ContentReSendError) {
+ m_state = Loading;
+ QScriptValue cbv = dispatchCallback(&m_me);
+ if (cbv.isError()) printError(cbv);
+ } else {
+ m_errorFlag = true;
+ }
+
+ m_state = Done;
+ QScriptValue cbv = dispatchCallback(&m_me);
+ if (cbv.isError()) printError(cbv);
+}
+
+#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
+void QmlXMLHttpRequest::finished()
+{
+ m_redirectCount++;
+ if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) {
+ QVariant redirect = m_network->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = redirect.toUrl();
+ destroyNetwork();
+ requestFromUrl(url);
+ return;
+ }
+ }
+
+ m_status =
+ m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ m_statusText =
+ QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
+
+ if (m_state < HeadersReceived) {
+ m_state = HeadersReceived;
+ fillHeadersList ();
+ QScriptValue cbv = dispatchCallback(&m_me);
+ if (cbv.isError()) printError(cbv);
+ }
+ m_responseEntityBody.append(m_network->readAll());
+ m_data.clear();
+ destroyNetwork();
+ if (m_state < Loading) {
+ m_state = Loading;
+ QScriptValue cbv = dispatchCallback(&m_me);
+ if (cbv.isError()) printError(cbv);
+ }
+ m_state = Done;
+ QScriptValue cbv = dispatchCallback(&m_me);
+ if (cbv.isError()) printError(cbv);
+
+ m_me = QScriptValue();
+}
+
+
+QString QmlXMLHttpRequest::responseBody() const
+{
+ return QString::fromUtf8(m_responseEntityBody);
+}
+
+QScriptValue QmlXMLHttpRequest::dispatchCallback(QScriptValue *me)
+{
+ QScriptValue v = me->property(QLatin1String("callback"));
+ return v.call();
+}
+
+void QmlXMLHttpRequest::printError(const QScriptValue& sv)
+{
+ QmlError error;
+ QmlExpressionPrivate::exceptionToError(sv.engine(), error);
+ qWarning().nospace() << qPrintable(error.toString());
+}
+
+void QmlXMLHttpRequest::destroyNetwork()
+{
+ if (m_network) {
+ m_network->disconnect();
+ m_network->deleteLater();
+ m_network = 0;
+ }
+}
+
+// XMLHttpRequest methods
+static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngine *engine)
+{
+ QScriptValue dataObject = context->thisObject().data();
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(dataObject.toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (context->argumentCount() < 2 || context->argumentCount() > 5)
+ THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+
+ // Argument 0 - Method
+ QString method = context->argument(0).toString().toUpper();
+ if (method != QLatin1String("GET") &&
+ method != QLatin1String("PUT") &&
+ method != QLatin1String("HEAD") &&
+ method != QLatin1String("POST"))
+ THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
+
+
+ // Argument 1 - URL
+ QUrl url = QUrl::fromEncoded(context->argument(1).toString().toUtf8());
+
+ if (url.isRelative()) {
+ url = QmlScriptEngine::get(engine)->resolvedUrl(context,url);
+ }
+
+ // Argument 2 - async (optional)
+ if (context->argumentCount() > 2 && !context->argument(2).toBoolean())
+ THROW_DOM(NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
+
+
+ // Argument 3/4 - user/pass (optional)
+ QString username, password;
+ if (context->argumentCount() > 3)
+ username = context->argument(3).toString();
+ if (context->argumentCount() > 4)
+ password = context->argument(4).toString();
+
+
+ // Clear the fragment (if any)
+ url.setFragment(QString());
+ // Set username/password
+ if (!username.isNull()) url.setUserName(username);
+ if (!password.isNull()) url.setPassword(password);
+
+ return request->open(&dataObject, method, url);
+}
+
+static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (context->argumentCount() != 2)
+ THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+
+
+ if (request->readyState() != QmlXMLHttpRequest::Opened ||
+ request->sendFlag())
+ THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+
+ QString name = context->argument(0).toString();
+ QString value = context->argument(1).toString();
+
+ // ### Check that name and value are well formed
+
+ QString nameUpper = name.toUpper();
+ if (nameUpper == QLatin1String("ACCEPT-CHARSET") ||
+ nameUpper == QLatin1String("ACCEPT-ENCODING") ||
+ nameUpper == QLatin1String("CONNECTION") ||
+ nameUpper == QLatin1String("CONTENT-LENGTH") ||
+ nameUpper == QLatin1String("COOKIE") ||
+ nameUpper == QLatin1String("COOKIE2") ||
+ nameUpper == QLatin1String("CONTENT-TRANSFER-ENCODING") ||
+ nameUpper == QLatin1String("DATE") ||
+ nameUpper == QLatin1String("EXPECT") ||
+ nameUpper == QLatin1String("HOST") ||
+ nameUpper == QLatin1String("KEEP-ALIVE") ||
+ nameUpper == QLatin1String("REFERER") ||
+ nameUpper == QLatin1String("TE") ||
+ nameUpper == QLatin1String("TRAILER") ||
+ nameUpper == QLatin1String("TRANSFER-ENCODING") ||
+ nameUpper == QLatin1String("UPGRADE") ||
+ nameUpper == QLatin1String("USER-AGENT") ||
+ nameUpper == QLatin1String("VIA") ||
+ nameUpper.startsWith(QLatin1String("PROXY-")) ||
+ nameUpper.startsWith(QLatin1String("SEC-")))
+ return engine->undefinedValue();
+
+ request->addHeader(nameUpper, value);
+
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngine *)
+{
+ QScriptValue dataObject = context->thisObject().data();
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(dataObject.toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (request->readyState() != QmlXMLHttpRequest::Opened)
+ THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ if (request->sendFlag())
+ THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ QByteArray data;
+ if (context->argumentCount() > 0)
+ data = context->argument(0).toString().toUtf8();
+
+ return request->send(&dataObject, data);
+}
+
+static QScriptValue qmlxmlhttprequest_abort(QScriptContext *context, QScriptEngine *)
+{
+ QScriptValue dataObject = context->thisObject().data();
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(dataObject.toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ return request->abort(&dataObject);
+}
+
+static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine)
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (context->argumentCount() != 1)
+ THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done &&
+ request->readyState() != QmlXMLHttpRequest::HeadersReceived)
+ THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ QString headerName = context->argument(0).toString();
+
+ return QScriptValue(request->header(headerName));
+}
+
+static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine)
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (context->argumentCount() != 0)
+ THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done &&
+ request->readyState() != QmlXMLHttpRequest::HeadersReceived)
+ THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ return QScriptValue(request->headers());
+}
+
+// XMLHttpRequest properties
+static QScriptValue qmlxmlhttprequest_readyState(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine)
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ return QScriptValue(request->readyState());
+}
+
+static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine)
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (request->readyState() == QmlXMLHttpRequest::Unsent ||
+ request->readyState() == QmlXMLHttpRequest::Opened)
+ THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ if (request->errorFlag())
+ return QScriptValue(0);
+ else
+ return QScriptValue(request->replyStatus());
+}
+
+static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine)
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (request->readyState() == QmlXMLHttpRequest::Unsent ||
+ request->readyState() == QmlXMLHttpRequest::Opened)
+ THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ if (request->errorFlag())
+ return QScriptValue(0);
+ else
+ return QScriptValue(request->replyStatusText());
+}
+
+static QScriptValue qmlxmlhttprequest_responseText(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine)
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done)
+ return QScriptValue(QString());
+ else
+ return QScriptValue(request->responseBody());
+}
+
+static QScriptValue qmlxmlhttprequest_responseXML(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done)
+ return engine->nullValue();
+ else
+ return Document::load(engine, request->responseBody());
+}
+
+static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine);
+ QScriptValue dataObject = context->thisObject().data();
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(dataObject.toQObject());
+ if (!request)
+ THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ if (context->argumentCount()) {
+ QScriptValue v = context->argument(0);
+ dataObject.setProperty(QLatin1String("callback"), v);
+ return v;
+ } else {
+ return dataObject.property(QLatin1String("callback"));
+ }
+}
+
+// Constructor
+static QScriptValue qmlxmlhttprequest_new(QScriptContext *context, QScriptEngine *engine)
+{
+ if (context->isCalledAsConstructor()) {
+ context->thisObject().setData(engine->newQObject(new QmlXMLHttpRequest(QmlScriptEngine::get(engine)->networkAccessManager()), QScriptEngine::ScriptOwnership));
+ }
+ return engine->undefinedValue();
+}
+
+void qt_add_qmlxmlhttprequest(QScriptEngine *engine)
+{
+ QScriptValue prototype = engine->newObject();
+
+ // Methods
+ prototype.setProperty(QLatin1String("open"), engine->newFunction(qmlxmlhttprequest_open, 2));
+ prototype.setProperty(QLatin1String("setRequestHeader"), engine->newFunction(qmlxmlhttprequest_setRequestHeader, 2));
+ prototype.setProperty(QLatin1String("send"), engine->newFunction(qmlxmlhttprequest_send));
+ prototype.setProperty(QLatin1String("abort"), engine->newFunction(qmlxmlhttprequest_abort));
+ prototype.setProperty(QLatin1String("getResponseHeader"), engine->newFunction(qmlxmlhttprequest_getResponseHeader, 1));
+ prototype.setProperty(QLatin1String("getAllResponseHeaders"), engine->newFunction(qmlxmlhttprequest_getAllResponseHeaders));
+
+ // Read-only properties
+ prototype.setProperty(QLatin1String("readyState"), engine->newFunction(qmlxmlhttprequest_readyState), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("status"), engine->newFunction(qmlxmlhttprequest_status), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("statusText"), engine->newFunction(qmlxmlhttprequest_statusText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("responseText"), engine->newFunction(qmlxmlhttprequest_responseText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("responseXML"), engine->newFunction(qmlxmlhttprequest_responseXML), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("onreadystatechange"), engine->newFunction(qmlxmlhttprequest_onreadystatechange), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+
+ // State values
+ prototype.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ prototype.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ prototype.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ prototype.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ prototype.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+
+ // Constructor
+ QScriptValue constructor = engine->newFunction(qmlxmlhttprequest_new, prototype);
+ constructor.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ engine->globalObject().setProperty(QLatin1String("XMLHttpRequest"), constructor);
+
+ // DOM Exception
+ QScriptValue domExceptionPrototype = engine->newObject();
+ domExceptionPrototype.setProperty(QLatin1String("INDEX_SIZE_ERR"), INDEX_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("DOMSTRING_SIZE_ERR"), DOMSTRING_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("HIERARCHY_REQUEST_ERR"), HIERARCHY_REQUEST_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("WRONG_DOCUMENT_ERR"), WRONG_DOCUMENT_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("INVALID_CHARACTER_ERR"), INVALID_CHARACTER_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("NO_DATA_ALLOWED_ERR"), NO_DATA_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("NO_MODIFICATION_ALLOWED_ERR"), NO_MODIFICATION_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("NOT_FOUND_ERR"), NOT_FOUND_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("NOT_SUPPORTED_ERR"), NOT_SUPPORTED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("INUSE_ATTRIBUTE_ERR"), INUSE_ATTRIBUTE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("INVALID_STATE_ERR"), INVALID_STATE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("SYNTAX_ERR"), SYNTAX_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("INVALID_MODIFICATION_ERR"), INVALID_MODIFICATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("NAMESPACE_ERR"), NAMESPACE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("INVALID_ACCESS_ERR"), INVALID_ACCESS_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("VALIDATION_ERR"), VALIDATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ domExceptionPrototype.setProperty(QLatin1String("TYPE_MISMATCH_ERR"), TYPE_MISMATCH_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+
+ engine->globalObject().setProperty(QLatin1String("DOMException"), domExceptionPrototype);
+}
+
+#include <qmlxmlhttprequest.moc>
diff --git a/src/declarative/qml/qmlxmlhttprequest_p.h b/src/declarative/qml/qmlxmlhttprequest_p.h
new file mode 100644
index 0000000..dfed5d2
--- /dev/null
+++ b/src/declarative/qml/qmlxmlhttprequest_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLXMLHTTPREQUEST_P_H
+#define QMLXMLHTTPREQUEST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+class QScriptEngine;
+void qt_add_qmlxmlhttprequest(QScriptEngine *engine);
+
+#endif // QMLXMLHTTPREQUEST_P_H
+
diff --git a/src/declarative/qml/qpodvector_p.h b/src/declarative/qml/qpodvector_p.h
new file mode 100644
index 0000000..42d6017
--- /dev/null
+++ b/src/declarative/qml/qpodvector_p.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPODVECTOR_P_H
+#define QPODVECTOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+template<class T, int Increment=1024>
+class QPODVector
+{
+public:
+ QPODVector()
+ : m_count(0), m_capacity(0), m_data(0) {}
+ ~QPODVector() { if (m_data) ::free(m_data); }
+
+ const T &at(int idx) const {
+ return m_data[idx];
+ }
+
+ T &operator[](int idx) {
+ return m_data[idx];
+ }
+
+ void clear() {
+ m_count = 0;
+ }
+
+ void prepend(const T &v) {
+ insert(0, v);
+ }
+
+ void append(const T &v) {
+ insert(m_count, v);
+ }
+
+ void insert(int idx, const T &v) {
+ if (m_count == m_capacity) {
+ m_capacity += Increment;
+ m_data = (T *)realloc(m_data, m_capacity * sizeof(T));
+ }
+ int moveCount = m_count - idx;
+ if (moveCount)
+ ::memmove(m_data + idx + 1, m_data + idx, moveCount * sizeof(T));
+ m_count++;
+ m_data[idx] = v;
+ }
+
+ void reserve(int count) {
+ if (count >= m_capacity) {
+ m_capacity = (count + (Increment-1)) & (0xFFFFFFFF - Increment + 1);
+ m_data = (T *)realloc(m_data, m_capacity * sizeof(T));
+ }
+ }
+
+ void insertBlank(int idx, int count) {
+ int newSize = m_count + count;
+ reserve(newSize);
+ int moveCount = m_count - idx;
+ if (moveCount)
+ ::memmove(m_data + idx + count, m_data + idx,
+ moveCount * sizeof(T));
+ m_count = newSize;
+ }
+
+ void remove(int idx, int count = 1) {
+ int moveCount = m_count - (idx + count);
+ if (moveCount)
+ ::memmove(m_data + idx, m_data + idx + count,
+ moveCount * sizeof(T));
+ m_count -= count;
+ }
+
+ void removeOne(const T &v) {
+ int idx = 0;
+ while (idx < m_count) {
+ if (m_data[idx] == v) {
+ remove(idx);
+ return;
+ }
+ ++idx;
+ }
+ }
+
+ int find(const T &v) {
+ for (int idx = 0; idx < m_count; ++idx)
+ if (m_data[idx] == v)
+ return idx;
+ return -1;
+ }
+
+ bool contains(const T &v) {
+ return find(v) != -1;
+ }
+
+ int count() const {
+ return m_count;
+ }
+
+ void copyAndClear(QPODVector<T,Increment> &other) {
+ if (other.m_data) ::free(other.m_data);
+ other.m_count = m_count;
+ other.m_capacity = m_capacity;
+ other.m_data = m_data;
+ m_count = 0;
+ m_capacity = 0;
+ m_data = 0;
+ }
+
+ QPODVector<T,Increment> &operator<<(const T &v) { append(v); return *this; }
+private:
+ QPODVector(const QPODVector &);
+ QPODVector &operator=(const QPODVector &);
+ int m_count;
+ int m_capacity;
+ T *m_data;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/rewriter/rewriter.cpp b/src/declarative/qml/rewriter/rewriter.cpp
new file mode 100644
index 0000000..237d33f
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rewriter_p.h"
+
+#include <qmljsast_p.h>
+
+QT_QML_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+
+void Rewriter::replace(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset, loc.length, text); }
+
+void Rewriter::remove(const AST::SourceLocation &loc)
+{ return replace(loc.offset, loc.length, QString()); }
+
+void Rewriter::remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc)
+{ return replace(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, QString()); }
+
+void Rewriter::insertTextBefore(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset, 0, text); }
+
+void Rewriter::insertTextAfter(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset + loc.length, 0, text); }
+
+void Rewriter::replace(int offset, int length, const QString &text)
+{ textWriter.replace(offset, length, text); }
+
+void Rewriter::insertText(int offset, const QString &text)
+{ replace(offset, 0, text); }
+
+void Rewriter::removeText(int offset, int length)
+{ replace(offset, length, QString()); }
+
+QString Rewriter::textAt(const AST::SourceLocation &loc) const
+{ return _code.mid(loc.offset, loc.length); }
+
+QString Rewriter::textAt(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc) const
+{ return _code.mid(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset); }
+
+void Rewriter::accept(QmlJS::AST::Node *node)
+{ QmlJS::AST::Node::acceptChild(node, this); }
+
+void Rewriter::moveTextBefore(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc)
+{
+ move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset);
+}
+
+void Rewriter::moveTextAfter(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc)
+{
+ move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset + loc.length);
+}
+
+void Rewriter::move(int pos, int length, int to)
+{
+ textWriter.move(pos, length, to);
+}
+
+QT_QML_END_NAMESPACE
diff --git a/src/declarative/qml/rewriter/rewriter.pri b/src/declarative/qml/rewriter/rewriter.pri
new file mode 100644
index 0000000..2c29061
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter.pri
@@ -0,0 +1,9 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/textwriter_p.h
+SOURCES += $$PWD/textwriter.cpp
+
+!no_ast_rewriter {
+ HEADERS += $$PWD/rewriter_p.h
+ SOURCES += $$PWD/rewriter.cpp
+}
diff --git a/src/declarative/qml/rewriter/rewriter_p.h b/src/declarative/qml/rewriter/rewriter_p.h
new file mode 100644
index 0000000..57e7ea2
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REWRITER_H
+#define REWRITER_H
+
+#include "textwriter_p.h"
+
+#include <qmljsastvisitor_p.h>
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+////////////////////////////////////////////////////////////////////////////////
+// Replacement
+////////////////////////////////////////////////////////////////////////////////
+class Replacement
+{
+ int _offset;
+ int _length;
+ QString _text;
+
+public:
+ Replacement(int offset = 0, int length = 0, const QString &text = QString())
+ : _offset(offset), _length(length), _text(text)
+ { }
+
+ bool isNull() const { return _offset == _length; }
+ operator bool() const { return ! isNull(); }
+
+ int offset() const { return _offset; }
+ int length() const { return _length; }
+ QString text() const { return _text; }
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Rewriter
+////////////////////////////////////////////////////////////////////////////////
+class Rewriter: public AST::Visitor
+{
+protected:
+ TextWriter textWriter;
+public:
+ //
+ // Token based API
+ //
+
+ /// Returns the text of the token at the given \a location.
+ QString textAt(const AST::SourceLocation &location) const;
+
+ QString textAt(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc) const;
+
+ /// Replace the token at \a loc with the given \a text.
+ void replace(const AST::SourceLocation &loc, const QString &text);
+
+ /// Remove the token at the given \a location.
+ void remove(const AST::SourceLocation &location);
+
+ /// Remove all tokens in the range [\a firstLoc, \a lastLoc].
+ void remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc);
+
+ /// Insert \a text before the token at the given \a location.
+ void insertTextBefore(const AST::SourceLocation &location, const QString &text);
+
+ /// Insert \a text after the token at the given \a location.
+ void insertTextAfter(const AST::SourceLocation &loc, const QString &text);
+
+ void moveTextBefore(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc);
+
+ void moveTextAfter(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc);
+
+ //
+ // low-level offset based API
+ //
+ virtual void replace(int offset, int length, const QString &text);
+ virtual void move(int pos, int length, int to);
+ void insertText(int offset, const QString &text);
+ void removeText(int offset, int length);
+
+ /// Visit the given \a node.
+ void accept(AST::Node *node);
+
+ /// Returns the original unchanged source code.
+ QString code() const { return _code; }
+
+ /// Returns the list of replacements.
+ QList<Replacement> replacementList() const { return _replacementList; }
+
+protected:
+ /// \internal
+ void setCode(const QString &code) { _code = code; }
+
+private:
+ QString _code;
+ QList<Replacement> _replacementList;
+};
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
+QT_END_HEADER
+
+#endif // REWRITER_H
diff --git a/src/declarative/qml/rewriter/textwriter.cpp b/src/declarative/qml/rewriter/textwriter.cpp
new file mode 100644
index 0000000..8f89f12
--- /dev/null
+++ b/src/declarative/qml/rewriter/textwriter.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "textwriter_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+
+TextWriter::TextWriter()
+ :string(0), cursor(0)
+{
+}
+
+static bool overlaps(int posA, int lengthA, int posB, int lengthB) {
+ return (posA < posB + lengthB && posA + lengthA > posB + lengthB)
+ || (posA < posB && posA + lengthA > posB);
+}
+
+bool TextWriter::hasOverlap(int pos, int length)
+{
+ {
+ QListIterator<Replace> i(replaceList);
+ while (i.hasNext()) {
+ const Replace &cmd = i.next();
+ if (overlaps(pos, length, cmd.pos, cmd.length))
+ return true;
+ }
+ }
+ {
+ QListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ const Move &cmd = i.next();
+ if (overlaps(pos, length, cmd.pos, cmd.length))
+ return true;
+ }
+ return false;
+ }
+}
+
+bool TextWriter::hasMoveInto(int pos, int length)
+{
+ QListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ const Move &cmd = i.next();
+ if (cmd.to >= pos && cmd.to < pos + length)
+ return true;
+ }
+ return false;
+}
+
+void TextWriter::replace(int pos, int length, const QString &replacement)
+{
+ Q_ASSERT(!hasOverlap(pos, length));
+ Q_ASSERT(!hasMoveInto(pos, length));
+
+ Replace cmd;
+ cmd.pos = pos;
+ cmd.length = length;
+ cmd.replacement = replacement;
+ replaceList += cmd;
+}
+
+void TextWriter::move(int pos, int length, int to)
+{
+ Q_ASSERT(!hasOverlap(pos, length));
+
+ Move cmd;
+ cmd.pos = pos;
+ cmd.length = length;
+ cmd.to = to;
+ moveList += cmd;
+}
+
+void TextWriter::doReplace(const Replace &replace)
+{
+ int diff = replace.replacement.size() - replace.length;
+ {
+ QMutableListIterator<Replace> i(replaceList);
+ while (i.hasNext()) {
+ Replace &c = i.next();
+ if (replace.pos < c.pos)
+ c.pos += diff;
+ else if (replace.pos + replace.length < c.pos + c.length)
+ c.length += diff;
+ }
+ }
+ {
+ QMutableListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ Move &c = i.next();
+ if (replace.pos < c.pos)
+ c.pos += diff;
+ else if (replace.pos + replace.length < c.pos + c.length)
+ c.length += diff;
+
+ if (replace.pos < c.to)
+ c.to += diff;
+ }
+ }
+
+ if (string) {
+ string->replace(replace.pos, replace.length, replace.replacement);
+ } else if (cursor) {
+ cursor->setPosition(replace.pos);
+ cursor->setPosition(replace.pos + replace.length, QTextCursor::KeepAnchor);
+ cursor->insertText(replace.replacement);
+ }
+}
+
+void TextWriter::doMove(const Move &move)
+{
+ QString text;
+ if (string) {
+ text = string->mid(move.pos, move.length);
+ } else if (cursor) {
+ cursor->setPosition(move.pos);
+ cursor->setPosition(move.pos + move.length, QTextCursor::KeepAnchor);
+ text = cursor->selectedText();
+ }
+
+ Replace cut;
+ cut.pos = move.pos;
+ cut.length = move.length;
+ Replace paste;
+ paste.pos = move.to;
+ paste.length = 0;
+ paste.replacement = text;
+
+ replaceList.append(cut);
+ replaceList.append(paste);
+
+ Replace cmd;
+ while (!replaceList.isEmpty()) {
+ cmd = replaceList.first();
+ replaceList.removeFirst();
+ doReplace(cmd);
+ }
+}
+
+void TextWriter::write(QString *s)
+{
+ string = s;
+ write_helper();
+ string = 0;
+}
+
+void TextWriter::write(QTextCursor *textCursor)
+{
+ cursor = textCursor;
+ write_helper();
+ cursor = 0;
+}
+
+void TextWriter::write_helper()
+{
+ if (cursor)
+ cursor->beginEditBlock();
+ {
+ Replace cmd;
+ while (!replaceList.isEmpty()) {
+ cmd = replaceList.first();
+ replaceList.removeFirst();
+ doReplace(cmd);
+ }
+ }
+ {
+ Move cmd;
+ while (!moveList.isEmpty()) {
+ cmd = moveList.first();
+ moveList.removeFirst();
+ doMove(cmd);
+ }
+ }
+ if (cursor)
+ cursor->endEditBlock();
+}
+
+QT_QML_END_NAMESPACE
diff --git a/src/declarative/qml/rewriter/textwriter_p.h b/src/declarative/qml/rewriter/textwriter_p.h
new file mode 100644
index 0000000..a19fa5e
--- /dev/null
+++ b/src/declarative/qml/rewriter/textwriter_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTWRITER_H
+#define TEXTWRITER_H
+
+#include <qmljsglobal_p.h>
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtGui/QTextCursor>
+
+QT_BEGIN_HEADER
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class TextWriter
+{
+ QString *string;
+ QTextCursor *cursor;
+
+ struct Replace {
+ int pos;
+ int length;
+ QString replacement;
+ };
+
+ QList<Replace> replaceList;
+
+ struct Move {
+ int pos;
+ int length;
+ int to;
+ };
+
+ QList<Move> moveList;
+
+ bool hasOverlap(int pos, int length);
+ bool hasMoveInto(int pos, int length);
+
+ void doReplace(const Replace &replace);
+ void doMove(const Move &move);
+
+ void write_helper();
+
+public:
+ TextWriter();
+
+ void replace(int pos, int length, const QString &replacement);
+ void move(int pos, int length, int to);
+
+ void write(QString *s);
+ void write(QTextCursor *textCursor);
+
+};
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
+QT_END_HEADER
+
+#endif // TEXTWRITER_H
diff --git a/src/declarative/util/qfxperf.cpp b/src/declarative/util/qfxperf.cpp
new file mode 100644
index 0000000..f62f810
--- /dev/null
+++ b/src/declarative/util/qfxperf.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxperf_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_DEFINE_PERFORMANCE_LOG(QmlPerf, "QmlGraphics") {
+ Q_DEFINE_PERFORMANCE_METRIC(QmlParsing, "Compilation: QML Parsing")
+ Q_DEFINE_PERFORMANCE_METRIC(Compilation, " QML Compilation")
+ Q_DEFINE_PERFORMANCE_METRIC(VMEExecution, "Execution: QML VME Execution")
+ Q_DEFINE_PERFORMANCE_METRIC(BindInit, "BindValue Initialization")
+ Q_DEFINE_PERFORMANCE_METRIC(BindValue, "BindValue execution")
+ Q_DEFINE_PERFORMANCE_METRIC(BindValueSSE, "BindValue execution SSE")
+ Q_DEFINE_PERFORMANCE_METRIC(BindValueQt, "BindValue execution QtScript")
+ Q_DEFINE_PERFORMANCE_METRIC(BindableValueUpdate, "QmlBinding::update")
+ Q_DEFINE_PERFORMANCE_METRIC(PixmapLoad, "Pixmap loading")
+ Q_DEFINE_PERFORMANCE_METRIC(FontDatabase, "Font database creation")
+ Q_DEFINE_PERFORMANCE_METRIC(QmlGraphicsPathViewPathCache, "FX Items: QmlGraphicsPathView: Path cache")
+ Q_DEFINE_PERFORMANCE_METRIC(CreateParticle, " QmlGraphicsParticles: Particle creation")
+ Q_DEFINE_PERFORMANCE_METRIC(ItemComponentComplete, " QmlGraphicsItem::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(ImageComponentComplete, " QmlGraphicsImage::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(BaseLayoutComponentComplete, " QmlGraphicsBasePositioner::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(TextComponentComplete, " QmlGraphicsText::componentComplete")
+ Q_DEFINE_PERFORMANCE_METRIC(QmlGraphicsText_setText, " QmlGraphicsText::setText")
+ Q_DEFINE_PERFORMANCE_METRIC(AddScript, "QmlScript::addScriptToEngine")
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qfxperf_p_p.h b/src/declarative/util/qfxperf_p_p.h
new file mode 100644
index 0000000..e3f820c
--- /dev/null
+++ b/src/declarative/util/qfxperf_p_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QFXPERF_H
+#define QFXPERF_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qperformancelog_p_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+Q_DECLARE_PERFORMANCE_LOG(QmlPerf) {
+ Q_DECLARE_PERFORMANCE_METRIC(QmlParsing)
+
+ Q_DECLARE_PERFORMANCE_METRIC(Compilation)
+ Q_DECLARE_PERFORMANCE_METRIC(VMEExecution)
+
+ Q_DECLARE_PERFORMANCE_METRIC(BindInit)
+ Q_DECLARE_PERFORMANCE_METRIC(BindValue)
+ Q_DECLARE_PERFORMANCE_METRIC(BindValueSSE)
+ Q_DECLARE_PERFORMANCE_METRIC(BindValueQt)
+ Q_DECLARE_PERFORMANCE_METRIC(BindableValueUpdate)
+ Q_DECLARE_PERFORMANCE_METRIC(PixmapLoad)
+ Q_DECLARE_PERFORMANCE_METRIC(FontDatabase)
+ Q_DECLARE_PERFORMANCE_METRIC(QmlGraphicsPathViewPathCache)
+ Q_DECLARE_PERFORMANCE_METRIC(CreateParticle)
+ Q_DECLARE_PERFORMANCE_METRIC(ItemComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(ImageComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(BaseLayoutComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(TextComponentComplete)
+ Q_DECLARE_PERFORMANCE_METRIC(QmlGraphicsText_setText)
+ Q_DECLARE_PERFORMANCE_METRIC(AddScript)
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXPERF_H
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
new file mode 100644
index 0000000..abffefe
--- /dev/null
+++ b/src/declarative/util/qmlanimation.cpp
@@ -0,0 +1,2337 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlanimation_p.h"
+#include "qmlanimation_p_p.h"
+
+#include "qmlbehavior_p.h"
+#include "qmlstateoperations_p.h"
+
+#include <qmlpropertyvaluesource.h>
+#include <qml.h>
+#include <qmlinfo.h>
+#include <qmlexpression.h>
+#include <qmlstringconverters_p.h>
+#include <qmlglobal_p.h>
+
+#include <qvariant.h>
+#include <qcolor.h>
+#include <qfile.h>
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
+#include <QtCore/qset.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsize.h>
+
+#include <private/qvariantanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QEasingCurve stringToCurve(const QString &curve, QObject *obj)
+{
+ QEasingCurve easingCurve;
+
+ QString normalizedCurve = curve;
+ bool hasParams = curve.contains(QLatin1Char('('));
+ QStringList props;
+
+ if (hasParams) {
+ QString easeName = curve.trimmed();
+ if (!easeName.endsWith(QLatin1Char(')'))) {
+ qmlInfo(obj) << obj->tr("Unmatched parenthesis in easing function \"%1\"").arg(curve);
+ return easingCurve;
+ }
+
+ int idx = easeName.indexOf(QLatin1Char('('));
+ QString prop_str =
+ easeName.mid(idx + 1, easeName.length() - 1 - idx - 1);
+ normalizedCurve = easeName.left(idx);
+ if (!normalizedCurve.startsWith(QLatin1String("ease"))) {
+ qmlInfo(obj) << obj->tr("Easing function \"%1\" must start with \"ease\"").arg(curve);
+ return easingCurve;
+ }
+
+ props = prop_str.split(QLatin1Char(','));
+ }
+
+ if (normalizedCurve.startsWith(QLatin1String("ease")))
+ normalizedCurve = normalizedCurve.mid(4);
+
+ static int index = QEasingCurve::staticMetaObject.indexOfEnumerator("Type");
+ static QMetaEnum me = QEasingCurve::staticMetaObject.enumerator(index);
+
+ int value = me.keyToValue(normalizedCurve.toUtf8().constData());
+ if (value < 0) {
+ qmlInfo(obj) << obj->tr("Unknown easing curve \"%1\"").arg(curve);
+ return easingCurve;
+ }
+ easingCurve.setType((QEasingCurve::Type)value);
+
+ if (hasParams) {
+ foreach(const QString &str, props) {
+ int sep = str.indexOf(QLatin1Char(':'));
+
+ if (sep == -1) {
+ qmlInfo(obj) << obj->tr("Improperly specified parameter in easing function \"%1\"").arg(curve);
+ continue;
+ }
+
+ QString propName = str.left(sep).trimmed();
+ bool isOk;
+ qreal propValue = str.mid(sep + 1).trimmed().toDouble(&isOk);
+
+ if (propName.isEmpty() || !isOk) {
+ qmlInfo(obj) << obj->tr("Improperly specified parameter in easing function \"%1\"").arg(curve);
+ continue;
+ }
+
+ if (propName == QLatin1String("amplitude")) {
+ easingCurve.setAmplitude(propValue);
+ } else if (propName == QLatin1String("period")) {
+ easingCurve.setPeriod(propValue);
+ } else if (propName == QLatin1String("overshoot")) {
+ easingCurve.setOvershoot(propValue);
+ } else {
+ qmlInfo(obj) << obj->tr("Unknown easing parameter \"%1\"").arg(propName);
+ continue;
+ }
+ }
+ }
+ return easingCurve;
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlAbstractAnimation)
+
+/*!
+ \qmlclass Animation QmlAbstractAnimation
+ \brief The Animation element is the base of all QML animations.
+
+ The Animation element cannot be used directly in a QML file. It exists
+ to provide a set of common properties and methods, available across all the
+ other animation types that inherit from it. Attempting to use the Animation
+ element directly will result in an error.
+*/
+
+/*!
+ \class QmlAbstractAnimation
+ \internal
+*/
+
+QmlAbstractAnimation::QmlAbstractAnimation(QObject *parent)
+: QObject(*(new QmlAbstractAnimationPrivate), parent)
+{
+}
+
+QmlAbstractAnimation::~QmlAbstractAnimation()
+{
+}
+
+QmlAbstractAnimation::QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent)
+: QObject(dd, parent)
+{
+}
+
+/*!
+ \qmlproperty bool Animation::running
+ This property holds whether the animation is currently running.
+
+ The \c running property can be set to declaratively control whether or not
+ an animation is running. The following example will animate a rectangle
+ whenever the \l MouseRegion is pressed.
+
+ \code
+ Rectangle {
+ width: 100; height: 100
+ x: NumberAnimation {
+ running: myMouse.pressed
+ from: 0; to: 100
+ }
+ MouseRegion { id: myMouse }
+ }
+ \endcode
+
+ Likewise, the \c running property can be read to determine if the animation
+ is running. In the following example the text element will indicate whether
+ or not the animation is running.
+
+ \code
+ NumberAnimation { id: myAnimation }
+ Text { text: myAnimation.running ? "Animation is running" : "Animation is not running" }
+ \endcode
+
+ Animations can also be started and stopped imperatively from JavaScript
+ using the \c start() and \c stop() methods.
+
+ By default, animations are not running. Though, when the animations are assigned to properties,
+ as property value sources, they are set to running by default.
+*/
+bool QmlAbstractAnimation::isRunning() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->running;
+}
+
+void QmlAbstractAnimationPrivate::commence()
+{
+ Q_Q(QmlAbstractAnimation);
+
+ q->prepare(userProperty.value);
+ q->qtAnimation()->start();
+ if (q->qtAnimation()->state() != QAbstractAnimation::Running) {
+ running = false;
+ emit q->completed();
+ }
+}
+
+QmlMetaProperty QmlAbstractAnimationPrivate::createProperty(QObject *obj, const QString &str, QObject *infoObj)
+{
+ QmlMetaProperty prop = QmlMetaProperty::createProperty(obj, str, qmlContext(infoObj));
+ if (!prop.isValid()) {
+ qmlInfo(infoObj) << QmlAbstractAnimation::tr("Cannot animate non-existant property \"%1\"").arg(str);
+ return QmlMetaProperty();
+ } else if (!prop.isWritable()) {
+ qmlInfo(infoObj) << QmlAbstractAnimation::tr("Cannot animate read-only property \"%1\"").arg(str);
+ return QmlMetaProperty();
+ }
+ return prop;
+}
+
+void QmlAbstractAnimation::setRunning(bool r)
+{
+ Q_D(QmlAbstractAnimation);
+
+ if (r == false)
+ d->avoidPropertyValueSourceStart = true;
+
+ if (d->running == r)
+ return;
+
+ if (d->group) {
+ qWarning("QmlAbstractAnimation: setRunning() cannot be used on non-root animation nodes");
+ return;
+ }
+
+ d->running = r;
+ if (d->running) {
+ if (d->alwaysRunToEnd && d->repeat
+ && qtAnimation()->state() == QAbstractAnimation::Running) {
+ qtAnimation()->setLoopCount(-1);
+ }
+
+ if (!d->connectedTimeLine) {
+ QObject::connect(qtAnimation(), SIGNAL(finished()),
+ this, SLOT(timelineComplete()));
+ d->connectedTimeLine = true;
+ }
+ if (d->componentComplete)
+ d->commence();
+ else
+ d->startOnCompletion = true;
+ emit started();
+ } else {
+ if (d->alwaysRunToEnd) {
+ if (d->repeat)
+ qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1);
+ } else
+ qtAnimation()->stop();
+
+ emit completed();
+ }
+
+ emit runningChanged(d->running);
+}
+
+/*!
+ \qmlproperty bool Animation::paused
+ This property holds whether the animation is currently paused.
+
+ The \c paused property can be set to declaratively control whether or not
+ an animation is paused.
+
+ Animations can also be paused and resumed imperatively from JavaScript
+ using the \c pause() and \c resume() methods.
+
+ By default, animations are not paused.
+*/
+bool QmlAbstractAnimation::isPaused() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->paused;
+}
+
+void QmlAbstractAnimation::setPaused(bool p)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->paused == p)
+ return;
+
+ if (d->group) {
+ qWarning("QmlAbstractAnimation: setPaused() cannot be used on non-root animation nodes");
+ return;
+ }
+
+ d->paused = p;
+ if (d->paused)
+ qtAnimation()->pause();
+ else
+ qtAnimation()->resume();
+
+ emit pausedChanged(d->running);
+}
+
+void QmlAbstractAnimation::classBegin()
+{
+ Q_D(QmlAbstractAnimation);
+ d->componentComplete = false;
+}
+
+void QmlAbstractAnimation::componentComplete()
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->startOnCompletion)
+ d->commence();
+ d->componentComplete = true;
+}
+
+/*!
+ \qmlproperty bool Animation::alwaysRunToEnd
+ This property holds whether the animation should run to completion when it is stopped.
+
+ If this true the animation will complete its current iteration when it
+ is stopped - either by setting the \c running property to false, or by
+ calling the \c stop() method. The \c complete() method is not effected
+ by this value.
+
+ This behavior is most useful when the \c repeat property is set, as the
+ animation will finish playing normally but not restart.
+
+ By default, the alwaysRunToEnd property is not set.
+*/
+bool QmlAbstractAnimation::alwaysRunToEnd() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->alwaysRunToEnd;
+}
+
+void QmlAbstractAnimation::setAlwaysRunToEnd(bool f)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->alwaysRunToEnd == f)
+ return;
+
+ d->alwaysRunToEnd = f;
+ emit alwaysRunToEndChanged(f);
+}
+
+/*!
+ \qmlproperty bool Animation::repeat
+ This property holds whether the animation should repeat.
+
+ If set, the animation will continuously repeat until it is explicitly
+ stopped - either by setting the \c running property to false, or by calling
+ the \c stop() method.
+
+ In the following example, the rectangle will spin indefinately.
+
+ \code
+ Rectangle {
+ rotation: NumberAnimation { running: true; repeat: true; from: 0 to: 360 }
+ }
+ \endcode
+*/
+bool QmlAbstractAnimation::repeat() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->repeat;
+}
+
+void QmlAbstractAnimation::setRepeat(bool r)
+{
+ Q_D(QmlAbstractAnimation);
+ if (r == d->repeat)
+ return;
+
+ d->repeat = r;
+ int lc = r ? -1 : 1;
+ qtAnimation()->setLoopCount(lc);
+ emit repeatChanged(r);
+}
+
+int QmlAbstractAnimation::currentTime()
+{
+ return qtAnimation()->currentLoopTime();
+}
+
+void QmlAbstractAnimation::setCurrentTime(int time)
+{
+ qtAnimation()->setCurrentTime(time);
+}
+
+QmlAnimationGroup *QmlAbstractAnimation::group() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->group;
+}
+
+void QmlAbstractAnimation::setGroup(QmlAnimationGroup *g)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->group == g)
+ return;
+ if (d->group)
+ static_cast<QmlAnimationGroupPrivate *>(d->group->d_func())->animations.removeAll(this);
+
+ d->group = g;
+
+ if (d->group && !static_cast<QmlAnimationGroupPrivate *>(d->group->d_func())->animations.contains(this))
+ static_cast<QmlAnimationGroupPrivate *>(d->group->d_func())->animations.append(this);
+
+ if (d->group)
+ ((QAnimationGroup*)d->group->qtAnimation())->addAnimation(qtAnimation());
+
+ //if (g) //if removed from a group, then the group should no longer be the parent
+ setParent(g);
+}
+
+/*!
+ \qmlmethod Animation::start()
+ \brief Starts the animation.
+
+ If the animation is already running, calling this method has no effect. The
+ \c running property will be true following a call to \c start().
+*/
+void QmlAbstractAnimation::start()
+{
+ setRunning(true);
+}
+
+/*!
+ \qmlmethod Animation::pause()
+ \brief Pauses the animation.
+
+ If the animation is already paused, calling this method has no effect. The
+ \c paused property will be true following a call to \c pause().
+*/
+void QmlAbstractAnimation::pause()
+{
+ setPaused(true);
+}
+
+/*!
+ \qmlmethod Animation::resume()
+ \brief Resumes a paused animation.
+
+ If the animation is not paused, calling this method has no effect. The
+ \c paused property will be false following a call to \c resume().
+*/
+void QmlAbstractAnimation::resume()
+{
+ setPaused(false);
+}
+
+/*!
+ \qmlmethod Animation::stop()
+ \brief Stops the animation.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c stop().
+
+ Normally \c stop() stops the animation immediately, and the animation has
+ no further influence on property values. In this example animation
+ \code
+ Rectangle {
+ x: NumberAnimation { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ was stopped at time 250ms, the \c x property will have a value of 50.
+
+ However, if the \c alwaysRunToEnd property is set, the animation will
+ continue running until it completes and then stop. The \c running property
+ will still become false immediately.
+*/
+void QmlAbstractAnimation::stop()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlmethod Animation::restart()
+ \brief Restarts the animation.
+
+ This is a convenience method, and is equivalent to calling \c stop() and
+ then \c start().
+*/
+void QmlAbstractAnimation::restart()
+{
+ stop();
+ start();
+}
+
+/*!
+ \qmlmethod Animation::complete()
+ \brief Stops the animation, jumping to the final property values.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c complete().
+
+ Unlike \c stop(), \c complete() immediately fast-forwards the animation to
+ its end. In the following example,
+ \code
+ Rectangle {
+ x: NumberAnimation { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ calling \c stop() at time 250ms will result in the \c x property having
+ a value of 50, while calling \c complete() will set the \c x property to
+ 100, exactly as though the animation had played the whole way through.
+*/
+void QmlAbstractAnimation::complete()
+{
+ if (isRunning()) {
+ qtAnimation()->setCurrentTime(qtAnimation()->duration());
+ }
+}
+
+void QmlAbstractAnimation::setTarget(const QmlMetaProperty &p)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->userProperty.isNull)
+ d->userProperty = p;
+
+ if (!d->avoidPropertyValueSourceStart)
+ setRunning(true);
+}
+
+//prepare is called before an animation begins
+//(when an animation is used as a simple animation, and not as part of a transition)
+void QmlAbstractAnimation::prepare(QmlMetaProperty &)
+{
+}
+
+void QmlAbstractAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_UNUSED(actions);
+ Q_UNUSED(modified);
+ Q_UNUSED(direction);
+}
+
+void QmlAbstractAnimation::timelineComplete()
+{
+ Q_D(QmlAbstractAnimation);
+ setRunning(false);
+ if (d->alwaysRunToEnd && d->repeat) {
+ qtAnimation()->setLoopCount(-1);
+ }
+}
+
+/*!
+ \qmlclass PauseAnimation QmlPauseAnimation
+ \inherits Animation
+ \brief The PauseAnimation element provides a pause for an animation.
+
+ When used in a SequentialAnimation, PauseAnimation is a step when
+ nothing happens, for a specified duration.
+
+ A 500ms animation sequence, with a 100ms pause between two animations:
+ \code
+ SequentialAnimation {
+ NumberAnimation { ... duration: 200 }
+ PauseAnimation { duration: 100 }
+ NumberAnimation { ... duration: 200 }
+ }
+ \endcode
+*/
+/*!
+ \internal
+ \class QmlPauseAnimation
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,PauseAnimation,QmlPauseAnimation)
+QmlPauseAnimation::QmlPauseAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlPauseAnimationPrivate), parent)
+{
+ Q_D(QmlPauseAnimation);
+ d->init();
+}
+
+QmlPauseAnimation::~QmlPauseAnimation()
+{
+}
+
+void QmlPauseAnimationPrivate::init()
+{
+ Q_Q(QmlPauseAnimation);
+ pa = new QPauseAnimation;
+ QmlGraphics_setParent_noEvent(pa, q);
+}
+
+/*!
+ \qmlproperty int PauseAnimation::duration
+ This property holds the duration of the pause in milliseconds
+
+ The default value is 250.
+*/
+int QmlPauseAnimation::duration() const
+{
+ Q_D(const QmlPauseAnimation);
+ return d->pa->duration();
+}
+
+void QmlPauseAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qmlInfo(this) << tr("Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlPauseAnimation);
+ if (d->pa->duration() == duration)
+ return;
+ d->pa->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+QAbstractAnimation *QmlPauseAnimation::qtAnimation()
+{
+ Q_D(QmlPauseAnimation);
+ return d->pa;
+}
+
+/*!
+ \qmlclass ColorAnimation QmlColorAnimation
+ \inherits PropertyAnimation
+ \brief The ColorAnimation element allows you to animate color changes.
+
+ \code
+ ColorAnimation { from: "white"; to: "#c0c0c0"; duration: 100 }
+ \endcode
+
+ When used in a transition, ColorAnimation will by default animate
+ all properties of type color that are changing. If a property or properties
+ are explicitly set for the animation, then those will be used instead.
+*/
+/*!
+ \internal
+ \class QmlColorAnimation
+*/
+
+QmlColorAnimation::QmlColorAnimation(QObject *parent)
+: QmlPropertyAnimation(parent)
+{
+ Q_D(QmlPropertyAnimation);
+ d->interpolatorType = QMetaType::QColor;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+ d->defaultToInterpolatorType = true;
+}
+
+QmlColorAnimation::~QmlColorAnimation()
+{
+}
+
+/*!
+ \qmlproperty color ColorAnimation::from
+ This property holds the starting color.
+*/
+QColor QmlColorAnimation::from() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->from.value<QColor>();
+}
+
+void QmlColorAnimation::setFrom(const QColor &f)
+{
+ QmlPropertyAnimation::setFrom(f);
+}
+
+/*!
+ \qmlproperty color ColorAnimation::from
+ This property holds the ending color.
+*/
+QColor QmlColorAnimation::to() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->to.value<QColor>();
+}
+
+void QmlColorAnimation::setTo(const QColor &t)
+{
+ QmlPropertyAnimation::setTo(t);
+}
+
+QML_DEFINE_TYPE(Qt,4,6,ColorAnimation,QmlColorAnimation)
+
+/*!
+ \qmlclass ScriptAction QmlScriptAction
+ \inherits Animation
+ \brief The ScriptAction element allows scripts to be run during an animation.
+
+*/
+/*!
+ \internal
+ \class QmlScriptAction
+*/
+QmlScriptAction::QmlScriptAction(QObject *parent)
+ :QmlAbstractAnimation(*(new QmlScriptActionPrivate), parent)
+{
+ Q_D(QmlScriptAction);
+ d->init();
+}
+
+QmlScriptAction::~QmlScriptAction()
+{
+}
+
+void QmlScriptActionPrivate::init()
+{
+ Q_Q(QmlScriptAction);
+ rsa = new QActionAnimation(&proxy);
+ QmlGraphics_setParent_noEvent(rsa, q);
+}
+
+/*!
+ \qmlproperty script ScriptAction::script
+ This property holds the script to run.
+*/
+QmlScriptString QmlScriptAction::script() const
+{
+ Q_D(const QmlScriptAction);
+ return d->script;
+}
+
+void QmlScriptAction::setScript(const QmlScriptString &script)
+{
+ Q_D(QmlScriptAction);
+ d->script = script;
+}
+
+/*!
+ \qmlproperty QString ScriptAction::stateChangeScriptName
+ This property holds the the name of the StateChangeScript to run.
+
+ This property is only valid when ScriptAction is used as part of a transition.
+ If both script and stateChangeScriptName are set, stateChangeScriptName will be used.
+*/
+QString QmlScriptAction::stateChangeScriptName() const
+{
+ Q_D(const QmlScriptAction);
+ return d->name;
+}
+
+void QmlScriptAction::setStateChangeScriptName(const QString &name)
+{
+ Q_D(QmlScriptAction);
+ d->name = name;
+}
+
+void QmlScriptActionPrivate::execute()
+{
+ QmlScriptString scriptStr = hasRunScriptScript ? runScriptScript : script;
+
+ const QString &str = scriptStr.script();
+ if (!str.isEmpty()) {
+ QmlExpression expr(scriptStr.context(), str, scriptStr.scopeObject());
+ expr.setTrackChange(false);
+ expr.value();
+ }
+}
+
+void QmlScriptAction::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlScriptAction);
+ Q_UNUSED(modified);
+ Q_UNUSED(direction);
+
+ d->hasRunScriptScript = false;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QmlAction &action = actions[ii];
+
+ if (action.event && action.event->typeName() == QLatin1String("StateChangeScript")
+ && static_cast<QmlStateChangeScript*>(action.event)->name() == d->name) {
+ //### how should we handle reverse direction?
+ d->runScriptScript = static_cast<QmlStateChangeScript*>(action.event)->script();
+ d->hasRunScriptScript = true;
+ action.actionDone = true;
+ break; //assumes names are unique
+ }
+ }
+}
+
+QAbstractAnimation *QmlScriptAction::qtAnimation()
+{
+ Q_D(QmlScriptAction);
+ return d->rsa;
+}
+
+QML_DEFINE_TYPE(Qt,4,6,ScriptAction,QmlScriptAction)
+
+/*!
+ \qmlclass PropertyAction QmlPropertyAction
+ \inherits Animation
+ \brief The PropertyAction element allows immediate property changes during animation.
+
+ Explicitly set \c theimage.smooth=true during a transition:
+ \code
+ PropertyAction { target: theimage; property: "smooth"; value: true }
+ \endcode
+
+ Set \c thewebview.url to the value set for the destination state:
+ \code
+ PropertyAction { matchTargets: thewebview; matchProperties: "url" }
+ \endcode
+
+ The PropertyAction is immediate -
+ the target property is not animated to the selected value in any way.
+*/
+/*!
+ \internal
+ \class QmlPropertyAction
+*/
+QmlPropertyAction::QmlPropertyAction(QObject *parent)
+: QmlAbstractAnimation(*(new QmlPropertyActionPrivate), parent)
+{
+ Q_D(QmlPropertyAction);
+ d->init();
+}
+
+QmlPropertyAction::~QmlPropertyAction()
+{
+}
+
+void QmlPropertyActionPrivate::init()
+{
+ Q_Q(QmlPropertyAction);
+ spa = new QActionAnimation;
+ QmlGraphics_setParent_noEvent(spa, q);
+}
+
+/*!
+ \qmlproperty Object PropertyAction::target
+ This property holds an explicit target object to animate.
+
+ The exact effect of the \c target property depends on how the animation
+ is being used. Refer to the \l animation documentation for details.
+*/
+
+QObject *QmlPropertyAction::target() const
+{
+ Q_D(const QmlPropertyAction);
+ return d->target;
+}
+
+void QmlPropertyAction::setTarget(QObject *o)
+{
+ Q_D(QmlPropertyAction);
+ if (d->target == o)
+ return;
+
+ d->target = o;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = d->createProperty(d->target, d->propertyName, this);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlproperty string PropertyAction::property
+ This property holds an explicit property to animated.
+
+ The exact effect of the \c property property depends on how the animation
+ is being used. Refer to the \l animation documentation for details.
+*/
+
+QString QmlPropertyAction::property() const
+{
+ Q_D(const QmlPropertyAction);
+ return d->propertyName;
+}
+
+void QmlPropertyAction::setProperty(const QString &n)
+{
+ Q_D(QmlPropertyAction);
+ if (d->propertyName == n)
+ return;
+
+ d->propertyName = n;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = d->createProperty(d->target, d->propertyName, this);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlproperty string PropertyAction::matchProperties
+ This property holds a comma-separated list of property names this action
+ will match against. These names are used in conjunction with matchTargets
+ to create a list of properties that the action will set, assuming those
+ properties have changed.
+
+ This property is typically used for an action appearing as part of a Transition.
+
+ By default, no property names will be matched.
+
+ \sa matchTargets PropertyAnimation::matchProperties
+*/
+QString QmlPropertyAction::properties() const
+{
+ Q_D(const QmlPropertyAction);
+ return d->properties;
+}
+
+void QmlPropertyAction::setProperties(const QString &p)
+{
+ Q_D(QmlPropertyAction);
+ if (d->properties == p)
+ return;
+ d->properties = p;
+ emit propertiesChanged(p);
+}
+
+/*!
+ \qmlproperty list<Object> PropertyAction::matchTargets
+ This property holds a list of objects this action will match against.
+ These objects are used in conjunction with matchProperties to create a list of properties
+ that the action will set, assuming those properties have changed.
+
+ This property is typically used for an action appearing as part of a Transition.
+
+ By default, all changing targets will be matched.
+
+ \sa exclude matchProperties PropertyAnimation::matchTargets
+*/
+QList<QObject *> *QmlPropertyAction::targets()
+{
+ Q_D(QmlPropertyAction);
+ return &d->targets;
+}
+
+/*!
+ \qmlproperty list<Object> PropertyAction::exclude
+ This property holds the objects not to be affected by this animation.
+ \sa matchTargets
+*/
+QList<QObject *> *QmlPropertyAction::exclude()
+{
+ Q_D(QmlPropertyAction);
+ return &d->exclude;
+}
+
+/*!
+ \qmlproperty any PropertyAction::value
+ This property holds the value to be set on the property.
+ If not set, then the value defined for the end state of the transition.
+*/
+QVariant QmlPropertyAction::value() const
+{
+ Q_D(const QmlPropertyAction);
+ return d->value;
+}
+
+void QmlPropertyAction::setValue(const QVariant &v)
+{
+ Q_D(QmlPropertyAction);
+ if (d->value.isNull || d->value != v) {
+ d->value = v;
+ emit valueChanged(v);
+ }
+}
+
+void QmlPropertyActionPrivate::doAction()
+{
+ property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+}
+
+QAbstractAnimation *QmlPropertyAction::qtAnimation()
+{
+ Q_D(QmlPropertyAction);
+ return d->spa;
+}
+
+void QmlPropertyAction::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlPropertyAction);
+
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ d->spa->setAnimAction(&d->proxy, QAbstractAnimation::KeepWhenStopped);
+}
+
+void QmlPropertyAction::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlPropertyAction);
+ Q_UNUSED(direction);
+
+ struct QmlSetPropertyAnimationAction : public QAbstractAnimationAction
+ {
+ QmlStateActions actions;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const QmlAction &action = actions.at(ii);
+ action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ }
+ }
+ };
+
+ QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+
+ bool hasSelectors = !props.isEmpty() || !d->targets.isEmpty() || !d->exclude.isEmpty();
+ bool hasTarget = !d->propertyName.isEmpty() || d->target;
+
+ if (hasSelectors && hasTarget) {
+ qmlInfo(this) << tr("matchTargets/matchProperties/exclude and target/property are mutually exclusive.");
+ return;
+ }
+
+ QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction;
+
+ bool hasExplicit = false;
+ if (hasTarget && d->value.isValid()) {
+ QmlAction myAction;
+ myAction.property = d->createProperty(target(), d->propertyName, this);
+ if (myAction.property.isValid()) {
+ myAction.toValue = d->value;
+ data->actions << myAction;
+ hasExplicit = true;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QmlAction &action = actions[ii];
+ if (action.property.object() == myAction.property.object() &&
+ myAction.property.name() == action.property.name()) {
+ modified << action.property;
+ break; //### any chance there could be multiples?
+ }
+ }
+ }
+ }
+
+ if (!hasExplicit)
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QmlAction &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+ QObject *sObj = action.specifiedObject;
+ QString sPropertyName = action.specifiedProperty;
+ bool same = (obj == sObj);
+
+ if ((d->targets.isEmpty() || d->targets.contains(obj) || (!same && d->targets.contains(sObj))) &&
+ (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
+ (props.contains(propertyName) || (!same && props.contains(sPropertyName)))) {
+ QmlAction myAction = action;
+
+ if (d->value.isValid())
+ myAction.toValue = d->value;
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ } else if (d->userProperty.isValid() &&
+ !hasSelectors && !hasTarget) {
+ if ((d->userProperty.value.object() == obj || (!same && d->userProperty.value.object() == sObj)) &&
+ (d->userProperty.value.name() == propertyName || (!same && d->userProperty.value.name() == sPropertyName))) {
+ //### same as above. merge
+ QmlAction myAction = action;
+
+ if (d->value.isValid())
+ myAction.toValue = d->value;
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+ }
+
+ if (data->actions.count()) {
+ d->spa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,PropertyAction,QmlPropertyAction)
+
+/*!
+ \qmlclass ParentAction QmlParentAction
+ \inherits Animation
+ \brief The ParentAction element allows parent changes during animation.
+
+ ParentAction provides a way to specify at what point in a Transition a ParentChange should
+ occur.
+ \qml
+ State {
+ ParentChange {
+ target: myItem
+ parent: newParent
+ }
+ }
+ Transition {
+ SequentialAnimation {
+ PropertyAnimation { ... }
+ ParentAction {} //reparent myItem now
+ PropertyAnimation { ... }
+ }
+ }
+ \endqml
+
+ It also provides a way to explicitly reparent an item during an animation.
+ \qml
+ SequentialAnimation {
+ ParentAction { target: myItem; parent: newParent }
+ PropertyAnimation {}
+ }
+ \endqml
+
+ The ParentAction is immediate - it is not animated in any way.
+*/
+
+QmlParentAction::QmlParentAction(QObject *parent)
+: QmlAbstractAnimation(*(new QmlParentActionPrivate), parent)
+{
+ Q_D(QmlParentAction);
+ d->init();
+}
+
+QmlParentAction::~QmlParentAction()
+{
+}
+
+void QmlParentActionPrivate::init()
+{
+ Q_Q(QmlParentAction);
+ cpa = new QActionAnimation;
+ QmlGraphics_setParent_noEvent(cpa, q);
+}
+
+/*!
+ \qmlproperty Item ParentAction::target
+
+ This property holds an explicit target item to reparent.
+ */
+QmlGraphicsItem *QmlParentAction::object() const
+{
+ Q_D(const QmlParentAction);
+ return d->pcTarget;
+}
+
+void QmlParentAction::setObject(QmlGraphicsItem *target)
+{
+ Q_D(QmlParentAction);
+ d->pcTarget = target;
+}
+
+/*!
+ \qmlproperty Item ParentAction::matchTarget
+ This property holds the item this action will match against -- the item
+ that the action will reparent, assuming its parent has changed.
+
+ In the following example, \c myItem will be reparented by the ParentAction, while
+ \c myOtherItem will not.
+ \qml
+ State {
+ ParentChange {
+ target: myItem
+ parent: newParent
+ }
+ ParentChange {
+ target: myOtherItem
+ parent: otherNewParent
+ }
+ }
+ Transition {
+ SequentialAnimation {
+ PropertyAnimation { ... }
+ ParentAction { matchTargets: myItem }
+ PropertyAnimation { ... }
+ }
+ }
+ \endqml
+
+ This property is typically used for an action appearing as part of a Transition.
+ */
+QmlGraphicsItem *QmlParentAction::matchTarget() const
+{
+ Q_D(const QmlParentAction);
+ return d->pcTarget;
+}
+
+void QmlParentAction::setMatchTarget(QmlGraphicsItem *target)
+{
+ Q_D(QmlParentAction);
+ d->pcMatchTarget = target;
+}
+
+/*!
+ \qmlproperty Item ParentAction::parent
+
+ The item to reparent to (i.e. the new parent).
+ */
+QmlGraphicsItem *QmlParentAction::parent() const
+{
+ Q_D(const QmlParentAction);
+ return d->pcParent;
+}
+
+void QmlParentAction::setParent(QmlGraphicsItem *parent)
+{
+ Q_D(QmlParentAction);
+ d->pcParent = parent;
+}
+
+void QmlParentActionPrivate::doAction()
+{
+ QmlParentChange pc;
+ pc.setObject(pcTarget);
+ pc.setParent(pcParent);
+ pc.execute();
+}
+
+QAbstractAnimation *QmlParentAction::qtAnimation()
+{
+ Q_D(QmlParentAction);
+ return d->cpa;
+}
+
+void QmlParentAction::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlParentAction);
+ Q_UNUSED(modified);
+ Q_UNUSED(direction);
+
+ struct QmlParentActionData : public QAbstractAnimationAction
+ {
+ QmlParentActionData(): pc(0) {}
+ ~QmlParentActionData() { delete pc; }
+
+ QmlStateActions actions;
+ bool reverse;
+ QmlParentChange *pc;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const QmlAction &action = actions.at(ii);
+ if (reverse)
+ action.event->reverse();
+ else
+ action.event->execute();
+ }
+ }
+ };
+
+ QmlParentActionData *data = new QmlParentActionData;
+
+ if (d->pcTarget && d->pcMatchTarget) {
+ qmlInfo(this) << tr("matchTarget and target are mutually exclusive.");
+ return;
+ }
+
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QmlAction &action = actions[ii];
+
+ if (action.event && action.event->typeName() == QLatin1String("ParentChange")
+ && !d->pcTarget
+ && (!d->pcMatchTarget || static_cast<QmlParentChange*>(action.event)->object() == d->pcMatchTarget)) {
+ QmlAction myAction = action;
+ data->reverse = action.reverseEvent;
+ //### this logic differs from PropertyAnimation
+ // (probably a result of modified vs. done)
+ if (d->pcParent) {
+ //### should we disallow this case?
+ QmlParentChange *pc = new QmlParentChange;
+ pc->setObject(d->pcTarget);
+ pc->setParent(static_cast<QmlParentChange*>(action.event)->parent());
+ myAction.event = pc;
+ data->pc = pc;
+ data->actions << myAction;
+ break; //only match one
+ } else {
+ action.actionDone = true;
+ data->actions << myAction;
+ }
+ }
+ }
+
+ if (d->pcTarget && d->pcParent) {
+ data->reverse = false;
+ QmlAction myAction;
+ QmlParentChange *pc = new QmlParentChange;
+ pc->setObject(d->pcTarget);
+ pc->setParent(d->pcParent);
+ myAction.event = pc;
+ data->pc = pc;
+ data->actions << myAction;
+ }
+
+ if (data->actions.count()) {
+ d->cpa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,ParentAction,QmlParentAction)
+
+/*!
+ \qmlclass NumberAnimation QmlNumberAnimation
+ \inherits PropertyAnimation
+ \brief The NumberAnimation element allows you to animate changes in properties of type qreal.
+
+ Animate a set of properties over 200ms, from their values in the start state to
+ their values in the end state of the transition:
+ \code
+ NumberAnimation { matchProperties: "x,y,scale"; duration: 200 }
+ \endcode
+*/
+
+/*!
+ \internal
+ \class QmlNumberAnimation
+*/
+
+QmlNumberAnimation::QmlNumberAnimation(QObject *parent)
+: QmlPropertyAnimation(parent)
+{
+ Q_D(QmlPropertyAnimation);
+ d->interpolatorType = QMetaType::QReal;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+}
+
+QmlNumberAnimation::~QmlNumberAnimation()
+{
+}
+
+/*!
+ \qmlproperty real NumberAnimation::from
+ This property holds the starting value.
+ If not set, then the value defined in the start state of the transition.
+*/
+qreal QmlNumberAnimation::from() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->from.toReal();
+}
+
+void QmlNumberAnimation::setFrom(qreal f)
+{
+ QmlPropertyAnimation::setFrom(f);
+}
+
+/*!
+ \qmlproperty real NumberAnimation::to
+ This property holds the ending value.
+ If not set, then the value defined in the end state of the transition.
+*/
+qreal QmlNumberAnimation::to() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->to.toReal();
+}
+
+void QmlNumberAnimation::setTo(qreal t)
+{
+ QmlPropertyAnimation::setTo(t);
+}
+
+QML_DEFINE_TYPE(Qt,4,6,NumberAnimation,QmlNumberAnimation)
+
+/*!
+ \qmlclass Vector3dAnimation QmlVector3dAnimation
+ \inherits PropertyAnimation
+ \brief The Vector3dAnimation element allows you to animate changes in properties of type QVector3d.
+*/
+
+/*!
+ \internal
+ \class QmlVector3dAnimation
+*/
+
+QmlVector3dAnimation::QmlVector3dAnimation(QObject *parent)
+: QmlPropertyAnimation(parent)
+{
+ Q_D(QmlPropertyAnimation);
+ d->interpolatorType = QMetaType::QVector3D;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+ d->defaultToInterpolatorType = true;
+}
+
+QmlVector3dAnimation::~QmlVector3dAnimation()
+{
+}
+
+/*!
+ \qmlproperty real Vector3dAnimation::from
+ This property holds the starting value.
+ If not set, then the value defined in the start state of the transition.
+*/
+QVector3D QmlVector3dAnimation::from() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->from.value<QVector3D>();
+}
+
+void QmlVector3dAnimation::setFrom(QVector3D f)
+{
+ QmlPropertyAnimation::setFrom(f);
+}
+
+/*!
+ \qmlproperty real Vector3dAnimation::to
+ This property holds the ending value.
+ If not set, then the value defined in the end state of the transition.
+*/
+QVector3D QmlVector3dAnimation::to() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->to.value<QVector3D>();
+}
+
+void QmlVector3dAnimation::setTo(QVector3D t)
+{
+ QmlPropertyAnimation::setTo(t);
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Vector3dAnimation,QmlVector3dAnimation)
+
+QmlAnimationGroup::QmlAnimationGroup(QObject *parent)
+: QmlAbstractAnimation(*(new QmlAnimationGroupPrivate), parent)
+{
+}
+
+QmlAnimationGroup::~QmlAnimationGroup()
+{
+}
+
+QmlList<QmlAbstractAnimation *> *QmlAnimationGroup::animations()
+{
+ Q_D(QmlAnimationGroup);
+ return &d->animations;
+}
+
+/*!
+ \qmlclass SequentialAnimation QmlSequentialAnimation
+ \inherits Animation
+ \brief The SequentialAnimation element allows you to run animations sequentially.
+
+ Animations controlled in SequentialAnimation will be run one after the other.
+
+ The following example chains two numeric animations together. The \c MyItem
+ object will animate from its current x position to 100, and then back to 0.
+
+ \code
+ SequentialAnimation {
+ NumberAnimation { target: MyItem; property: "x"; to: 100 }
+ NumberAnimation { target: MyItem; property: "x"; to: 0 }
+ }
+ \endcode
+
+ \sa ParallelAnimation
+*/
+
+QmlSequentialAnimation::QmlSequentialAnimation(QObject *parent) :
+ QmlAnimationGroup(parent)
+{
+ Q_D(QmlAnimationGroup);
+ d->ag = new QSequentialAnimationGroup(this);
+}
+
+QmlSequentialAnimation::~QmlSequentialAnimation()
+{
+}
+
+void QmlSequentialAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlAnimationGroup);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->prepare(d->property);
+}
+
+QAbstractAnimation *QmlSequentialAnimation::qtAnimation()
+{
+ Q_D(QmlAnimationGroup);
+ return d->ag;
+}
+
+void QmlSequentialAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlAnimationGroup);
+
+ int inc = 1;
+ int from = 0;
+ if (direction == Backward) {
+ inc = -1;
+ from = d->animations.count() - 1;
+ }
+
+ //needed for Behavior
+ if (d->userProperty.isValid()) {
+ for (int i = 0; i < d->animations.count(); ++i)
+ d->animations.at(i)->setTarget(d->userProperty);
+ }
+
+ for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) {
+ d->animations.at(ii)->transition(actions, modified, direction);
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,SequentialAnimation,QmlSequentialAnimation)
+
+/*!
+ \qmlclass ParallelAnimation QmlParallelAnimation
+ \inherits Animation
+ \brief The ParallelAnimation element allows you to run animations in parallel.
+
+ Animations contained in ParallelAnimation will be run at the same time.
+
+ The following animation demonstrates animating the \c MyItem item
+ to (100,100) by animating the x and y properties in parallel.
+
+ \code
+ ParallelAnimation {
+ NumberAnimation { target: MyItem; property: "x"; to: 100 }
+ NumberAnimation { target: MyItem; property: "y"; to: 100 }
+ }
+ \endcode
+
+ \sa SequentialAnimation
+*/
+/*!
+ \internal
+ \class QmlParallelAnimation
+*/
+
+QmlParallelAnimation::QmlParallelAnimation(QObject *parent) :
+ QmlAnimationGroup(parent)
+{
+ Q_D(QmlAnimationGroup);
+ d->ag = new QParallelAnimationGroup(this);
+}
+
+QmlParallelAnimation::~QmlParallelAnimation()
+{
+}
+
+void QmlParallelAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlAnimationGroup);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->prepare(d->property);
+}
+
+QAbstractAnimation *QmlParallelAnimation::qtAnimation()
+{
+ Q_D(QmlAnimationGroup);
+ return d->ag;
+}
+
+void QmlParallelAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlAnimationGroup);
+
+ //needed for Behavior
+ if (d->userProperty.isValid()) {
+ for (int i = 0; i < d->animations.count(); ++i)
+ d->animations.at(i)->setTarget(d->userProperty);
+ }
+
+ for (int ii = 0; ii < d->animations.count(); ++ii) {
+ d->animations.at(ii)->transition(actions, modified, direction);
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,ParallelAnimation,QmlParallelAnimation)
+
+//convert a variant from string type to another animatable type
+void QmlPropertyAnimationPrivate::convertVariant(QVariant &variant, int type)
+{
+ if (variant.userType() != QVariant::String) {
+ variant.convert((QVariant::Type)type);
+ return;
+ }
+
+ switch (type) {
+ case QVariant::Rect: {
+ variant.setValue(QmlStringConverters::rectFFromString(variant.toString()).toRect());
+ break;
+ }
+ case QVariant::RectF: {
+ variant.setValue(QmlStringConverters::rectFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Point: {
+ variant.setValue(QmlStringConverters::pointFFromString(variant.toString()).toPoint());
+ break;
+ }
+ case QVariant::PointF: {
+ variant.setValue(QmlStringConverters::pointFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Size: {
+ variant.setValue(QmlStringConverters::sizeFFromString(variant.toString()).toSize());
+ break;
+ }
+ case QVariant::SizeF: {
+ variant.setValue(QmlStringConverters::sizeFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Color: {
+ variant.setValue(QmlStringConverters::colorFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Vector3D: {
+ variant.setValue(QmlStringConverters::vector3DFromString(variant.toString()));
+ break;
+ }
+ default:
+ if ((uint)type >= QVariant::UserType) {
+ QmlMetaType::StringConverter converter = QmlMetaType::customStringConverter(type);
+ if (converter)
+ variant = converter(variant.toString());
+ } else
+ variant.convert((QVariant::Type)type);
+ break;
+ }
+}
+
+/*!
+ \qmlclass PropertyAnimation QmlPropertyAnimation
+ \inherits Animation
+ \brief The PropertyAnimation element allows you to animate property changes.
+
+ Animate theObject's size property over 200ms, from its current size to 20-by-20:
+ \code
+ PropertyAnimation { target: theObject; property: "size"; to: "20x20"; duration: 200 }
+ \endcode
+
+ For an introduction to animation in QML, see \l{QML Animation}.
+*/
+
+QmlPropertyAnimation::QmlPropertyAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlPropertyAnimationPrivate), parent)
+{
+ Q_D(QmlPropertyAnimation);
+ d->init();
+}
+
+QmlPropertyAnimation::~QmlPropertyAnimation()
+{
+}
+
+void QmlPropertyAnimationPrivate::init()
+{
+ Q_Q(QmlPropertyAnimation);
+ va = new QmlTimeLineValueAnimator;
+ QmlGraphics_setParent_noEvent(va, q);
+}
+
+/*!
+ \qmlproperty int PropertyAnimation::duration
+ This property holds the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+int QmlPropertyAnimation::duration() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->va->duration();
+}
+
+void QmlPropertyAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qmlInfo(this) << tr("Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlPropertyAnimation);
+ if (d->va->duration() == duration)
+ return;
+ d->va->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty real PropertyAnimation::from
+ This property holds the starting value.
+ If not set, then the value defined in the start state of the transition.
+*/
+QVariant QmlPropertyAnimation::from() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->from;
+}
+
+void QmlPropertyAnimation::setFrom(const QVariant &f)
+{
+ Q_D(QmlPropertyAnimation);
+ if (d->fromIsDefined && f == d->from)
+ return;
+ d->from = f;
+ d->fromIsDefined = f.isValid();
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty real PropertyAnimation::to
+ This property holds the ending value.
+ If not set, then the value defined in the end state of the transition.
+*/
+QVariant QmlPropertyAnimation::to() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->to;
+}
+
+void QmlPropertyAnimation::setTo(const QVariant &t)
+{
+ Q_D(QmlPropertyAnimation);
+ if (d->toIsDefined && t == d->to)
+ return;
+ d->to = t;
+ d->toIsDefined = t.isValid();
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty string PropertyAnimation::easing
+ \brief the easing curve used for the transition.
+
+ Available values are:
+
+ \table
+ \row
+ \o \c easeLinear
+ \o Easing curve for a linear (t) function: velocity is constant.
+ \o \inlineimage qeasingcurve-linear.png
+ \row
+ \o \c easeInQuad
+ \o Easing curve for a quadratic (t^2) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inquad.png
+ \row
+ \o \c easeOutQuad
+ \o Easing curve for a quadratic (t^2) function: decelerating to zero velocity.
+ \o \inlineimage qeasingcurve-outquad.png
+ \row
+ \o \c easeInOutQuad
+ \o Easing curve for a quadratic (t^2) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutquad.png
+ \row
+ \o \c easeOutInQuad
+ \o Easing curve for a quadratic (t^2) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinquad.png
+ \row
+ \o \c easeInCubic
+ \o Easing curve for a cubic (t^3) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-incubic.png
+ \row
+ \o \c easeOutCubic
+ \o Easing curve for a cubic (t^3) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outcubic.png
+ \row
+ \o \c easeInOutCubic
+ \o Easing curve for a cubic (t^3) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutcubic.png
+ \row
+ \o \c easeOutInCubic
+ \o Easing curve for a cubic (t^3) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outincubic.png
+ \row
+ \o \c easeInQuart
+ \o Easing curve for a quartic (t^4) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inquart.png
+ \row
+ \o \c easeOutQuart
+ \o Easing curve for a cubic (t^4) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outquart.png
+ \row
+ \o \c easeInOutQuart
+ \o Easing curve for a cubic (t^4) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutquart.png
+ \row
+ \o \c easeOutInQuart
+ \o Easing curve for a cubic (t^4) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinquart.png
+ \row
+ \o \c easeInQuint
+ \o Easing curve for a quintic (t^5) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inquint.png
+ \row
+ \o \c easeOutQuint
+ \o Easing curve for a cubic (t^5) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outquint.png
+ \row
+ \o \c easeInOutQuint
+ \o Easing curve for a cubic (t^5) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutquint.png
+ \row
+ \o \c easeOutInQuint
+ \o Easing curve for a cubic (t^5) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinquint.png
+ \row
+ \o \c easeInSine
+ \o Easing curve for a sinusoidal (sin(t)) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-insine.png
+ \row
+ \o \c easeOutSine
+ \o Easing curve for a sinusoidal (sin(t)) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outsine.png
+ \row
+ \o \c easeInOutSine
+ \o Easing curve for a sinusoidal (sin(t)) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutsine.png
+ \row
+ \o \c easeOutInSine
+ \o Easing curve for a sinusoidal (sin(t)) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinsine.png
+ \row
+ \o \c easeInExpo
+ \o Easing curve for an exponential (2^t) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inexpo.png
+ \row
+ \o \c easeOutExpo
+ \o Easing curve for an exponential (2^t) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outexpo.png
+ \row
+ \o \c easeInOutExpo
+ \o Easing curve for an exponential (2^t) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutexpo.png
+ \row
+ \o \c easeOutInExpo
+ \o Easing curve for an exponential (2^t) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinexpo.png
+ \row
+ \o \c easeInCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-incirc.png
+ \row
+ \o \c easeOutCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outcirc.png
+ \row
+ \o \c easeInOutCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutcirc.png
+ \row
+ \o \c easeOutInCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outincirc.png
+ \row
+ \o \c easeInElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: accelerating from zero velocity.
+ \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \o \inlineimage qeasingcurve-inelastic.png
+ \row
+ \o \c easeOutElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: decelerating from zero velocity.
+ \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \o \inlineimage qeasingcurve-outelastic.png
+ \row
+ \o \c easeInOutElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutelastic.png
+ \row
+ \o \c easeOutInElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinelastic.png
+ \row
+ \o \c easeInBack
+ \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inback.png
+ \row
+ \o \c easeOutBack
+ \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity.
+ \o \inlineimage qeasingcurve-outback.png
+ \row
+ \o \c easeInOutBack
+ \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutback.png
+ \row
+ \o \c easeOutInBack
+ \o Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinback.png
+ \row
+ \o \c easeInBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inbounce.png
+ \row
+ \o \c easeOutBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outbounce.png
+ \row
+ \o \c easeInOutBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutbounce.png
+ \row
+ \o \c easeOutInBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinbounce.png
+ \endtable
+
+*/
+QString QmlPropertyAnimation::easing() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->easing;
+}
+
+void QmlPropertyAnimation::setEasing(const QString &e)
+{
+ Q_D(QmlPropertyAnimation);
+ if (d->easing == e)
+ return;
+
+ d->easing = e;
+ d->va->setEasingCurve(stringToCurve(d->easing, this));
+ emit easingChanged(e);
+}
+
+/*!
+ \qmlproperty Object PropertyAnimation::target
+ This property holds an explicit target object to animate.
+
+ target is used in conjunction with property to determine
+ what property should be animated.
+
+ \sa property matchTargets
+*/
+
+QObject *QmlPropertyAnimation::target() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->target;
+}
+
+void QmlPropertyAnimation::setTarget(QObject *o)
+{
+ Q_D(QmlPropertyAnimation);
+ if (d->target == o)
+ return;
+
+ d->target = o;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = d->createProperty(d->target, d->propertyName, this);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlproperty string PropertyAnimation::property
+ This property holds an explicit property name to animate.
+
+ property is used in conjunction with target to determine
+ what property should be animated.
+
+ \sa target matchProperties
+*/
+
+QString QmlPropertyAnimation::property() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->propertyName;
+}
+
+void QmlPropertyAnimation::setProperty(const QString &n)
+{
+ Q_D(QmlPropertyAnimation);
+ if (d->propertyName == n)
+ return;
+
+ d->propertyName = n;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = d->createProperty(d->target, d->propertyName, this);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlproperty string PropertyAnimation::matchProperties
+ This property holds a comma-separated list of property names this animation
+ will match against. These names are used in conjunction with matchTargets
+ to create a list of properties that the animation will animate, assuming those
+ properties have changed.
+
+ In the following example, the change in 'x' will be animated by the transition, while
+ the change in 'y' will not.
+ \qml
+ State {
+ PropertyChanges {
+ target: myItem
+ x: 15; y: 15
+ }
+ }
+ Transition {
+ PropertyAnimation {
+ matchProperties: "x"
+ }
+ }
+ \endqml
+
+ This property is typically used for an animation appearing as part of a Transition.
+
+ By default, no property names will be matched.
+
+ \sa matchTargets PropertyAction::matchTargets
+*/
+QString QmlPropertyAnimation::properties() const
+{
+ Q_D(const QmlPropertyAnimation);
+ return d->properties;
+}
+
+void QmlPropertyAnimation::setProperties(const QString &prop)
+{
+ Q_D(QmlPropertyAnimation);
+ if (d->properties == prop)
+ return;
+
+ d->properties = prop;
+ emit propertiesChanged(prop);
+}
+
+/*!
+ \qmlproperty list<Object> PropertyAnimation::matchTargets
+ This property holds a list of objects this animation will match against.
+ These objects are used in conjunction with matchProperties to create a list of properties
+ that the animation will animate, assuming those properties have changed.
+
+ In the following example, the changes to \c myItem will be animated by the transition, while
+ the changes to \c myOtherItem will not.
+ \qml
+ State {
+ PropertyChanges {
+ target: myItem
+ x: 15; y: 15
+ }
+ PropertyChanges {
+ target: myOtherItem
+ x: 30; y: 30
+ }
+ }
+ Transition {
+ PropertyAnimation {
+ matchTargets: myItem
+ matchProperties: "x,y"
+ }
+ }
+ \endqml
+
+ This property is typically used for an animation appearing as part of a Transition.
+
+ By default, all changing targets will be matched.
+
+ \sa exclude matchProperties
+*/
+QList<QObject *> *QmlPropertyAnimation::targets()
+{
+ Q_D(QmlPropertyAnimation);
+ return &d->targets;
+}
+
+/*!
+ \qmlproperty list<Object> PropertyAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa matchTargets
+*/
+QList<QObject *> *QmlPropertyAnimation::exclude()
+{
+ Q_D(QmlPropertyAnimation);
+ return &d->exclude;
+}
+
+void QmlPropertyAnimationPrivate::valueChanged(qreal r)
+{
+ if (!fromSourced) {
+ if (!fromIsDefined) {
+ from = property.read();
+ convertVariant(from, interpolatorType ? interpolatorType : property.propertyType());
+ //### check for invalid variant if using property type
+ }
+ fromSourced = true;
+ }
+
+ if (r == 1.) {
+ property.write(to, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ } else {
+ if (interpolator)
+ property.write(interpolator(from.constData(), to.constData(), r), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ }
+}
+
+QAbstractAnimation *QmlPropertyAnimation::qtAnimation()
+{
+ Q_D(QmlPropertyAnimation);
+ return d->va;
+}
+
+void QmlPropertyAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlPropertyAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ if (!d->rangeIsSet) {
+ d->va->setStartValue(qreal(0));
+ d->va->setEndValue(qreal(1));
+ d->rangeIsSet = true;
+ }
+
+ int propType = d->property.propertyType();
+ d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : propType);
+ if (d->fromIsDefined)
+ d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : propType);
+
+ if (!d->interpolatorType) {
+ //### check for invalid variants
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(propType);
+ }
+
+ d->fromSourced = false;
+ d->value.QmlTimeLineValue::setValue(0.);
+ d->va->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->va->setFromSourcedValue(&d->fromSourced);
+}
+
+void QmlPropertyAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlPropertyAnimation);
+ Q_UNUSED(direction);
+
+ struct PropertyUpdater : public QmlTimeLineValue
+ {
+ QmlStateActions actions;
+ int interpolatorType; //for Number/ColorAnimation
+ int prevInterpolatorType; //for generic
+ QVariantAnimation::Interpolator interpolator;
+ bool reverse;
+ bool *wasDeleted;
+ PropertyUpdater() : wasDeleted(0) {}
+ ~PropertyUpdater() { if (wasDeleted) *wasDeleted = true; }
+ void setValue(qreal v)
+ {
+ bool deleted = false;
+ wasDeleted = &deleted;
+ if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1
+ v = 1 - v;
+ QmlTimeLineValue::setValue(v);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QmlAction &action = actions[ii];
+
+ if (v == 1.)
+ action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ else {
+ if (action.fromValue.isNull()) {
+ action.fromValue = action.property.read();
+ if (interpolatorType)
+ QmlPropertyAnimationPrivate::convertVariant(action.fromValue, interpolatorType);
+ }
+ if (!interpolatorType) {
+ int propType = action.property.propertyType();
+ if (!prevInterpolatorType || prevInterpolatorType != propType) {
+ prevInterpolatorType = propType;
+ interpolator = QVariantAnimationPrivate::getInterpolator(prevInterpolatorType);
+ }
+ }
+ if (interpolator)
+ action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ }
+ if (deleted)
+ return;
+ }
+ wasDeleted = 0;
+ }
+ };
+
+ QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+
+ bool hasSelectors = !props.isEmpty() || !d->targets.isEmpty() || !d->exclude.isEmpty();
+ bool hasTarget = !d->propertyName.isEmpty() || d->target;
+
+ if (hasSelectors && hasTarget) {
+ qmlInfo(this) << tr("matchTargets/matchProperties/exclude and target/property are mutually exclusive.");
+ return;
+ }
+
+ bool useType = (props.isEmpty() && d->propertyName.isEmpty() && d->defaultToInterpolatorType) ? true : false;
+
+ PropertyUpdater *data = new PropertyUpdater;
+ data->interpolatorType = d->interpolatorType;
+ data->interpolator = d->interpolator;
+ data->reverse = direction == Backward ? true : false;
+
+ bool hasExplicit = false;
+ //an explicit animation has been specified
+ if (hasTarget && d->toIsDefined) {
+ QmlAction myAction;
+ myAction.property = d->createProperty(target(), d->propertyName, this);
+ if (myAction.property.isValid()) {
+ if (d->fromIsDefined) {
+ d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ myAction.fromValue = d->from;
+ }
+ d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ myAction.toValue = d->to;
+ data->actions << myAction;
+ hasExplicit = true;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QmlAction &action = actions[ii];
+ if (action.property.object() == myAction.property.object() &&
+ myAction.property.name() == action.property.name()) {
+ modified << action.property;
+ break; //### any chance there could be multiples?
+ }
+ }
+ }
+ }
+
+ if (!hasExplicit)
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QmlAction &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+ QObject *sObj = action.specifiedObject;
+ QString sPropertyName = action.specifiedProperty;
+ bool same = (obj == sObj);
+
+ if ((d->targets.isEmpty() || d->targets.contains(obj) || (!same && d->targets.contains(sObj))) &&
+ (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
+ (props.contains(propertyName) || (!same && props.contains(sPropertyName))
+ || (useType && action.property.propertyType() == d->interpolatorType))) {
+ QmlAction myAction = action;
+
+ if (d->fromIsDefined)
+ myAction.fromValue = d->from;
+ else
+ myAction.fromValue = QVariant();
+ if (d->toIsDefined)
+ myAction.toValue = d->to;
+
+ d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+
+ modified << action.property;
+
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ } else if (d->userProperty.isValid() &&
+ !hasSelectors && !hasTarget) {
+ if ((d->userProperty.value.object() == obj || (!same && d->userProperty.value.object() == sObj)) &&
+ (d->userProperty.value.name() == propertyName || (!same && d->userProperty.value.name() == sPropertyName))) {
+ //### same as above. merge
+ QmlAction myAction = action;
+
+ if (d->fromIsDefined)
+ myAction.fromValue = d->from;
+ else
+ myAction.fromValue = QVariant();
+ if (d->toIsDefined)
+ myAction.toValue = d->to;
+
+ d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+
+ modified << action.property;
+
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+ }
+
+ if (data->actions.count()) {
+ if (!d->rangeIsSet) {
+ d->va->setStartValue(qreal(0));
+ d->va->setEndValue(qreal(1));
+ d->rangeIsSet = true;
+ }
+ d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(Qt,4,6,PropertyAnimation,QmlPropertyAnimation)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h
new file mode 100644
index 0000000..6a69e4d
--- /dev/null
+++ b/src/declarative/util/qmlanimation_p.h
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLANIMATION_H
+#define QMLANIMATION_H
+
+#include "qmltransition_p.h"
+#include "qmlstate_p.h"
+#include <QtGui/qvector3d.h>
+
+#include <qmlpropertyvaluesource.h>
+#include <qml.h>
+#include <qmlscriptstring.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/QAbstractAnimation>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractAnimationPrivate;
+class QmlAnimationGroup;
+class Q_AUTOTEST_EXPORT QmlAbstractAnimation : public QObject, public QmlPropertyValueSource, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAbstractAnimation)
+
+ Q_INTERFACES(QmlParserStatus)
+ Q_INTERFACES(QmlPropertyValueSource)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged())
+ Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged)
+ Q_CLASSINFO("DefaultMethod", "start()")
+
+public:
+ QmlAbstractAnimation(QObject *parent=0);
+ virtual ~QmlAbstractAnimation();
+
+ bool isRunning() const;
+ void setRunning(bool);
+ bool isPaused() const;
+ void setPaused(bool);
+ bool alwaysRunToEnd() const;
+ void setAlwaysRunToEnd(bool);
+ bool repeat() const;
+ void setRepeat(bool);
+
+ int currentTime();
+ void setCurrentTime(int);
+
+ QmlAnimationGroup *group() const;
+ void setGroup(QmlAnimationGroup *);
+
+ virtual void setTarget(const QmlMetaProperty &);
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void started();
+ void completed();
+ void runningChanged(bool);
+ void pausedChanged(bool);
+ void repeatChanged(bool);
+ void alwaysRunToEndChanged(bool);
+
+public Q_SLOTS:
+ void restart();
+ void start();
+ void pause();
+ void resume();
+ void stop();
+ void complete();
+
+protected:
+ QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent);
+
+public:
+ enum TransitionDirection { Forward, Backward };
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual void prepare(QmlMetaProperty &);
+ virtual QAbstractAnimation *qtAnimation() = 0;
+
+private Q_SLOTS:
+ void timelineComplete();
+};
+
+class QmlPauseAnimationPrivate;
+class Q_AUTOTEST_EXPORT QmlPauseAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPauseAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+
+public:
+ QmlPauseAnimation(QObject *parent=0);
+ virtual ~QmlPauseAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+Q_SIGNALS:
+ void durationChanged(int);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QmlScriptActionPrivate;
+class QmlScriptAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlScriptAction)
+
+ Q_PROPERTY(QmlScriptString script READ script WRITE setScript)
+ Q_PROPERTY(QString stateChangeScriptName READ stateChangeScriptName WRITE setStateChangeScriptName)
+
+public:
+ QmlScriptAction(QObject *parent=0);
+ virtual ~QmlScriptAction();
+
+ QmlScriptString script() const;
+ void setScript(const QmlScriptString &);
+
+ QString stateChangeScriptName() const;
+ void setStateChangeScriptName(const QString &);
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QmlPropertyActionPrivate;
+class QmlPropertyAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPropertyAction)
+
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged)
+ Q_PROPERTY(QString matchProperties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QList<QObject *>* matchTargets READ targets)
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ QmlPropertyAction(QObject *parent=0);
+ virtual ~QmlPropertyAction();
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *targets();
+ QList<QObject *> *exclude();
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &);
+ void propertiesChanged(const QString &);
+ void targetChanged(QObject *, const QString &);
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+
+class QmlGraphicsItem;
+class QmlParentActionPrivate;
+class QmlParentAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlParentAction)
+
+ Q_PROPERTY(QmlGraphicsItem *target READ object WRITE setObject)
+ Q_PROPERTY(QmlGraphicsItem *matchTarget READ matchTarget WRITE setMatchTarget)
+ Q_PROPERTY(QmlGraphicsItem *parent READ parent WRITE setParent)
+
+public:
+ QmlParentAction(QObject *parent=0);
+ virtual ~QmlParentAction();
+
+ QmlGraphicsItem *object() const;
+ void setObject(QmlGraphicsItem *);
+
+ QmlGraphicsItem *matchTarget() const;
+ void setMatchTarget(QmlGraphicsItem *);
+
+ QmlGraphicsItem *parent() const;
+ void setParent(QmlGraphicsItem *);
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QmlPropertyAnimationPrivate;
+class Q_AUTOTEST_EXPORT QmlPropertyAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPropertyAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QVariant from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(QVariant to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged)
+ Q_PROPERTY(QString matchProperties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QList<QObject *>* matchTargets READ targets)
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude)
+
+public:
+ QmlPropertyAnimation(QObject *parent=0);
+ virtual ~QmlPropertyAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+ QVariant from() const;
+ void setFrom(const QVariant &);
+
+ QVariant to() const;
+ void setTo(const QVariant &);
+
+ QString easing() const;
+ void setEasing(const QString &);
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *targets();
+ QList<QObject *> *exclude();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(QVariant);
+ void toChanged(QVariant);
+ void easingChanged(const QString &);
+ void propertiesChanged(const QString &);
+ void targetChanged(QObject *, const QString &);
+};
+
+class Q_AUTOTEST_EXPORT QmlColorAnimation : public QmlPropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPropertyAnimation)
+ Q_PROPERTY(QColor from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(QColor to READ to WRITE setTo NOTIFY toChanged)
+
+public:
+ QmlColorAnimation(QObject *parent=0);
+ virtual ~QmlColorAnimation();
+
+ QColor from() const;
+ void setFrom(const QColor &);
+
+ QColor to() const;
+ void setTo(const QColor &);
+};
+
+class Q_AUTOTEST_EXPORT QmlNumberAnimation : public QmlPropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPropertyAnimation)
+
+ Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged)
+
+public:
+ QmlNumberAnimation(QObject *parent=0);
+ virtual ~QmlNumberAnimation();
+
+ qreal from() const;
+ void setFrom(qreal);
+
+ qreal to() const;
+ void setTo(qreal);
+};
+
+class Q_AUTOTEST_EXPORT QmlVector3dAnimation : public QmlPropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPropertyAnimation)
+
+ Q_PROPERTY(QVector3D from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(QVector3D to READ to WRITE setTo NOTIFY toChanged)
+
+public:
+ QmlVector3dAnimation(QObject *parent=0);
+ virtual ~QmlVector3dAnimation();
+
+ QVector3D from() const;
+ void setFrom(QVector3D);
+
+ QVector3D to() const;
+ void setTo(QVector3D);
+};
+
+class QmlAnimationGroupPrivate;
+class QmlAnimationGroup : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup)
+
+ Q_CLASSINFO("DefaultProperty", "animations")
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *> *animations READ animations)
+
+public:
+ QmlAnimationGroup(QObject *parent);
+ virtual ~QmlAnimationGroup();
+
+ QmlList<QmlAbstractAnimation *>* animations();
+ friend class QmlAbstractAnimation;
+};
+
+class QmlSequentialAnimation : public QmlAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup)
+
+public:
+ QmlSequentialAnimation(QObject *parent=0);
+ virtual ~QmlSequentialAnimation();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+
+class QmlParallelAnimation : public QmlAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup)
+
+public:
+ QmlParallelAnimation(QObject *parent=0);
+ virtual ~QmlParallelAnimation();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlAbstractAnimation)
+QML_DECLARE_TYPE(QmlPauseAnimation)
+QML_DECLARE_TYPE(QmlScriptAction)
+QML_DECLARE_TYPE(QmlPropertyAction)
+QML_DECLARE_TYPE(QmlParentAction)
+QML_DECLARE_TYPE(QmlPropertyAnimation)
+QML_DECLARE_TYPE(QmlColorAnimation)
+QML_DECLARE_TYPE(QmlNumberAnimation)
+QML_DECLARE_TYPE(QmlSequentialAnimation)
+QML_DECLARE_TYPE(QmlParallelAnimation)
+QML_DECLARE_TYPE(QmlVector3dAnimation)
+
+QT_END_HEADER
+
+#endif // QMLANIMATION_H
diff --git a/src/declarative/util/qmlanimation_p_p.h b/src/declarative/util/qmlanimation_p_p.h
new file mode 100644
index 0000000..d680194
--- /dev/null
+++ b/src/declarative/util/qmlanimation_p_p.h
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLANIMATION_P_H
+#define QMLANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlanimation_p.h"
+
+#include "qmlnullablevalue_p_p.h"
+#include "qmltimeline_p_p.h"
+
+#include <qml.h>
+#include <qmlcontext.h>
+
+#include <QtCore/QPauseAnimation>
+#include <QtCore/QVariantAnimation>
+#include <QtCore/QAnimationGroup>
+#include <QtGui/QColor>
+#include <QDebug>
+
+#include <private/qobject_p.h>
+#include <private/qvariantanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//interface for classes that provide animation actions for QActionAnimation
+class QAbstractAnimationAction
+{
+public:
+ virtual ~QAbstractAnimationAction() {}
+ virtual void doAction() = 0;
+};
+
+//templated animation action
+//allows us to specify an action that calls a function of a class.
+//(so that class doesn't have to inherit QmlAbstractAnimationAction)
+template<class T, void (T::*method)()>
+class QAnimationActionProxy : public QAbstractAnimationAction
+{
+public:
+ QAnimationActionProxy(T *p) : m_p(p) {}
+ virtual void doAction() { (m_p->*method)(); }
+
+private:
+ T *m_p;
+};
+
+//performs an action of type QAbstractAnimationAction
+class QActionAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+public:
+ QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped), running(false) {}
+ QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0)
+ : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped), running(false) {}
+ ~QActionAnimation() { if (policy == DeleteWhenStopped) { delete animAction; animAction = 0; } }
+ virtual int duration() const { return 0; }
+ void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ animAction = action;
+ policy = p;
+ }
+protected:
+ virtual void updateCurrentTime(int) {}
+
+ virtual void updateState(State newState, State /*oldState*/)
+ {
+ if (newState == Running) {
+ if (animAction) {
+ running = true;
+ animAction->doAction();
+ running = false;
+ if (state() == Stopped && policy == DeleteWhenStopped) {
+ delete animAction;
+ animAction = 0;
+ }
+ }
+ } else if (newState == Stopped && policy == DeleteWhenStopped) {
+ if (!running) {
+ delete animAction;
+ animAction = 0;
+ }
+ }
+ }
+
+private:
+ QAbstractAnimationAction *animAction;
+ DeletionPolicy policy;
+ bool running;
+};
+
+//animates QmlTimeLineValue (assumes start and end values will be reals or compatible)
+class QmlTimeLineValueAnimator : public QVariantAnimation
+{
+ Q_OBJECT
+public:
+ QmlTimeLineValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {}
+ ~QmlTimeLineValueAnimator() { if (policy == DeleteWhenStopped) { delete animValue; animValue = 0; } }
+ void setAnimValue(QmlTimeLineValue *value, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ animValue = value;
+ policy = p;
+ }
+ void setFromSourcedValue(bool *value)
+ {
+ fromSourced = value;
+ }
+protected:
+ virtual void updateCurrentValue(const QVariant &value)
+ {
+ if (animValue)
+ animValue->setValue(value.toReal());
+ }
+ virtual void updateState(State newState, State oldState)
+ {
+ QVariantAnimation::updateState(newState, oldState);
+ if (newState == Running) {
+ //check for new from every loop
+ if (fromSourced)
+ *fromSourced = false;
+ } else if (newState == Stopped && policy == DeleteWhenStopped) {
+ delete animValue;
+ animValue = 0;
+ }
+ }
+
+private:
+ QmlTimeLineValue *animValue;
+ bool *fromSourced;
+ DeletionPolicy policy;
+};
+
+//an animation that just gives a tick
+template<class T, void (T::*method)(int)>
+class QTickAnimationProxy : public QAbstractAnimation
+{
+ //Q_OBJECT //doesn't work with templating
+public:
+ QTickAnimationProxy(T *p, QObject *parent = 0) : QAbstractAnimation(parent), m_p(p) {}
+ virtual int duration() const { return -1; }
+protected:
+ virtual void updateCurrentTime(int msec) { (m_p->*method)(msec); }
+
+private:
+ T *m_p;
+};
+
+class QmlAbstractAnimationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlAbstractAnimation)
+public:
+ QmlAbstractAnimationPrivate()
+ : running(false), paused(false), alwaysRunToEnd(false), repeat(false),
+ connectedTimeLine(false), componentComplete(true), startOnCompletion(false),
+ avoidPropertyValueSourceStart(false), group(0) {}
+
+ bool running:1;
+ bool paused:1;
+ bool alwaysRunToEnd:1;
+ bool repeat:1;
+ bool connectedTimeLine:1;
+
+ bool componentComplete:1;
+ bool startOnCompletion:1;
+ bool avoidPropertyValueSourceStart:1;
+
+ void commence();
+
+ QmlNullableValue<QmlMetaProperty> userProperty;
+
+ QmlMetaProperty property;
+ QmlAnimationGroup *group;
+
+ static QmlMetaProperty createProperty(QObject *obj, const QString &str, QObject *infoObj);
+};
+
+class QmlPauseAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPauseAnimation)
+public:
+ QmlPauseAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), pa(0) {}
+
+ void init();
+
+ QPauseAnimation *pa;
+};
+
+class QmlScriptActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlScriptAction)
+public:
+ QmlScriptActionPrivate()
+ : QmlAbstractAnimationPrivate(), hasRunScriptScript(false), proxy(this), rsa(0) {}
+
+ void init();
+
+ QmlScriptString script;
+ QString name;
+ QmlScriptString runScriptScript;
+ bool hasRunScriptScript;
+
+ void execute();
+
+ QAnimationActionProxy<QmlScriptActionPrivate,
+ &QmlScriptActionPrivate::execute> proxy;
+ QActionAnimation *rsa;
+};
+
+class QmlPropertyActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPropertyAction)
+public:
+ QmlPropertyActionPrivate()
+ : QmlAbstractAnimationPrivate(), target(0), proxy(this), spa(0) {}
+
+ void init();
+
+ QObject *target;
+ QString propertyName;
+ QString properties;
+ QList<QObject *> targets;
+ QList<QObject *> exclude;
+
+ QmlNullableValue<QVariant> value;
+
+ void doAction();
+
+ QAnimationActionProxy<QmlPropertyActionPrivate,
+ &QmlPropertyActionPrivate::doAction> proxy;
+ QActionAnimation *spa;
+};
+
+class QmlParentActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlParentAction)
+public:
+ QmlParentActionPrivate()
+ : QmlAbstractAnimationPrivate(), pcTarget(0), pcMatchTarget(0), pcParent(0) {}
+
+ void init();
+
+ QmlGraphicsItem *pcTarget;
+ QmlGraphicsItem *pcMatchTarget;
+ QmlGraphicsItem *pcParent;
+
+ void doAction();
+ QActionAnimation *cpa;
+};
+
+class QmlAnimationGroupPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlAnimationGroup)
+public:
+ QmlAnimationGroupPrivate()
+ : QmlAbstractAnimationPrivate(), animations(this), ag(0) {}
+
+ struct AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ AnimationList(QmlAnimationGroupPrivate *p)
+ : anim(p) {}
+ virtual void append(QmlAbstractAnimation *a) {
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ a->setGroup(anim->q_func());
+ }
+ virtual void clear()
+ {
+ for (int i = 0; i < count(); ++i)
+ at(i)->setGroup(0);
+ QmlConcreteList<QmlAbstractAnimation *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ at(i)->setGroup(0);
+ QmlConcreteList<QmlAbstractAnimation *>::removeAt(i);
+ }
+ virtual void insert(int i, QmlAbstractAnimation *a)
+ {
+ QmlConcreteList<QmlAbstractAnimation *>::insert(i, a);
+ a->setGroup(anim->q_func());
+ }
+
+ QmlAnimationGroupPrivate *anim;
+ };
+
+ AnimationList animations;
+ QAnimationGroup *ag;
+};
+
+class QmlPropertyAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPropertyAnimation)
+public:
+ QmlPropertyAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), target(0), fromSourced(false), fromIsDefined(false), toIsDefined(false),
+ rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0),
+ value(this, &QmlPropertyAnimationPrivate::valueChanged) {}
+
+ void init();
+
+ QVariant from;
+ QVariant to;
+
+ QString easing;
+
+ QObject *target;
+ QString propertyName;
+ QString properties;
+ QList<QObject *> targets;
+ QList<QObject *> exclude;
+
+ bool fromSourced;
+ bool fromIsDefined:1;
+ bool toIsDefined:1;
+ bool rangeIsSet:1;
+ bool defaultToInterpolatorType:1;
+ int interpolatorType;
+ QVariantAnimation::Interpolator interpolator;
+
+ QmlTimeLineValueAnimator *va;
+ virtual void valueChanged(qreal);
+
+ QmlTimeLineValueProxy<QmlPropertyAnimationPrivate> value;
+
+ static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress);
+ static void convertVariant(QVariant &variant, int type);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLANIMATION_P_H
diff --git a/src/declarative/util/qmlbehavior.cpp b/src/declarative/util/qmlbehavior.cpp
new file mode 100644
index 0000000..b9c77f5
--- /dev/null
+++ b/src/declarative/util/qmlbehavior.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlbehavior_p.h"
+
+#include "qmlanimation_p.h"
+#include "qmltransition_p.h"
+
+#include <qmlcontext.h>
+#include <qmlinfo.h>
+
+#include <QtCore/qparallelanimationgroup.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,Behavior,QmlBehavior)
+
+class QmlBehaviorPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlBehavior)
+public:
+ QmlBehaviorPrivate() : animation(0), enabled(true) {}
+
+ QmlMetaProperty property;
+ QVariant currentValue;
+ QmlAbstractAnimation *animation;
+ bool enabled;
+};
+
+/*!
+ \qmlclass Behavior QmlBehavior
+ \brief The Behavior element allows you to specify a default animation for a property change.
+
+ Behaviors provide one way to specify \l{qmlanimation.html}{animations} in QML.
+
+ In the example below, the rect will use a bounce easing curve over 200 millisecond for any changes to its y property:
+ \code
+ Rectangle {
+ width: 20; height: 20
+ color: "#00ff00"
+ y: 200 //initial value
+ y: Behavior {
+ NumberAnimation {
+ easing: "easeOutBounce(amplitude:100)"
+ duration: 200
+ }
+ }
+ }
+ \endcode
+
+ Currently only a single Behavior may be specified for a property;
+ this Behavior can be enabled and disabled via the \l{enabled} property.
+*/
+
+
+QmlBehavior::QmlBehavior(QObject *parent)
+ : QObject(*(new QmlBehaviorPrivate), parent)
+{
+}
+
+QmlBehavior::~QmlBehavior()
+{
+}
+
+/*!
+ \qmlproperty Animation Behavior::animation
+ \default
+
+ The animation to use when the behavior is triggered.
+*/
+
+QmlAbstractAnimation *QmlBehavior::animation()
+{
+ Q_D(QmlBehavior);
+ return d->animation;
+}
+
+void QmlBehavior::setAnimation(QmlAbstractAnimation *animation)
+{
+ Q_D(QmlBehavior);
+ if (d->animation) {
+ qmlInfo(this) << tr("Can't change the animation assigned to a Behavior.");
+ return;
+ }
+
+ d->animation = animation;
+ if (d->animation)
+ d->animation->setTarget(d->property);
+}
+
+/*!
+ \qmlproperty bool Behavior::enabled
+ Whether the Behavior will be triggered when the property it is tracking changes.
+
+ By default a Behavior is enabled.
+*/
+
+bool QmlBehavior::enabled() const
+{
+ Q_D(const QmlBehavior);
+ return d->enabled;
+}
+
+void QmlBehavior::setEnabled(bool enabled)
+{
+ Q_D(QmlBehavior);
+ if (d->enabled == enabled)
+ return;
+ d->enabled = enabled;
+ emit enabledChanged();
+}
+
+void QmlBehavior::write(const QVariant &value)
+{
+ Q_D(QmlBehavior);
+ if (!d->animation || !d->enabled) {
+ d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ return;
+ }
+
+ d->currentValue = d->property.read();
+
+ d->animation->qtAnimation()->stop();
+
+ QmlStateOperation::ActionList actions;
+ QmlAction action;
+ action.property = d->property;
+ action.fromValue = d->currentValue;
+ action.toValue = value;
+ actions << action;
+
+ QList<QmlMetaProperty> after;
+ if (d->animation)
+ d->animation->transition(actions, after, QmlAbstractAnimation::Forward);
+ d->animation->qtAnimation()->start();
+ if (!after.contains(d->property))
+ d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+}
+
+void QmlBehavior::setTarget(const QmlMetaProperty &property)
+{
+ Q_D(QmlBehavior);
+ d->property = property;
+ d->currentValue = property.read();
+ if (d->animation)
+ d->animation->setTarget(property);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbehavior_p.h b/src/declarative/util/qmlbehavior_p.h
new file mode 100644
index 0000000..da3b40f
--- /dev/null
+++ b/src/declarative/util/qmlbehavior_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBEHAVIOR_H
+#define QMLBEHAVIOR_H
+
+#include "qmlstate_p.h"
+
+#include <qmlpropertyvaluesource.h>
+#include <qmlpropertyvalueinterceptor.h>
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractAnimation;
+class QmlBehaviorPrivate;
+class Q_DECLARATIVE_EXPORT QmlBehavior : public QObject, public QmlPropertyValueInterceptor
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlBehavior)
+
+ Q_INTERFACES(QmlPropertyValueInterceptor)
+ Q_CLASSINFO("DefaultProperty", "animation")
+ Q_PROPERTY(QmlAbstractAnimation *animation READ animation WRITE setAnimation)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+
+public:
+ QmlBehavior(QObject *parent=0);
+ ~QmlBehavior();
+
+ virtual void setTarget(const QmlMetaProperty &);
+ virtual void write(const QVariant &value);
+
+ QmlAbstractAnimation *animation();
+ void setAnimation(QmlAbstractAnimation *);
+
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+Q_SIGNALS:
+ void enabledChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlBehavior)
+
+QT_END_HEADER
+
+#endif // QMLBEHAVIOR_H
diff --git a/src/declarative/util/qmlbind.cpp b/src/declarative/util/qmlbind.cpp
new file mode 100644
index 0000000..c68cef2
--- /dev/null
+++ b/src/declarative/util/qmlbind.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlbind_p.h"
+
+#include "qmlnullablevalue_p_p.h"
+
+#include <qmlengine.h>
+#include <qmlcontext.h>
+
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlBindPrivate : public QObjectPrivate
+{
+public:
+ QmlBindPrivate() : when(true), componentComplete(false), obj(0) {}
+
+ bool when : 1;
+ bool componentComplete : 1;
+ QObject *obj;
+ QString prop;
+ QmlNullableValue<QVariant> value;
+};
+
+QML_DEFINE_TYPE(Qt,4,6,Binding,QmlBind)
+/*!
+ \qmlclass Binding QmlBind
+ \brief The Binding element allows arbitrary property bindings to be created.
+
+ Sometimes it is necessary to bind to a property of an object that wasn't
+ directly instantiated by QML - generally a property of a class exported
+ to QML by C++. In these cases, regular property binding doesn't work. Binding
+ allows you to bind any value to any property.
+
+ For example, imagine a C++ application that maps an "app.enteredText"
+ property into QML. You could use Binding to update the enteredText property
+ like this.
+ \code
+ TextEdit { id: myTextField; text: "Please type here..." }
+ Binding { target: app; property: "enteredText"; value: myTextField.text }
+ \endcode
+ Whenever the text in the TextEdit is updated, the C++ property will be
+ updated also.
+
+ If the binding target or binding property is changed, the bound value is
+ immediately pushed onto the new target.
+ */
+/*!
+ \internal
+ \class QmlBind
+ \ingroup group_utility
+ \brief The QmlBind class allows arbitrary property bindings to be created.
+
+ Simple bindings are usually earier to do in-place rather than creating a
+ QmlBind item. For that reason, QmlBind is usually used to transfer property information
+ from Qml to C++.
+
+ \sa cppqml
+ */
+QmlBind::QmlBind(QObject *parent)
+ : QObject(*(new QmlBindPrivate), parent)
+{
+}
+
+QmlBind::~QmlBind()
+{
+}
+
+bool QmlBind::when() const
+{
+ Q_D(const QmlBind);
+ return d->when;
+}
+
+void QmlBind::setWhen(bool v)
+{
+ Q_D(QmlBind);
+ d->when = v;
+ eval();
+}
+
+/*!
+ \qmlproperty Object Binding::target
+
+ The object to be updated.
+*/
+QObject *QmlBind::object()
+{
+ Q_D(const QmlBind);
+ return d->obj;
+}
+
+void QmlBind::setObject(QObject *obj)
+{
+ Q_D(QmlBind);
+ d->obj = obj;
+ eval();
+}
+
+/*!
+ \qmlproperty string Binding::property
+
+ The property to be updated.
+*/
+QString QmlBind::property() const
+{
+ Q_D(const QmlBind);
+ return d->prop;
+}
+
+void QmlBind::setProperty(const QString &p)
+{
+ Q_D(QmlBind);
+ d->prop = p;
+ eval();
+}
+
+/*!
+ \qmlproperty any Binding::value
+
+ The value to be set on the target object and property. This can be a
+ constant (which isn't very useful), or a bound expression.
+*/
+QVariant QmlBind::value() const
+{
+ Q_D(const QmlBind);
+ return d->value.value;
+}
+
+void QmlBind::setValue(const QVariant &v)
+{
+ Q_D(QmlBind);
+ d->value.value = v;
+ d->value.isNull = false;
+ eval();
+}
+
+void QmlBind::componentComplete()
+{
+ Q_D(QmlBind);
+ d->componentComplete = true;
+ eval();
+}
+
+void QmlBind::eval()
+{
+ Q_D(QmlBind);
+ if (!d->obj || d->value.isNull || !d->when || !d->componentComplete)
+ return;
+
+ QmlMetaProperty prop(d->obj, d->prop);
+ prop.write(d->value.value);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbind_p.h b/src/declarative/util/qmlbind_p.h
new file mode 100644
index 0000000..4d7cd1f
--- /dev/null
+++ b/src/declarative/util/qmlbind_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBIND_H
+#define QMLBIND_H
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlBindPrivate;
+class Q_DECLARATIVE_EXPORT QmlBind : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlBind)
+ Q_INTERFACES(QmlParserStatus)
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QString property READ property WRITE setProperty)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(bool when READ when WRITE setWhen)
+
+public:
+ QmlBind(QObject *parent=0);
+ ~QmlBind();
+
+ bool when() const;
+ void setWhen(bool);
+
+ QObject *object();
+ void setObject(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+protected:
+ virtual void componentComplete();
+
+private:
+ void eval();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlBind)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp
new file mode 100644
index 0000000..800fd6b
--- /dev/null
+++ b/src/declarative/util/qmlconnection.cpp
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlconnection_p.h"
+
+#include <qmlexpression.h>
+#include <qmlboundsignal_p.h>
+#include <qmlcontext.h>
+
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlConnectionPrivate : public QObjectPrivate
+{
+public:
+ QmlConnectionPrivate() : boundsignal(0), signalSender(0), scriptset(false), componentcomplete(false) {}
+
+ QmlBoundSignal *boundsignal;
+ QObject *signalSender;
+ QmlScriptString script;
+ bool scriptset;
+ QString signal;
+ bool componentcomplete;
+};
+
+/*!
+ \qmlclass Connection QmlConnection
+ \brief A Connection object describes generalized connections to signals.
+
+ When connecting to signals in QML, the usual way is to create an
+ "on<Signal>" handler that reacts when a signal is received, like this:
+
+ \qml
+ MouseRegion {
+ onClicked: { foo(x+123,y+456) }
+ }
+ \endqml
+
+ However, in some cases, it is not possible to connect to a signal in this
+ way. For example, JavaScript-in-HTML style signal properties do not allow:
+
+ \list
+ \i connecting to signals with the same name but different parameters
+ \i conformance checking that parameters are correctly named
+ \i multiple connections to the same signal
+ \i connections outside the scope of the signal sender
+ \i signals in classes with coincidentally-named on<Signal> properties
+ \endlist
+
+ When any of these are needed, the Connection object can be used instead.
+
+ For example, the above code can be changed to use a Connection object,
+ like this:
+
+ \qml
+ MouseRegion {
+ Connection {
+ signal: "clicked(x,y)"
+ script: { foo(x+123,y+456) }
+ }
+ }
+ \endqml
+
+ More generally, the Connection object can be a child of some other object than
+ the sender of the signal, and the script is the default attribute:
+
+ \qml
+ MouseRegion {
+ id: mr
+ }
+ ...
+ Connection {
+ sender: mr
+ signal: "clicked(x,y)"
+ script: { foo(x+123,y+456) }
+ }
+ \endqml
+*/
+
+/*!
+ \internal
+ \class QmlConnection
+ \brief The QmlConnection class describes generalized connections to signals.
+
+*/
+QmlConnection::QmlConnection(QObject *parent) :
+ QObject(*(new QmlConnectionPrivate), parent)
+{
+}
+
+QmlConnection::~QmlConnection()
+{
+ Q_D(QmlConnection);
+ delete d->boundsignal;
+}
+
+/*!
+ \qmlproperty Object Connection::sender
+ This property holds the object that sends the signal.
+
+ By default, the sender is assumed to be the parent of the Connection.
+*/
+QObject *QmlConnection::signalSender() const
+{
+ Q_D(const QmlConnection);
+ return d->signalSender ? d->signalSender : parent();
+}
+
+void QmlConnection::setSignalSender(QObject *obj)
+{
+ Q_D(QmlConnection);
+ if (d->signalSender == obj)
+ return;
+ disconnectIfValid();
+ d->signalSender = obj;
+ connectIfValid();
+}
+
+void QmlConnection::connectIfValid()
+{
+ Q_D(QmlConnection);
+ if (!d->componentcomplete)
+ return;
+ // boundsignal must not exist
+ if ((d->signalSender || parent()) && !d->signal.isEmpty() && d->scriptset) {
+ // create
+ // XXX scope?
+ int sigIdx = -1;
+ int lparen = d->signal.indexOf(QLatin1Char('('));
+ QList<QByteArray> sigparams;
+ if (lparen >= 0 && d->signal.length() > lparen+2) {
+ QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(','));
+ foreach (const QString &s, l) {
+ sigparams.append(s.trimmed().toUtf8());
+ }
+ }
+ QString signalname = d->signal.left(lparen);
+ QObject *sender = d->signalSender ? d->signalSender : parent();
+ const QMetaObject *mo = sender->metaObject();
+ int methods = mo->methodCount();
+ for (int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QString::fromUtf8(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+ if (methodName == signalname && (lparen<0 || method.parameterNames() == sigparams)) {
+ sigIdx = ii;
+ break;
+ }
+ }
+ if (sigIdx < 0) {
+ // Cannot usefully warn, since could be in middle of
+ // changing sender and signal.
+ // XXX need state change transactions to do better
+ return;
+ }
+
+ d->boundsignal = new QmlBoundSignal(qmlContext(this), d->script.script(), sender, mo->method(sigIdx), this);
+ }
+}
+
+void QmlConnection::disconnectIfValid()
+{
+ Q_D(QmlConnection);
+ if (!d->componentcomplete)
+ return;
+ if ((d->signalSender || parent()) && !d->signal.isEmpty() && d->scriptset) {
+ // boundsignal must exist
+ // destroy
+ delete d->boundsignal;
+ d->boundsignal = 0;
+ }
+}
+
+void QmlConnection::componentComplete()
+{
+ Q_D(QmlConnection);
+ d->componentcomplete=true;
+ connectIfValid();
+}
+
+
+/*!
+ \qmlproperty script Connection::script
+ This property holds the JavaScript executed whenever the signal is sent.
+
+ This is the default attribute of Connection.
+*/
+QmlScriptString QmlConnection::script() const
+{
+ Q_D(const QmlConnection);
+ return d->script;
+}
+
+void QmlConnection::setScript(const QmlScriptString& script)
+{
+ Q_D(QmlConnection);
+ if ((d->signalSender || parent()) && !d->signal.isEmpty()) {
+ if (!d->scriptset) {
+ // mustn't exist - create
+ d->scriptset = true;
+ d->script = script;
+ connectIfValid();
+ } else {
+ // must exist - update
+ d->script = script;
+ d->boundsignal->expression()->setExpression(script.script());
+ }
+ } else {
+ d->scriptset = true;
+ d->script = script;
+ }
+}
+
+/*!
+ \qmlproperty string Connection::signal
+ This property holds the signal from the sender to which the script is attached.
+
+ The signal's formal parameter names must be given in parentheses:
+
+ \qml
+Connection {
+ signal: "clicked(x,y)"
+ script: { ... }
+}
+ \endqml
+*/
+QString QmlConnection::signal() const
+{
+ Q_D(const QmlConnection);
+ return d->signal;
+}
+
+void QmlConnection::setSignal(const QString& sig)
+{
+ Q_D(QmlConnection);
+ if (d->signal == sig)
+ return;
+ disconnectIfValid();
+ d->signal = sig;
+ connectIfValid();
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Connection,QmlConnection)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlconnection_p.h b/src/declarative/util/qmlconnection_p.h
new file mode 100644
index 0000000..52bc247
--- /dev/null
+++ b/src/declarative/util/qmlconnection_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONNECTION_H
+#define QMLCONNECTION_H
+
+#include <qml.h>
+#include <qmlscriptstring.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlBoundSignal;
+class QmlContext;
+class QmlConnectionPrivate;
+class Q_DECLARATIVE_EXPORT QmlConnection : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlConnection)
+
+ Q_INTERFACES(QmlParserStatus)
+ Q_PROPERTY(QObject *sender READ signalSender WRITE setSignalSender)
+ Q_PROPERTY(QmlScriptString script READ script WRITE setScript)
+ Q_PROPERTY(QString signal READ signal WRITE setSignal)
+
+public:
+ QmlConnection(QObject *parent=0);
+ ~QmlConnection();
+
+ QObject *signalSender() const;
+ void setSignalSender(QObject *);
+ QmlScriptString script() const;
+ void setScript(const QmlScriptString&);
+ QString signal() const;
+ void setSignal(const QString&);
+
+private:
+ void disconnectIfValid();
+ void connectIfValid();
+ void componentComplete();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlConnection)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qmldatetimeformatter.cpp b/src/declarative/util/qmldatetimeformatter.cpp
new file mode 100644
index 0000000..9d216cf
--- /dev/null
+++ b/src/declarative/util/qmldatetimeformatter.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldatetimeformatter_p.h"
+
+#include <QtCore/qlocale.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//TODO: may need optimisation as the QDateTime member may not be needed?
+// be able to set a locale?
+
+class QmlDateTimeFormatterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDateTimeFormatter)
+public:
+ QmlDateTimeFormatterPrivate() : locale(QLocale::system()), longStyle(false), componentComplete(true) {}
+
+ void updateText();
+
+ QDateTime dateTime;
+ QDate date;
+ QTime time;
+ QLocale locale;
+ QString dateTimeText;
+ QString dateText;
+ QString timeText;
+ QString dateTimeFormat; //set for convienience?
+ QString dateFormat;
+ QString timeFormat;
+ bool longStyle;
+ bool componentComplete;
+};
+
+/*!
+ \qmlclass DateTimeFormatter QmlDateTimeFormatter
+ \brief The DateTimeFormatter allows you to control the format of a date string.
+
+ \code
+ DateTimeFormatter { id: formatter; date: System.date }
+ Text { text: formatter.dateText }
+ \endcode
+
+ By default, the text properties (dateText, timeText, and dateTimeText) will return the
+ date and time using the current system locale's format.
+*/
+
+/*!
+ \internal
+ \class QmlDateTimeFormatter
+ \ingroup group_utility
+ \brief The QmlDateTimeFormatter class allows you to format a date string.
+*/
+
+QmlDateTimeFormatter::QmlDateTimeFormatter(QObject *parent)
+: QObject(*(new QmlDateTimeFormatterPrivate), parent)
+{
+}
+
+QmlDateTimeFormatter::~QmlDateTimeFormatter()
+{
+}
+
+/*!
+ \qmlproperty string DateTimeFormatter::dateText
+ \qmlproperty string DateTimeFormatter::timeText
+ \qmlproperty string DateTimeFormatter::dateTimeText
+
+ Formatted text representations of the \c date, \c time,
+ and \c {date and time}, respectively.
+
+ If there is no explictly specified format the DateTimeFormatter
+ will use the system locale's default 'short' setting.
+
+ \code
+ // specify source date (assuming today is February 19, 2009)
+ DateTimeFormatter { id: formatter; dateTime: Today.date }
+
+ // display the full date and time
+ Text { text: formatter.dateText }
+ \endcode
+
+ Would be equivalent to the following for a US English locale:
+
+ \code
+ // display the date
+ Text { text: "2/19/09" }
+ \endcode
+*/
+QString QmlDateTimeFormatter::dateTimeText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTimeText;
+}
+
+QString QmlDateTimeFormatter::dateText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateText;
+}
+
+QString QmlDateTimeFormatter::timeText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->timeText;
+}
+
+/*!
+ \qmlproperty date DateTimeFormatter::date
+ \qmlproperty time DateTimeFormatter::time
+ \qmlproperty datetime DateTimeFormatter::dateTime
+
+ The source date and time to be used by the formatter.
+
+ \code
+ // setting the date and time
+ DateTimeFormatter { date: System.date; time: System.time }
+ \endcode
+
+ For convienience it is possible to set the datetime property to set both the date and the time.
+ \code
+ // setting the datetime
+ DateTimeFormatter { dateTime: System.dateTime }
+ \endcode
+
+ There can only be one instance of date and time per formatter; if date, time, and dateTime are all
+ set the actual date and time used is not guaranteed.
+
+ \note If no date is set, dateTimeText will be just the date;
+ If no time is set, the dateTimeText will be just the time.
+
+*/
+QDate QmlDateTimeFormatter::date() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->date;
+}
+
+QTime QmlDateTimeFormatter::time() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->time;
+}
+
+QDateTime QmlDateTimeFormatter::dateTime() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTime;
+}
+
+/*!
+ \qmlproperty string DateTimeFormatter::dateFormat
+ \qmlproperty string DateTimeFormatter::timeFormat
+ \qmlproperty string DateTimeFormatter::dateTimeFormat
+
+ Specifies a custom format which the DateTime Formatter can use.
+
+ If there is no explictly specified format the DateTimeFormatter
+ will use the system locale's default 'short' setting.
+
+ The text's format may be modified by setting:
+ \list
+ \i \c dateFormat
+ \i \c timeFormat
+ \i \c dateTimeFormat
+ \endlist
+
+ If only the format for date is defined, the time and dateTime formats will be defined
+ as the system locale default and likewise for the others.
+
+ Syntax for the format is based on the QDateTime::toString() formatting options.
+
+ \code
+ // Format the date such that the dateText is: '1997-12-12'
+ DateTimeFormatter { id: formatter; dateTime: Today.dateTime; formatDate: "yyyy-MM-d" }
+ \endcode
+
+ Assigning an empty string to a particular format will reset it.
+*/
+QString QmlDateTimeFormatter::dateTimeFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTimeFormat;
+}
+
+QString QmlDateTimeFormatter::dateFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateFormat;
+}
+
+QString QmlDateTimeFormatter::timeFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->timeFormat;
+}
+
+/*!
+ \qmlproperty bool DateTimeFormatter::longStyle
+
+ This property causes the formatter to use the system locale's long format rather than short format
+ by default.
+
+ This setting is off by default.
+*/
+bool QmlDateTimeFormatter::longStyle() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->longStyle;
+}
+
+void QmlDateTimeFormatter::setDateTime(const QDateTime &dateTime)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime == dateTime)
+ return;
+ d->dateTime = dateTime;
+ d->date = d->dateTime.date();
+ d->time = d->dateTime.time();
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setTime(const QTime &time)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime.time() == time)
+ return;
+ d->time = time;
+ d->dateTime.setTime(time);
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setDate(const QDate &date)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime.date() == date)
+ return;
+ d->date = date;
+ bool clearTime = d->dateTime.time().isValid() ? false : true; //because setting date generates default time
+ d->dateTime.setDate(date);
+ if (clearTime)
+ d->dateTime.setTime(QTime());
+ d->updateText();
+}
+
+//DateTime formatting may be a combination of date and time?
+void QmlDateTimeFormatter::setDateTimeFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->dateTimeFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setDateFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->dateFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setTimeFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->timeFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setLongStyle(bool longStyle)
+{
+ Q_D(QmlDateTimeFormatter);
+ d->longStyle = longStyle;
+ d->updateText();
+}
+
+void QmlDateTimeFormatterPrivate::updateText()
+{
+ Q_Q(QmlDateTimeFormatter);
+ if (!componentComplete)
+ return;
+
+ QString str;
+ QString str1;
+ QString str2;
+
+ Qt::DateFormat defaultFormat = longStyle ? Qt::SystemLocaleLongDate : Qt::SystemLocaleShortDate;
+
+ if (dateFormat.isEmpty())
+ str1 = date.toString(defaultFormat);
+ else
+ str1 = date.toString(dateFormat);
+
+ if (timeFormat.isEmpty())
+ str2 = time.toString(defaultFormat);
+ else
+ str2 = time.toString(timeFormat);
+
+ if (dateTimeFormat.isEmpty())
+ str = dateTime.toString(defaultFormat);
+ //else if (!formatTime.isEmpty() && !formatDate.isEmpty())
+ // str = str1 + QLatin1Char(' ') + str2;
+ else
+ str = dateTime.toString(dateTimeFormat);
+
+ if (dateTimeText == str && dateText == str1 && timeText == str2)
+ return;
+
+ dateTimeText = str;
+ dateText = str1;
+ timeText = str2;
+
+ emit q->textChanged();
+}
+
+void QmlDateTimeFormatter::classBegin()
+{
+ Q_D(QmlDateTimeFormatter);
+ d->componentComplete = false;
+}
+
+void QmlDateTimeFormatter::componentComplete()
+{
+ Q_D(QmlDateTimeFormatter);
+ d->componentComplete = true;
+ d->updateText();
+}
+
+QML_DEFINE_TYPE(Qt,4,6,DateTimeFormatter,QmlDateTimeFormatter)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmldatetimeformatter_p.h b/src/declarative/util/qmldatetimeformatter_p.h
new file mode 100644
index 0000000..c90ee8c
--- /dev/null
+++ b/src/declarative/util/qmldatetimeformatter_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDATETIMEFORMATTER_H
+#define QMLDATETIMEFORMATTER_H
+
+#include <qml.h>
+
+#include <QtCore/qdatetime.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlDateTimeFormatterPrivate;
+class Q_DECLARATIVE_EXPORT QmlDateTimeFormatter : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString dateText READ dateText NOTIFY textChanged)
+ Q_PROPERTY(QString timeText READ timeText NOTIFY textChanged)
+ Q_PROPERTY(QString dateTimeText READ dateTimeText NOTIFY textChanged)
+ Q_PROPERTY(QDate date READ date WRITE setDate)
+ Q_PROPERTY(QTime time READ time WRITE setTime)
+ Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime)
+ Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat)
+ Q_PROPERTY(QString timeFormat READ timeFormat WRITE setTimeFormat)
+ Q_PROPERTY(QString dateTimeFormat READ dateTimeFormat WRITE setDateTimeFormat)
+ Q_PROPERTY(bool longStyle READ longStyle WRITE setLongStyle)
+public:
+ QmlDateTimeFormatter(QObject *parent=0);
+ ~QmlDateTimeFormatter();
+
+ QString dateTimeText() const;
+ QString dateText() const;
+ QString timeText() const;
+
+ QDate date() const;
+ void setDate(const QDate &);
+
+ QTime time() const;
+ void setTime(const QTime &);
+
+ QDateTime dateTime() const;
+ void setDateTime(const QDateTime &);
+
+ QString dateTimeFormat() const;
+ void setDateTimeFormat(const QString &);
+
+ QString dateFormat() const;
+ void setDateFormat(const QString &);
+
+ QString timeFormat() const;
+ void setTimeFormat(const QString &);
+
+ bool longStyle() const;
+ void setLongStyle(bool);
+
+ virtual void classBegin();
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ Q_DISABLE_COPY(QmlDateTimeFormatter)
+ Q_DECLARE_PRIVATE(QmlDateTimeFormatter)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlDateTimeFormatter)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qmleasefollow.cpp b/src/declarative/util/qmleasefollow.cpp
new file mode 100644
index 0000000..e3153b1
--- /dev/null
+++ b/src/declarative/util/qmleasefollow.cpp
@@ -0,0 +1,527 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmleasefollow_p.h"
+
+#include "qmlanimation_p_p.h"
+
+#include <qmlmetaproperty.h>
+
+#include <QtCore/qdebug.h>
+
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,EaseFollow,QmlEaseFollow);
+
+class QmlEaseFollowPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEaseFollow)
+public:
+ QmlEaseFollowPrivate()
+ : source(0), velocity(200), duration(-1), maximumEasingTime(-1),
+ reversingMode(QmlEaseFollow::Eased), initialVelocity(0),
+ initialValue(0), invert(false), enabled(true), trackVelocity(0), clockOffset(0),
+ lastTick(0), clock(this)
+ {}
+
+ qreal source;
+ qreal velocity;
+ qreal duration;
+ qreal maximumEasingTime;
+ QmlEaseFollow::ReversingMode reversingMode;
+
+ qreal initialVelocity;
+ qreal initialValue;
+ bool invert;
+ bool enabled;
+
+ qreal trackVelocity;
+
+ QmlMetaProperty target;
+
+ int clockOffset;
+ int lastTick;
+ void tick(int);
+ void clockStart();
+ void clockStop();
+ QTickAnimationProxy<QmlEaseFollowPrivate, &QmlEaseFollowPrivate::tick> clock;
+
+ void restart();
+
+ // Parameters for use in tick()
+ qreal a; // Acceleration
+ qreal d; // Deceleration
+ qreal tf; // Total time
+ qreal tp; // Time at which peak velocity occurs
+ qreal td; // Time at which decelleration begins
+ qreal vp; // Velocity at tp
+ qreal sp; // Displacement at tp
+ qreal sd; // Displacement at td
+ qreal vi; // "Normalized" initialvelocity
+ bool recalc();
+};
+
+bool QmlEaseFollowPrivate::recalc()
+{
+ qreal s = source - initialValue;
+ vi = initialVelocity;
+
+ s = (invert?-1.0:1.0) * s;
+ vi = (invert?-1.0:1.0) * vi;
+
+ if (duration > 0 && velocity > 0) {
+ tf = s / velocity;
+ if (tf > (duration / 1000.)) tf = (duration / 1000.);
+ } else if (duration > 0) {
+ tf = duration / 1000.;
+ } else if (velocity > 0) {
+ tf = s / velocity;
+ } else {
+ return false;
+ }
+
+ if (maximumEasingTime == 0) {
+ a = 0;
+ d = 0;
+ tp = 0;
+ td = tf;
+ vp = velocity;
+ sp = 0;
+ sd = s;
+ } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
+
+ qreal met = maximumEasingTime / 1000.;
+ td = tf - met;
+
+ qreal c1 = td;
+ qreal c2 = (tf - td) * vi - tf * velocity;
+ qreal c3 = -0.5 * (tf - td) * vi * vi;
+
+ qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+ // qreal vp2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+
+ vp = vp1;
+ a = vp / met;
+ d = a;
+ tp = (vp - vi) / a;
+ sp = vi * tp + 0.5 * a * tp * tp;
+ sd = sp + (td - tp) * vp;
+ } else {
+
+ qreal c1 = 0.25 * tf * tf;
+ qreal c2 = 0.5 * vi * tf - s;
+ qreal c3 = -0.25 * vi * vi;
+
+ qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+ //qreal a2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+
+ qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
+ //qreal tp2 = 0.5 * tf - 0.5 * vi / a2;
+ qreal vp1 = a1 * tp1 + vi;
+ //qreal vp2 = a2 * tp2 + vi;
+
+ qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
+ //qreal sp2 = 0.5 * a2 * tp2 * tp2 + vi * tp2;
+
+ a = a1;
+ d = a1;
+ tp = tp1;
+ td = tp1;
+ vp = vp1;
+ sp = sp1;
+ sd = sp1;
+ }
+
+ /*
+ qWarning() << "a:" << a << "tf:" << tf << "tp:" << tp << "vp:"
+ << vp << "sp:" << sp << "vi:" << vi << "invert:" << invert;
+ */
+ return true;
+}
+
+void QmlEaseFollowPrivate::clockStart()
+{
+ if (clock.state() == QAbstractAnimation::Running) {
+ clockOffset = lastTick;
+ return;
+ } else {
+ clockOffset = 0;
+ lastTick = 0;
+ clock.start();
+ }
+}
+
+void QmlEaseFollowPrivate::clockStop()
+{
+ clockOffset = 0;
+ lastTick = 0;
+ clock.stop();
+}
+
+void QmlEaseFollowPrivate::tick(int t)
+{
+ lastTick = t;
+ t -= clockOffset;
+
+ qreal time_seconds = qreal(t) / 1000.;
+
+ qreal out = 0;
+ if (time_seconds < tp) {
+
+ trackVelocity = vi + time_seconds * a;
+ trackVelocity = (invert?-1.0:1.0) * trackVelocity;
+
+ qreal value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
+ value = (invert?-1.0:1.0) * value;
+ target.write(initialValue + value);
+ out = initialValue + value;
+ } else if (time_seconds < td) {
+
+ time_seconds -= tp;
+ trackVelocity = (invert?-1.0:1.0) * vp;
+ qreal value = sp + time_seconds * vp;
+ value = (invert?-1.0:1.0) * value;
+
+ target.write(initialValue + value);
+
+ out = initialValue + value;
+ } else if (time_seconds < tf) {
+
+ time_seconds -= td;
+
+ trackVelocity = vp - time_seconds * a;
+ trackVelocity = (invert?-1.0:1.0) * trackVelocity;
+
+ qreal value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
+ value = (invert?-1.0:1.0) * value;
+
+ target.write(initialValue + value);
+
+ out = initialValue + value;
+ } else {
+
+ clock.stop();
+
+ trackVelocity = 0;
+ target.write(source);
+ }
+
+ //qWarning() << out << trackVelocity << t << a;
+}
+
+/*!
+ \qmlclass EaseFollow QmlEaseFollow
+ \brief The EaseFollow element allows a property to smoothly track a value.
+
+ The EaseFollow smoothly animates a property's value to a set target value
+ using an ease in/out quad easing curve. If the target value changes while
+ the animation is in progress, the easing curves used to animate to the old
+ and the new target values are spliced together to avoid any obvious visual
+ glitches.
+
+ The property animation is configured by setting the velocity at which the
+ animation should occur, or the duration that the animation should take.
+ If both a velocity and a duration are specified, the one that results in
+ the quickest animation is chosen for each change in the target value.
+
+ For example, animating from 0 to 800 will take 4 seconds if a velocity
+ of 200 is set, will take 8 seconds with a duration of 8000 set, and will
+ take 4 seconds with both a velocity of 200 and a duration of 8000 set.
+ Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set,
+ will take 8 seconds with a duration of 8000 set, and will take 8 seconds
+ with both a velocity of 200 and a duration of 8000 set.
+
+ The follow example shows one rectangle tracking the position of another.
+\code
+import Qt 4.6
+
+Rectangle {
+ width: 800; height: 600; color: "blue"
+
+ Rectangle {
+ color: "green"
+ width: 60; height: 60;
+ x: -5; y: -5;
+ x: EaseFollow { source: rect1.x - 5; velocity: 200 }
+ y: EaseFollow { source: rect1.y - 5; velocity: 200 }
+ }
+
+ Rectangle {
+ id: rect1
+ color: "red"
+ width: 50; height: 50;
+ }
+
+ focus: true
+ Keys.onRightPressed: rect1.x = rect1.x + 100
+ Keys.onLeftPressed: rect1.x = rect1.x - 100
+ Keys.onUpPressed: rect1.y = rect1.y - 100
+ Keys.onDownPressed: rect1.y = rect1.y + 100
+}
+\endcode
+
+ \sa SpringFollow
+*/
+
+QmlEaseFollow::QmlEaseFollow(QObject *parent)
+: QObject(*(new QmlEaseFollowPrivate), parent)
+{
+}
+
+QmlEaseFollow::~QmlEaseFollow()
+{
+}
+
+/*!
+ \qmlproperty qreal EaseFollow::source
+ This property holds the source value which will be tracked.
+
+ Bind to a property in order to track its changes.
+*/
+qreal QmlEaseFollow::sourceValue() const
+{
+ Q_D(const QmlEaseFollow);
+ return d->source;
+}
+
+/*!
+ \qmlproperty enumeration EaseFollow::reversingMode
+
+ Sets how the EaseFollow behaves if an animation direction is reversed.
+
+ If reversing mode is \c Eased, the animation will smoothly decelerate, and
+ then reverse direction. If the reversing mode is \c Immediate, the
+ animation will immediately begin accelerating in the reverse direction,
+ begining with a velocity of 0. If the reversing mode is \c Sync, the
+ property is immediately set to the target value.
+*/
+QmlEaseFollow::ReversingMode QmlEaseFollow::reversingMode() const
+{
+ Q_D(const QmlEaseFollow);
+ return d->reversingMode;
+}
+
+void QmlEaseFollow::setReversingMode(ReversingMode m)
+{
+ Q_D(QmlEaseFollow);
+ if (d->reversingMode == m)
+ return;
+
+ d->reversingMode = m;
+ emit reversingModeChanged();
+}
+
+void QmlEaseFollowPrivate::restart()
+{
+ if (!enabled || velocity == 0) {
+ clockStop();
+ return;
+ }
+
+ initialValue = target.read().toReal();
+
+ if (source == initialValue) {
+ clockStop();
+ return;
+ }
+
+ bool hasReversed = trackVelocity != 0. &&
+ ((trackVelocity > 0) == ((initialValue - source) > 0));
+
+ if (hasReversed) {
+ switch (reversingMode) {
+ default:
+ case QmlEaseFollow::Eased:
+ break;
+ case QmlEaseFollow::Sync:
+ target.write(source);
+ return;
+ case QmlEaseFollow::Immediate:
+ initialVelocity = 0;
+ clockStop();
+ break;
+ }
+ }
+
+ trackVelocity = initialVelocity;
+
+ invert = (source < initialValue);
+
+ if (!recalc()) {
+ target.write(source);
+ clockStop();
+ return;
+ }
+
+ clockStart();
+}
+
+void QmlEaseFollow::setSourceValue(qreal s)
+{
+ Q_D(QmlEaseFollow);
+
+ if (d->clock.state() == QAbstractAnimation::Running && d->source == s)
+ return;
+
+ d->source = s;
+ d->initialVelocity = d->trackVelocity;
+ d->restart();
+
+ emit sourceChanged();
+}
+
+/*!
+ \qmlproperty qreal EaseFollow::duration
+
+ This property holds the animation duration used when tracking the source.
+
+ Setting this to -1 disables the duration value.
+*/
+qreal QmlEaseFollow::duration() const
+{
+ Q_D(const QmlEaseFollow);
+ return d->duration;
+}
+
+void QmlEaseFollow::setDuration(qreal v)
+{
+ Q_D(QmlEaseFollow);
+ if (d->duration == v)
+ return;
+
+ d->duration = v;
+ d->trackVelocity = 0;
+
+ if (d->clock.state() == QAbstractAnimation::Running)
+ d->restart();
+
+ emit durationChanged();
+}
+
+qreal QmlEaseFollow::velocity() const
+{
+ Q_D(const QmlEaseFollow);
+ return d->velocity;
+}
+
+/*!
+ \qmlproperty qreal EaseFollow::velocity
+
+ This property holds the average velocity allowed when tracking the source.
+
+ Setting this to -1 disables the velocity value.
+*/
+void QmlEaseFollow::setVelocity(qreal v)
+{
+ Q_D(QmlEaseFollow);
+ if (d->velocity == v)
+ return;
+
+ d->velocity = v;
+ d->trackVelocity = 0;
+
+ if (d->clock.state() == QAbstractAnimation::Running)
+ d->restart();
+
+ emit velocityChanged();
+}
+
+/*!
+ \qmlproperty bool EaseFollow::enabled
+ This property holds whether the target will track the source.
+*/
+bool QmlEaseFollow::enabled() const
+{
+ Q_D(const QmlEaseFollow);
+ return d->enabled;
+}
+
+void QmlEaseFollow::setEnabled(bool enabled)
+{
+ Q_D(QmlEaseFollow);
+ if (d->enabled == enabled)
+ return;
+
+ d->enabled = enabled;
+ if (enabled)
+ d->restart();
+ else
+ d->clockStop();
+
+ emit enabledChanged();
+}
+
+void QmlEaseFollow::setTarget(const QmlMetaProperty &t)
+{
+ Q_D(QmlEaseFollow);
+ d->target = t;
+}
+
+/*!
+\qmlproperty qreal EaseFollow::maximumEasingTime
+
+This property specifies the maximum time an "eases" during the follow should take.
+Setting this property causes the velocity to "level out" after at a time. Setting
+a negative value reverts to the normal mode of easing over the entire animation
+duration.
+
+The default value is -1.
+*/
+qreal QmlEaseFollow::maximumEasingTime() const
+{
+ Q_D(const QmlEaseFollow);
+ return d->maximumEasingTime;
+}
+
+void QmlEaseFollow::setMaximumEasingTime(qreal v)
+{
+ Q_D(QmlEaseFollow);
+ d->maximumEasingTime = v;
+
+ if (d->clock.state() == QAbstractAnimation::Running)
+ d->restart();
+
+ emit maximumEasingTimeChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmleasefollow_p.h b/src/declarative/util/qmleasefollow_p.h
new file mode 100644
index 0000000..ef095a3
--- /dev/null
+++ b/src/declarative/util/qmleasefollow_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLEASEFOLLOW_H
+#define QMLEASEFOLLOW_H
+
+#include <qml.h>
+#include <qmlpropertyvaluesource.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlMetaProperty;
+class QmlEaseFollowPrivate;
+class Q_DECLARATIVE_EXPORT QmlEaseFollow : public QObject,
+ public QmlPropertyValueSource
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlEaseFollow)
+ Q_INTERFACES(QmlPropertyValueSource)
+ Q_ENUMS(ReversingMode)
+
+ Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue NOTIFY sourceChanged)
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(qreal duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged)
+
+public:
+ enum ReversingMode { Eased, Immediate, Sync };
+
+ QmlEaseFollow(QObject *parent = 0);
+ ~QmlEaseFollow();
+
+ ReversingMode reversingMode() const;
+ void setReversingMode(ReversingMode);
+
+ qreal sourceValue() const;
+ void setSourceValue(qreal);
+
+ qreal velocity() const;
+ void setVelocity(qreal);
+
+ qreal duration() const;
+ void setDuration(qreal);
+
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+ qreal maximumEasingTime() const;
+ void setMaximumEasingTime(qreal);
+
+ virtual void setTarget(const QmlMetaProperty &);
+
+Q_SIGNALS:
+ void sourceChanged();
+ void velocityChanged();
+ void durationChanged();
+ void reversingModeChanged();
+ void enabledChanged();
+ void maximumEasingTimeChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlEaseFollow);
+
+QT_END_HEADER
+
+#endif // QMLEASEFOLLOW_H
diff --git a/src/declarative/util/qmlfontloader.cpp b/src/declarative/util/qmlfontloader.cpp
new file mode 100644
index 0000000..b56043b
--- /dev/null
+++ b/src/declarative/util/qmlfontloader.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlfontloader_p.h"
+
+#include <qmlcontext.h>
+#include <qmlengine.h>
+
+#include <QUrl>
+#include <QDebug>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFile>
+#include <QFontDatabase>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlFontLoaderPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlFontLoader)
+
+public:
+ QmlFontLoaderPrivate() : reply(0), status(QmlFontLoader::Null) {}
+
+ void addFontToDatabase(const QByteArray &);
+
+ QUrl url;
+ QString name;
+ QNetworkReply *reply;
+ QmlFontLoader::Status status;
+};
+
+QML_DEFINE_TYPE(Qt,4,6,FontLoader,QmlFontLoader)
+
+/*!
+ \qmlclass FontLoader QmlFontLoader
+ \ingroup group_utility
+ \brief This item allows using fonts by name or url.
+
+ Example:
+ \qml
+ FontLoader { id: fixedFont; name: "Courier" }
+ FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
+
+ Text { text: "Fixed-size font"; font.family: fixedFont.name }
+ Text { text: "Fancy font"; font.family: webFont.name }
+ \endqml
+*/
+QmlFontLoader::QmlFontLoader(QObject *parent)
+ : QObject(*(new QmlFontLoaderPrivate), parent)
+{
+}
+
+QmlFontLoader::~QmlFontLoader()
+{
+}
+
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+
+/*!
+ \qmlproperty url FontLoader::source
+ The url of the font to load.
+*/
+QUrl QmlFontLoader::source() const
+{
+ Q_D(const QmlFontLoader);
+ return d->url;
+}
+
+void QmlFontLoader::setSource(const QUrl &url)
+{
+ Q_D(QmlFontLoader);
+ if (url == d->url)
+ return;
+ d->url = qmlContext(this)->resolvedUrl(url);
+
+ d->status = Loading;
+ emit statusChanged();
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = toLocalFileOrQrc(d->url);
+ if (!lf.isEmpty()) {
+ int id = QFontDatabase::addApplicationFont(lf);
+ if (id != -1) {
+ d->name = QFontDatabase::applicationFontFamilies(id).at(0);
+ emit nameChanged();
+ d->status = QmlFontLoader::Ready;
+ } else {
+ d->status = QmlFontLoader::Error;
+ qWarning() << "Cannot load font:" << url;
+ }
+ emit statusChanged();
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ d->reply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ }
+}
+
+/*!
+ \qmlproperty string FontLoader::name
+
+ This property holds the name of the font family.
+ It is set automatically when a font is loaded using the \c url property.
+
+ Use this to set the \c font.family property of a \c Text item.
+
+ Example:
+ \qml
+ FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
+ Text { text: "Fancy font"; font.family: webFont.name }
+ \endqml
+*/
+QString QmlFontLoader::name() const
+{
+ Q_D(const QmlFontLoader);
+ return d->name;
+}
+
+void QmlFontLoader::setName(const QString &name)
+{
+ Q_D(QmlFontLoader);
+ if (d->name == name )
+ return;
+ d->name = name;
+ emit nameChanged();
+ d->status = Ready;
+ emit statusChanged();
+}
+
+/*!
+ \qmlproperty enum FontLoader::status
+
+ This property holds the status of font loading. It can be one of:
+ \list
+ \o Null - no font has been set
+ \o Ready - the font has been loaded
+ \o Loading - the font is currently being loaded
+ \o Error - an error occurred while loading the font
+ \endlist
+*/
+QmlFontLoader::Status QmlFontLoader::status() const
+{
+ Q_D(const QmlFontLoader);
+ return d->status;
+}
+
+void QmlFontLoader::replyFinished()
+{
+ Q_D(QmlFontLoader);
+ if (d->reply) {
+ if (!d->reply->error()) {
+ QByteArray ba = d->reply->readAll();
+ d->addFontToDatabase(ba);
+ } else {
+ d->status = Error;
+ emit statusChanged();
+ }
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+}
+
+void QmlFontLoaderPrivate::addFontToDatabase(const QByteArray &ba)
+{
+ Q_Q(QmlFontLoader);
+
+ int id = QFontDatabase::addApplicationFontFromData(ba);
+ if (id != -1) {
+ name = QFontDatabase::applicationFontFamilies(id).at(0);
+ emit q->nameChanged();
+ status = QmlFontLoader::Ready;
+ } else {
+ status = QmlFontLoader::Error;
+ qWarning() << "Cannot load font:" << url;
+ }
+ emit q->statusChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlfontloader_p.h b/src/declarative/util/qmlfontloader_p.h
new file mode 100644
index 0000000..aac8a71
--- /dev/null
+++ b/src/declarative/util/qmlfontloader_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLFONTLOADER_H
+#define QMLFONTLOADER_H
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlFontLoaderPrivate;
+class Q_DECLARATIVE_EXPORT QmlFontLoader : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlFontLoader)
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+public:
+ enum Status { Null = 0, Ready, Loading, Error };
+
+ QmlFontLoader(QObject *parent = 0);
+ ~QmlFontLoader();
+
+ QUrl source() const;
+ void setSource(const QUrl &url);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ Status status() const;
+
+private Q_SLOTS:
+ void replyFinished();
+
+Q_SIGNALS:
+ void nameChanged();
+ void statusChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlFontLoader)
+
+QT_END_HEADER
+
+#endif // QMLFONTLOADER_H
+
diff --git a/src/declarative/util/qmllistaccessor.cpp b/src/declarative/util/qmllistaccessor.cpp
new file mode 100644
index 0000000..6658949
--- /dev/null
+++ b/src/declarative/util/qmllistaccessor.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmllistaccessor_p.h"
+
+#include <qmlmetatype.h>
+
+#include <QStringList>
+#include <QtCore/qdebug.h>
+
+// ### Remove me
+#include <qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlListAccessor::QmlListAccessor()
+: m_type(Invalid)
+{
+}
+
+QmlListAccessor::~QmlListAccessor()
+{
+}
+
+QVariant QmlListAccessor::list() const
+{
+ return d;
+}
+
+void QmlListAccessor::setList(const QVariant &v, QmlEngine *engine)
+{
+ d = v;
+
+ QmlEnginePrivate *enginePrivate = engine?QmlEnginePrivate::get(engine):0;
+
+ if (!d.isValid()) {
+ m_type = Invalid;
+ } else if (d.userType() == QVariant::StringList) {
+ m_type = StringList;
+ } else if (d.userType() == QMetaType::QVariantList) {
+ m_type = VariantList;
+ } else if (d.canConvert(QVariant::Int)) {
+ m_type = Integer;
+ } else if ((!enginePrivate && QmlMetaType::isQObject(d.userType())) ||
+ (enginePrivate && enginePrivate->isQObject(d.userType()))) {
+ QObject *data = enginePrivate?enginePrivate->toQObject(v):QmlMetaType::toQObject(v);
+ d = QVariant::fromValue(data);
+ m_type = Instance;
+ } else if ((!enginePrivate && QmlMetaType::isQmlList(d.userType())) ||
+ (enginePrivate && enginePrivate->isQmlList(d.userType()))) {
+ m_type = QmlList;
+ } else if (QmlMetaType::isList(d.userType())) {
+ m_type = QListPtr;
+ } else {
+ m_type = Instance;
+ }
+}
+
+int QmlListAccessor::count() const
+{
+ switch(m_type) {
+ case StringList:
+ return qvariant_cast<QStringList>(d).count();
+ case VariantList:
+ return qvariant_cast<QVariantList>(d).count();
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ return li->count();
+ }
+ case QListPtr:
+ {
+ QList<void *> *li = *(QList<void *> **)d.constData();
+ return li->count();
+ }
+ case Instance:
+ return 1;
+ case Integer:
+ return d.toInt();
+ default:
+ case Invalid:
+ return 0;
+ }
+}
+
+QVariant QmlListAccessor::at(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < count());
+ switch(m_type) {
+ case StringList:
+ return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx));
+ case VariantList:
+ return qvariant_cast<QVariantList>(d).at(idx);
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ void *ptr[1];
+ li->at(idx, ptr);
+ return QVariant::fromValue((QObject*)ptr[0]);
+ }
+ case QListPtr:
+ {
+ QList<void *> *li = *(QList<void *> **)d.constData();
+ void *ptr = li->at(idx);
+ return QVariant::fromValue((QObject*)ptr);
+ }
+ case Instance:
+ return d;
+ case Integer:
+ return QVariant(idx);
+ default:
+ case Invalid:
+ return QVariant();
+ }
+}
+
+bool QmlListAccessor::append(const QVariant &value)
+{
+ switch(m_type) {
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->append(const_cast<void *>(value.constData())); //XXX Typesafety
+ return true;
+ }
+ case QListPtr:
+ {
+ QList<void *> *li = *(QList<void *> **)d.constData();
+ li->append(*reinterpret_cast<void **>(const_cast<void *>(value.constData()))); //XXX Typesafety
+ return true;
+ }
+ case StringList:
+ case VariantList:
+ case Invalid:
+ case Instance:
+ case Integer:
+ default:
+ return false;
+ }
+}
+
+bool QmlListAccessor::insert(int index, const QVariant &value)
+{
+ switch(m_type) {
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->insert(index, const_cast<void *>(value.constData())); //XXX Typesafety
+ return true;
+ }
+ case QListPtr:
+ {
+ QList<void *> *li = *(QList<void *>**)d.constData();
+ li->insert(index, *reinterpret_cast<void **>(const_cast<void *>(value.constData()))); //XXX Typesafety
+ return true;
+ }
+ case StringList:
+ case VariantList:
+ case Invalid:
+ case Instance:
+ case Integer:
+ default:
+ return false;
+ }
+}
+
+bool QmlListAccessor::removeAt(int index)
+{
+ switch(m_type) {
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->removeAt(index);
+ return true;
+ }
+ case QListPtr:
+ {
+ QList<void *> *li = *(QList<void *>**)d.constData();
+ li->removeAt(index);
+ return true;
+ }
+ case StringList:
+ case VariantList:
+ case Invalid:
+ case Instance:
+ case Integer:
+ default:
+ return false;
+ }
+}
+
+bool QmlListAccessor::clear()
+{
+ switch(m_type) {
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->clear();
+ return true;
+ }
+ case QListPtr:
+ {
+ QList<void *> *li = *(QList<void *>**)d.constData();
+ li->clear();
+ return true;
+ }
+ case StringList:
+ case VariantList:
+ case Invalid:
+ case Instance:
+ case Integer:
+ default:
+ return false;
+ }
+}
+
+bool QmlListAccessor::isValid() const
+{
+ return m_type != Invalid;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmllistaccessor_p.h b/src/declarative/util/qmllistaccessor_p.h
new file mode 100644
index 0000000..3c67e3a
--- /dev/null
+++ b/src/declarative/util/qmllistaccessor_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLISTACCESSOR_H
+#define QMLLISTACCESSOR_H
+
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlEngine;
+class Q_DECLARATIVE_EXPORT QmlListAccessor
+{
+public:
+ QmlListAccessor();
+ ~QmlListAccessor();
+
+ QVariant list() const;
+ void setList(const QVariant &, QmlEngine * = 0);
+
+ bool isValid() const;
+
+ int count() const;
+ QVariant at(int) const;
+
+ bool append(const QVariant &);
+ bool insert(int, const QVariant &);
+ bool removeAt(int);
+ bool clear();
+
+ enum Type { Invalid, StringList, VariantList, QmlList, QListPtr, Instance, Integer };
+ Type type() const { return m_type; }
+
+private:
+ Type m_type;
+ QVariant d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLISTACCESSOR_H
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
new file mode 100644
index 0000000..61fc50d
--- /dev/null
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -0,0 +1,990 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmllistmodel_p.h"
+
+#include "qmlopenmetaobject_p.h"
+
+#include <qmlcustomparser_p.h>
+#include <qmlparser_p.h>
+#include <qmlengine_p.h>
+#include <qmlcontext.h>
+#include <qmlinfo.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstack.h>
+#include <QXmlStreamReader>
+#include <QtScript/qscriptvalueiterator.h>
+
+Q_DECLARE_METATYPE(QListModelInterface *)
+
+QT_BEGIN_NAMESPACE
+
+#define DATA_ROLE_ID 1
+#define DATA_ROLE_NAME "data"
+
+struct ListInstruction
+{
+ enum { Push, Pop, Value, Set } type;
+ int dataIdx;
+};
+
+struct ListModelData
+{
+ int dataOffset;
+ int instrCount;
+ ListInstruction *instructions() const { return (ListInstruction *)((char *)this + sizeof(ListModelData)); }
+};
+
+static void dump(ModelNode *node, int ind);
+
+/*!
+ \qmlclass ListModel QmlListModel
+ \brief The ListModel element defines a free-form list data source.
+
+ The ListModel is a simple hierarchy of elements containing data roles. The contents can
+ be defined dynamically, or explicitly in QML:
+
+ For example:
+
+ \code
+ ListModel {
+ id: fruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ }
+ }
+ \endcode
+
+ Roles (properties) must begin with a lower-case letter. The above example defines a
+ ListModel containing three elements, with the roles "name" and "cost".
+
+ The defined model can be used in views such as ListView:
+ \code
+ Component {
+ id: fruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ }
+ }
+
+ ListView {
+ model: fruitModel
+ delegate: fruitDelegate
+ anchors.fill: parent
+ }
+ \endcode
+
+ It is possible for roles to contain list data. In the example below we create a list of fruit attributes:
+
+ \code
+ ListModel {
+ id: fruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ attributes: [
+ ListElement { description: "Core" },
+ ListElement { description: "Deciduous" }
+ ]
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ attributes: [
+ ListElement { description: "Citrus" }
+ ]
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ attributes: [
+ ListElement { description: "Tropical" },
+ ListElement { description: "Seedless" }
+ ]
+ }
+ }
+ \endcode
+
+ The delegate below will list all the fruit attributes:
+ \code
+ Component {
+ id: fruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { id: name; text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ Row {
+ anchors.top: name.bottom
+ spacing: 5
+ Text { text: "Attributes:" }
+ Repeater {
+ dataSource: attributes
+ Component { Text { text: description } }
+ }
+ }
+ }
+ }
+ \endcode
+
+ The content of a ListModel may be created and modified using the clear(),
+ append(), and set() methods. For example:
+
+ \code
+ Component {
+ id: fruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+
+ // Double the price when clicked.
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: fruitModel.set(index, "cost", cost*2)
+ }
+ }
+ }
+ \endcode
+
+ When creating content dynamically, note that the set of available properties cannot be changed
+ except by first clearing the model - whatever properties are first added are then the
+ only permitted properties in the model.
+
+ \sa {qmlmodels}{Data Models}
+*/
+
+class ModelObject : public QObject
+{
+ Q_OBJECT
+public:
+ ModelObject();
+
+ void setValue(const QByteArray &name, const QVariant &val)
+ {
+ _mo->setValue(name, val);
+ }
+
+private:
+ QmlOpenMetaObject *_mo;
+};
+
+struct ModelNode
+{
+ ModelNode();
+ ~ModelNode();
+
+ QList<QVariant> values;
+ QHash<QString, ModelNode *> properties;
+
+ QmlListModel *model(const QmlListModel *parent) {
+ if (!modelCache) {
+ modelCache = new QmlListModel;
+ QmlEngine::setContextForObject(modelCache,QmlEngine::contextForObject(parent));
+
+ modelCache->_root = this;
+ }
+ return modelCache;
+ }
+
+ ModelObject *object(const QmlListModel *parent) {
+ if (!objectCache) {
+ objectCache = new ModelObject();
+ QHash<QString, ModelNode *>::iterator it;
+ for (it = properties.begin(); it != properties.end(); ++it) {
+ objectCache->setValue(it.key().toUtf8(), parent->valueForNode(*it));
+ }
+ }
+ return objectCache;
+ }
+
+ void setObjectValue(const QScriptValue& valuemap);
+ void setListValue(const QScriptValue& valuelist);
+
+ void setProperty(const QString& prop, const QVariant& val) {
+ QHash<QString, ModelNode *>::const_iterator it = properties.find(prop);
+ if (it != properties.end()) {
+ (*it)->values[0] = val;
+ } else {
+ ModelNode *n = new ModelNode;
+ n->values << val;
+ properties.insert(prop,n);
+ }
+ if (objectCache)
+ objectCache->setValue(prop.toUtf8(), val);
+ }
+
+ QmlListModel *modelCache;
+ ModelObject *objectCache;
+ bool isArray;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(ModelNode *)
+
+QT_BEGIN_NAMESPACE
+
+void ModelNode::setObjectValue(const QScriptValue& valuemap) {
+ QScriptValueIterator it(valuemap);
+ while (it.hasNext()) {
+ it.next();
+ ModelNode *value = new ModelNode;
+ QScriptValue v = it.value();
+ if (v.isArray()) {
+ value->isArray = true;
+ value->setListValue(v);
+ } else {
+ value->values << v.toVariant();
+ }
+ properties.insert(it.name(),value);
+ }
+}
+
+void ModelNode::setListValue(const QScriptValue& valuelist) {
+ QScriptValueIterator it(valuelist);
+ values.clear();
+ while (it.hasNext()) {
+ it.next();
+ ModelNode *value = new ModelNode;
+ QScriptValue v = it.value();
+ if (v.isArray()) {
+ value->isArray = true;
+ value->setListValue(v);
+ } else if (v.isObject()) {
+ value->setObjectValue(v);
+ } else {
+ value->values << v.toVariant();
+ }
+ values.append(qVariantFromValue(value));
+
+ }
+}
+
+
+ModelObject::ModelObject()
+: _mo(new QmlOpenMetaObject(this))
+{
+}
+
+QmlListModel::QmlListModel(QObject *parent)
+: QListModelInterface(parent), _rolesOk(false), _root(0)
+{
+}
+
+QmlListModel::~QmlListModel()
+{
+ delete _root;
+}
+
+void QmlListModel::checkRoles() const
+{
+ if (_rolesOk || !_root)
+ return;
+
+ for (int ii = 0; ii < _root->values.count(); ++ii) {
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(ii));
+ if (node) {
+ foreach (const QString &role, node->properties.keys())
+ addRole(role);
+ }
+ }
+
+ _rolesOk = true;
+}
+
+void QmlListModel::addRole(const QString &role) const
+{
+ if (!roleStrings.contains(role))
+ roleStrings << role;
+}
+
+QList<int> QmlListModel::roles() const
+{
+ checkRoles();
+ QList<int> rv;
+ for (int ii = 0; ii < roleStrings.count(); ++ii)
+ rv << ii;
+ return rv;
+}
+
+QString QmlListModel::toString(int role) const
+{
+ checkRoles();
+ if (role < roleStrings.count())
+ return roleStrings.at(role);
+ else
+ return QString();
+}
+
+QVariant QmlListModel::valueForNode(ModelNode *node) const
+{
+ QObject *rv = 0;
+
+ if (node->isArray) {
+ // List
+ rv = node->model(this);
+ } else {
+ if (!node->properties.isEmpty()) {
+ // Object
+ rv = node->object(this);
+ } else if (node->values.count() == 0) {
+ // Invalid
+ return QVariant();
+ } else if (node->values.count() == 1) {
+ // Value
+ QVariant &var = node->values[0];
+ ModelNode *valueNode = qvariant_cast<ModelNode *>(var);
+ if (valueNode) {
+ if (!valueNode->properties.isEmpty())
+ rv = valueNode->object(this);
+ else
+ rv = valueNode->model(this);
+ } else {
+ return var;
+ }
+ }
+ }
+
+ if (rv)
+ return QVariant::fromValue(rv);
+ else
+ return QVariant();
+}
+
+QHash<int,QVariant> QmlListModel::data(int index, const QList<int> &roles) const
+{
+ checkRoles();
+ QHash<int, QVariant> rv;
+ if (index >= count() || index < 0)
+ return rv;
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return rv;
+
+ for (int ii = 0; ii < roles.count(); ++ii) {
+ const QString &roleString = roleStrings.at(roles.at(ii));
+
+ QHash<QString, ModelNode *>::ConstIterator iter =
+ node->properties.find(roleString);
+ if (iter != node->properties.end()) {
+ ModelNode *row = *iter;
+ rv.insert(roles.at(ii), valueForNode(row));
+ }
+ }
+
+ return rv;
+}
+
+QVariant QmlListModel::data(int index, int role) const
+{
+ checkRoles();
+ QVariant rv;
+ if (index >= count() || index < 0)
+ return rv;
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return rv;
+
+ const QString &roleString = roleStrings.at(role);
+
+ QHash<QString, ModelNode *>::ConstIterator iter =
+ node->properties.find(roleString);
+ if (iter != node->properties.end()) {
+ ModelNode *row = *iter;
+ rv = valueForNode(row);
+ }
+
+ return rv;
+}
+
+/*!
+ \qmlproperty int ListModel::count
+ The number of data entries in the model.
+*/
+int QmlListModel::count() const
+{
+ if (!_root) return 0;
+ return _root->values.count();
+}
+
+/*!
+ \qmlmethod ListModel::clear()
+
+ Deletes all content from the model. The properties are cleared such that
+ different properties may be set on subsequent additions.
+
+ \sa append() remove()
+*/
+void QmlListModel::clear()
+{
+ int cleared = count();
+ _rolesOk = false;
+ delete _root;
+ _root = 0;
+ roleStrings.clear();
+ emit itemsRemoved(0,cleared);
+ emit countChanged(0);
+}
+
+/*!
+ \qmlmethod ListModel::remove(int index)
+
+ Deletes the content at \a index from the model.
+
+ \sa clear()
+*/
+void QmlListModel::remove(int index)
+{
+ if (!_root || index < 0 || index >= _root->values.count()) {
+ qmlInfo(this) << tr("remove: index %1 out of range").arg(index);
+ return;
+ }
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ _root->values.removeAt(index);
+ if (node)
+ delete node;
+ emit itemsRemoved(index,1);
+ emit countChanged(_root->values.count());
+}
+
+/*!
+ \qmlmethod ListModel::insert(int index, jsobject dict)
+
+ Adds a new item to the list model at position \a index, with the
+ values in \a dict.
+
+ \code
+ FruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ The \a index must be to an existing item in the list, or one past
+ the end of the list (equivalent to append).
+
+ \sa set() append()
+*/
+void QmlListModel::insert(int index, const QScriptValue& valuemap)
+{
+ if (!valuemap.isObject() || valuemap.isArray()) {
+ qmlInfo(this) << tr("insert: value is not an object");
+ return;
+ }
+ if (!_root)
+ _root = new ModelNode;
+ if (index >= _root->values.count() || index<0) {
+ if (index == _root->values.count())
+ append(valuemap);
+ else
+ qmlInfo(this) << tr("insert: index %1 out of range").arg(index);
+ return;
+ }
+ ModelNode *mn = new ModelNode;
+ mn->setObjectValue(valuemap);
+ _root->values.insert(index,qVariantFromValue(mn));
+ emit itemsInserted(index,1);
+ emit countChanged(_root->values.count());
+}
+
+/*!
+ \qmlmethod ListModel::move(int from, int to, int n)
+
+ Moves \a n items \a from one position \a to another.
+
+ The from and to ranges must exist; for example, to move the first 3 items
+ to the end of the list:
+
+ \code
+ FruitModel.move(0,FruitModel.count-3,3)
+ \endcode
+
+ \sa append()
+*/
+void QmlListModel::move(int from, int to, int n)
+{
+ if (n==0 || from==to)
+ return;
+ if (from+n > count() || to+n > count() || from < 0 || to < 0 || n < 0) {
+ qmlInfo(this) << tr("move: out of range");
+ return;
+ }
+ int origfrom=from; // preserve actual move, so any animations are correct
+ int origto=to;
+ int orign=n;
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+ if (n==1) {
+ _root->values.move(from,to);
+ } else {
+ QList<QVariant> replaced;
+ int i=0;
+ QVariantList::const_iterator it=_root->values.begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=_root->values.begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ QVariantList::const_iterator f=replaced.begin();
+ QVariantList::iterator t=_root->values.begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+ emit itemsMoved(origfrom,origto,orign);
+}
+
+/*!
+ \qmlmethod ListModel::append(jsobject dict)
+
+ Adds a new item to the end of the list model, with the
+ values in \a dict.
+
+ \code
+ FruitModel.append({"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ \sa set() remove()
+*/
+void QmlListModel::append(const QScriptValue& valuemap)
+{
+ if (!valuemap.isObject() || valuemap.isArray()) {
+ qmlInfo(this) << tr("append: value is not an object");
+ return;
+ }
+ if (!_root)
+ _root = new ModelNode;
+ ModelNode *mn = new ModelNode;
+ mn->setObjectValue(valuemap);
+ _root->values << qVariantFromValue(mn);
+ emit itemsInserted(count()-1,1);
+ emit countChanged(_root->values.count());
+}
+
+/*!
+ \qmlmethod object ListModel::get(int index)
+
+ Returns the item at \a index in the list model.
+
+ \code
+ FruitModel.append({"cost": 5.95, "name":"Jackfruit"})
+ FruitModel.get(0).cost
+ \endcode
+
+ The \a index must be an element in the list.
+
+ Note that properties of the returned object that are themselves objects
+ will also be models, and this get() method is used to access elements:
+
+ \code
+ FruitModel.append(..., "attributes":
+ [{"name":"spikes","value":"7mm"},
+ {"name":"color","value":"green"}]);
+ FruitModel.get(0).attributes.get(1).value; // == "green"
+ \endcode
+
+ \sa append()
+*/
+QScriptValue QmlListModel::get(int index) const
+{
+ if (index >= count() || index < 0) {
+ qmlInfo(this) << tr("get: index %1 out of range").arg(index);
+ return 0;
+ }
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return 0;
+ QmlEngine *eng = qmlEngine(this);
+ if (!eng) {
+ qWarning("Cannot call QmlListModel::get() without a QmlEngine");
+ return 0;
+ }
+ return QmlEnginePrivate::qmlScriptObject(node->object(this), eng);
+}
+
+/*!
+ \qmlmethod ListModel::set(int index, jsobject dict)
+
+ Changes the item at \a index in the list model with the
+ values in \a dict. Properties not appearing in \a valuemap
+ are left unchanged.
+
+ \code
+ FruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ The \a index must be an element in the list.
+
+ \sa append()
+*/
+void QmlListModel::set(int index, const QScriptValue& valuemap)
+{
+ if (!valuemap.isObject() || valuemap.isArray()) {
+ qmlInfo(this) << tr("set: value is not an object");
+ return;
+ }
+ if ( !_root || index > _root->values.count() || index < 0) {
+ qmlInfo(this) << tr("set: index %1 out of range").arg(index);
+ return;
+ }
+ if (index == _root->values.count())
+ append(valuemap);
+ else {
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ QList<int> roles;
+ node->setObjectValue(valuemap);
+ QScriptValueIterator it(valuemap);
+ while (it.hasNext()) {
+ it.next();
+ int r = roleStrings.indexOf(it.name());
+ if (r<0) {
+ r = roleStrings.count();
+ roleStrings << it.name();
+ }
+ roles.append(r);
+ }
+ emit itemsChanged(index,1,roles);
+ }
+}
+
+/*!
+ \qmlmethod ListModel::setProperty(int index, string property, variant value)
+
+ Changes the \a property of the item at \a index in the list model to \a value.
+
+ \code
+ FruitModel.set(3, "cost", 5.95)
+ \endcode
+
+ The \a index must be an element in the list.
+
+ \sa append()
+*/
+void QmlListModel::setProperty(int index, const QString& property, const QVariant& value)
+{
+ if ( !_root || index >= _root->values.count() || index < 0) {
+ qmlInfo(this) << tr("set: index %1 out of range").arg(index);
+ return;
+ }
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ int r = roleStrings.indexOf(property);
+ if (r<0) {
+ r = roleStrings.count();
+ roleStrings << property;
+ }
+ QList<int> roles;
+ roles.append(r);
+
+ if (node)
+ node->setProperty(property,value);
+ emit itemsChanged(index,1,roles);
+}
+
+class QmlListModelParser : public QmlCustomParser
+{
+public:
+ QByteArray compile(const QList<QmlCustomParserProperty> &);
+ bool compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data);
+ void setCustomData(QObject *, const QByteArray &);
+
+private:
+ bool definesEmptyList(const QString &);
+};
+
+bool QmlListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data)
+{
+ QList<QVariant> values = prop.assignedValues();
+ for(int ii = 0; ii < values.count(); ++ii) {
+ const QVariant &value = values.at(ii);
+
+ if(value.userType() == qMetaTypeId<QmlCustomParserNode>()) {
+ QmlCustomParserNode node =
+ qvariant_cast<QmlCustomParserNode>(value);
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Push;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ QList<QmlCustomParserProperty> props = node.properties();
+ for(int jj = 0; jj < props.count(); ++jj) {
+ const QmlCustomParserProperty &nodeProp = props.at(jj);
+ if (nodeProp.name() == "") {
+ error(nodeProp, QmlListModel::tr("ListElement: cannot use default property"));
+ return false;
+ }
+ if (nodeProp.name() == "id") {
+ error(nodeProp, QmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
+ return false;
+ }
+
+ ListInstruction li;
+ int ref = data.count();
+ data.append(nodeProp.name());
+ data.append('\0');
+ li.type = ListInstruction::Set;
+ li.dataIdx = ref;
+ instr << li;
+
+ if(!compileProperty(nodeProp, instr, data))
+ return false;
+
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ } else {
+
+ QmlParser::Variant variant =
+ qvariant_cast<QmlParser::Variant>(value);
+
+ int ref = data.count();
+ QByteArray d = variant.asScript().toUtf8();
+ d.append('\0');
+ data.append(d);
+
+ ListInstruction li;
+ li.type = ListInstruction::Value;
+ li.dataIdx = ref;
+ instr << li;
+
+ }
+ }
+
+ return true;
+}
+
+QByteArray QmlListModelParser::compile(const QList<QmlCustomParserProperty> &customProps)
+{
+ QList<ListInstruction> instr;
+ QByteArray data;
+
+ for(int ii = 0; ii < customProps.count(); ++ii) {
+ const QmlCustomParserProperty &prop = customProps.at(ii);
+ if(prop.name() != "") { // isn't default property
+ error(prop, QmlListModel::tr("ListModel: undefined property '%1'").arg(QString::fromUtf8(prop.name())));
+ return QByteArray();
+ }
+
+ if(!compileProperty(prop, instr, data)) {
+ return QByteArray();
+ }
+ }
+
+ int size = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction) +
+ data.count();
+
+ QByteArray rv;
+ rv.resize(size);
+
+ ListModelData *lmd = (ListModelData *)rv.data();
+ lmd->dataOffset = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction);
+ lmd->instrCount = instr.count();
+ for (int ii = 0; ii < instr.count(); ++ii)
+ lmd->instructions()[ii] = instr.at(ii);
+ ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
+
+ return rv;
+}
+
+void QmlListModelParser::setCustomData(QObject *obj, const QByteArray &d)
+{
+ QmlListModel *rv = static_cast<QmlListModel *>(obj);
+
+ ModelNode *root = new ModelNode;
+ rv->_root = root;
+ QStack<ModelNode *> nodes;
+ nodes << root;
+
+ bool processingSet = false;
+
+ const ListModelData *lmd = (const ListModelData *)d.constData();
+ const char *data = ((const char *)lmd) + lmd->dataOffset;
+
+ for (int ii = 0; ii < lmd->instrCount; ++ii) {
+ const ListInstruction &instr = lmd->instructions()[ii];
+
+ switch(instr.type) {
+ case ListInstruction::Push:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode;
+ n->values << qVariantFromValue(n2);
+ nodes.push(n2);
+ if (processingSet)
+ n->isArray = true;
+ }
+ break;
+
+ case ListInstruction::Pop:
+ nodes.pop();
+ break;
+
+ case ListInstruction::Value:
+ {
+ ModelNode *n = nodes.top();
+ QString s = QString::fromUtf8(QByteArray(data + instr.dataIdx));
+
+ bool isEmptyList = false;
+ if (!n->isArray)
+ isEmptyList = definesEmptyList(s);
+ if (isEmptyList)
+ n->isArray = true;
+ else
+ n->values.append(s);
+
+ processingSet = false;
+ }
+ break;
+
+ case ListInstruction::Set:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode;
+ n->properties.insert(QString::fromUtf8(data + instr.dataIdx), n2);
+ nodes.push(n2);
+ processingSet = true;
+ }
+ break;
+ }
+ }
+}
+
+bool QmlListModelParser::definesEmptyList(const QString &s)
+{
+ if (s.startsWith(QLatin1Char('[')) && s.endsWith(QLatin1Char(']'))) {
+ for (int i=1; i<s.length()-1; i++) {
+ if (!s[i].isSpace())
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+QML_DEFINE_CUSTOM_TYPE(Qt, 4,6, ListModel, QmlListModel, QmlListModelParser)
+
+/*!
+ \qmlclass ListElement
+ \brief The ListElement element defines a data item in a ListModel.
+
+ \sa ListModel
+*/
+// ### FIXME
+class QmlListElement : public QObject
+{
+Q_OBJECT
+};
+QML_DEFINE_TYPE(Qt,4,6,ListElement,QmlListElement)
+
+static void dump(ModelNode *node, int ind)
+{
+ QByteArray indentBa(ind * 4, ' ');
+ const char *indent = indentBa.constData();
+
+ for (int ii = 0; ii < node->values.count(); ++ii) {
+ ModelNode *subNode = qvariant_cast<ModelNode *>(node->values.at(ii));
+ if (subNode) {
+ qWarning().nospace() << indent << "Sub-node " << ii;
+ dump(subNode, ind + 1);
+ } else {
+ qWarning().nospace() << indent << "Sub-node " << ii << ": " << node->values.at(ii).toString();
+ }
+ }
+
+ for (QHash<QString, ModelNode *>::ConstIterator iter = node->properties.begin(); iter != node->properties.end(); ++iter) {
+ qWarning().nospace() << indent << "Property " << iter.key() << ':';
+ dump(iter.value(), ind + 1);
+ }
+}
+
+ModelNode::ModelNode()
+: modelCache(0), objectCache(0), isArray(false)
+{
+}
+
+ModelNode::~ModelNode()
+{
+ qDeleteAll(properties);
+ for (int ii = 0; ii < values.count(); ++ii) {
+ ModelNode *node = qvariant_cast<ModelNode *>(values.at(ii));
+ if (node) { delete node; node = 0; }
+ }
+ if (modelCache) { modelCache->_root = 0/* ==this */; delete modelCache; modelCache = 0; }
+ if (objectCache) { delete objectCache; }
+}
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlListElement)
+
+#include <qmllistmodel.moc>
diff --git a/src/declarative/util/qmllistmodel_p.h b/src/declarative/util/qmllistmodel_p.h
new file mode 100644
index 0000000..e18d3fd
--- /dev/null
+++ b/src/declarative/util/qmllistmodel_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLISTMODEL_H
+#define QMLLISTMODEL_H
+
+#include <qml.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+#include "../3rdparty/qlistmodelinterface_p.h"
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+struct ModelNode;
+class Q_DECLARATIVE_EXPORT QmlListModel : public QListModelInterface
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ QmlListModel(QObject *parent=0);
+ ~QmlListModel();
+
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+ virtual int count() const;
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual QVariant data(int index, int role) const;
+
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void remove(int index);
+ Q_INVOKABLE void append(const QScriptValue&);
+ Q_INVOKABLE void insert(int index, const QScriptValue&);
+ Q_INVOKABLE QScriptValue get(int index) const;
+ Q_INVOKABLE void set(int index, const QScriptValue&);
+ Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value);
+ Q_INVOKABLE void move(int from, int to, int count);
+
+Q_SIGNALS:
+ void countChanged(int);
+
+private:
+ QVariant valueForNode(ModelNode *) const;
+ mutable QStringList roleStrings;
+ friend class QmlListModelParser;
+ friend struct ModelNode;
+
+ void checkRoles() const;
+ void addRole(const QString &) const;
+ mutable bool _rolesOk;
+ ModelNode *_root;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlListModel)
+
+QT_END_HEADER
+
+#endif // QMLLISTMODEL_H
diff --git a/src/declarative/util/qmlnullablevalue_p_p.h b/src/declarative/util/qmlnullablevalue_p_p.h
new file mode 100644
index 0000000..151a3d4
--- /dev/null
+++ b/src/declarative/util/qmlnullablevalue_p_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLNULLABLEVALUE_P_H
+#define QMLNULLABLEVALUE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+template<typename T>
+struct QmlNullableValue
+{
+ QmlNullableValue()
+ : isNull(true), value(T()) {}
+ QmlNullableValue(const QmlNullableValue<T> &o)
+ : isNull(o.isNull), value(o.value) {}
+ QmlNullableValue(const T &t)
+ : isNull(false), value(t) {}
+ QmlNullableValue<T> &operator=(const T &t)
+ { isNull = false; value = t; return *this; }
+ QmlNullableValue<T> &operator=(const QmlNullableValue<T> &o)
+ { isNull = o.isNull; value = o.value; return *this; }
+ operator T() const { return value; }
+
+ void invalidate() { isNull = true; }
+ bool isValid() const { return !isNull; }
+ bool isNull;
+ T value;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLNULLABLEVALUE_P_H
diff --git a/src/declarative/util/qmlnumberformatter.cpp b/src/declarative/util/qmlnumberformatter.cpp
new file mode 100644
index 0000000..073dc68
--- /dev/null
+++ b/src/declarative/util/qmlnumberformatter.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlnumberformatter_p.h"
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//TODO: set locale
+// docs
+// this is a wrapper around qnumberformat (test integration)
+// if number or format haven't been explictly set, text should be an empty string
+
+class QmlNumberFormatterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlNumberFormatter)
+public:
+ QmlNumberFormatterPrivate() : locale(QLocale::system()), number(0), componentComplete(true) {}
+
+ void updateText();
+
+ QLocale locale;
+ QString format;
+ QNumberFormat numberFormat;
+ QString text;
+ qreal number;
+ bool componentComplete;
+};
+/*!
+ \qmlclass NumberFormatter
+ \brief The NumberFormatter allows you to control the format of a number string.
+
+ The format property documentation has more details on how the format can be manipulated.
+
+ In the following example, the text element will display the text "1,234.57".
+ \code
+ NumberFormatter { id: formatter; number: 1234.5678; format: "##,##0.##" }
+ Text { text: formatter.text }
+ \endcode
+
+ */
+/*!
+ \internal
+ \class QmlNumberFormatter
+ \ingroup group_utility
+ \brief The QmlNumberFormatter class allows you to format a number to a particular string format/locale specific number format.
+*/
+
+QmlNumberFormatter::QmlNumberFormatter(QObject *parent)
+: QObject(*(new QmlNumberFormatterPrivate), parent)
+{
+}
+
+QmlNumberFormatter::~QmlNumberFormatter()
+{
+}
+
+/*!
+ \qmlproperty string NumberFormatter::text
+
+ The number in the specified format.
+
+ If no format is specified the text will be empty.
+*/
+
+QString QmlNumberFormatter::text() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->text;
+}
+
+/*!
+ \qmlproperty real NumberFormatter::number
+
+ A single point precision number. (Doubles are not yet supported)
+
+*/
+qreal QmlNumberFormatter::number() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->number;
+}
+
+/*!
+ \qmlproperty string NumberFormatter::format
+
+ The particular format the number will adhere to during the conversion to text.
+
+ The format syntax follows a style similar to the Unicode Standard (UTS35).
+
+ The table below shows the characters, patterns that can be used in the format.
+
+ \table
+ \header
+ \o Character
+ \o Meaning
+ \row
+ \o #
+ \o Any digit(s), zero shows as absent (for leading/trailing zeroes).
+ \row
+ \o 0
+ \o Implicit digit. Zero will show in the case that the input number is too small.
+ \row
+ \o .
+ \o Decimal separator. Output decimal seperator will be dependant on system locale.
+ \row
+ \o ,
+ \o Grouping separator. The number of digits (either #, or 0) between the grouping separator and the decimal (or the rightmost digit) will determine the groupingSize).
+ \row
+ \o other
+ \o Any other character will be taken as a string literal and placed directly into the output string.
+ \endtable
+
+ Invalid formats will not guarantee a meaningful text output.
+
+ \note Input numbers that are too long for the given format will be rounded dependent on precison based on the position of the decimal point.
+
+ The following table illustrates the output text created by applying some examples of numeric formats to the formatter.
+
+ \table
+ \header
+ \o Format
+ \o Number
+ \o Output
+ \row
+ \o ###
+ \o 123456
+ \o 123456
+ \row
+ \o 000
+ \o 123456
+ \o 123456
+ \row
+ \o ######
+ \o 1234
+ \o 1234
+ \row
+ \o 000000
+ \o 1234
+ \o 001234
+ \row
+ \o ##,##0.##
+ \o 1234.456
+ \o 1,234.46 (for US locale)
+ \codeline 1 234,46 (for FR locale)
+ \row
+ \o 000000,000.#
+ \o 123456
+ \o 000,123,456 (for US locale)
+ \codeline 000 123 456 (for FR locale)
+ \row
+ \o 0.0###
+ \o 0.999997
+ \o 1.0
+ \row
+ \o (000) 000 - 000
+ \o 12345678
+ \o (012) 345 - 678
+ \row
+ \o #A
+ \o 12
+ \o 12A
+ \endtable
+
+*/
+QString QmlNumberFormatter::format() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->format;
+}
+
+void QmlNumberFormatter::setNumber(const qreal &number)
+{
+ Q_D(QmlNumberFormatter);
+ if (d->number == number)
+ return;
+ d->number = number;
+ d->updateText();
+}
+
+void QmlNumberFormatter::setFormat(const QString &format)
+{
+ Q_D(QmlNumberFormatter);
+ //no format checking
+ if (format.isEmpty())
+ d->format = QString::null;
+ else
+ d->format = format;
+ d->updateText();
+}
+
+void QmlNumberFormatterPrivate::updateText()
+{
+ Q_Q(QmlNumberFormatter);
+ if (!componentComplete)
+ return;
+
+ QNumberFormat tempFormat;
+ tempFormat.setFormat(format);
+ tempFormat.setNumber(number);
+
+ text = tempFormat.text();
+
+ emit q->textChanged();
+}
+
+void QmlNumberFormatter::classBegin()
+{
+ Q_D(QmlNumberFormatter);
+ d->componentComplete = false;
+}
+
+void QmlNumberFormatter::componentComplete()
+{
+ Q_D(QmlNumberFormatter);
+ d->componentComplete = true;
+ d->updateText();
+}
+QML_DEFINE_TYPE(Qt,4,6,NumberFormatter,QmlNumberFormatter);
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlnumberformatter_p.h b/src/declarative/util/qmlnumberformatter_p.h
new file mode 100644
index 0000000..71fceb2
--- /dev/null
+++ b/src/declarative/util/qmlnumberformatter_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLNUMBERFORMATTER_H
+#define QMLNUMBERFORMATTER_H
+
+#include "qnumberformat_p.h"
+
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlNumberFormatterPrivate;
+class Q_DECLARATIVE_EXPORT QmlNumberFormatter : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
+ Q_PROPERTY(QString format READ format WRITE setFormat)
+ Q_PROPERTY(qreal number READ number WRITE setNumber)
+public:
+ QmlNumberFormatter(QObject *parent=0);
+ ~QmlNumberFormatter();
+
+ QString text() const;
+
+ qreal number() const;
+ void setNumber(const qreal &);
+
+ QString format() const;
+ void setFormat(const QString &);
+
+ virtual void classBegin();
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ Q_DISABLE_COPY(QmlNumberFormatter)
+ Q_DECLARE_PRIVATE(QmlNumberFormatter)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlNumberFormatter)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qmlopenmetaobject.cpp b/src/declarative/util/qmlopenmetaobject.cpp
new file mode 100644
index 0000000..1be81de
--- /dev/null
+++ b/src/declarative/util/qmlopenmetaobject.cpp
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlopenmetaobject_p.h"
+#include "qmlpropertycache_p.h"
+#include "qmldeclarativedata_p.h"
+#include <qmetaobjectbuilder_p.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QmlOpenMetaObjectTypePrivate
+{
+public:
+ QmlOpenMetaObjectTypePrivate() : mem(0), cache(0), engine(0) {}
+
+ void init(const QMetaObject *metaObj);
+
+ int propertyOffset;
+ int signalOffset;
+ QHash<QByteArray, int> names;
+ QMetaObjectBuilder mob;
+ QMetaObject *mem;
+ QmlPropertyCache *cache;
+ QmlEngine *engine;
+ QSet<QmlOpenMetaObject*> referers;
+};
+
+QmlOpenMetaObjectType::QmlOpenMetaObjectType(const QMetaObject *base, QmlEngine *engine)
+ : d(new QmlOpenMetaObjectTypePrivate)
+{
+ d->engine = engine;
+ d->init(base);
+}
+
+QmlOpenMetaObjectType::~QmlOpenMetaObjectType()
+{
+ if (d->mem)
+ qFree(d->mem);
+ if (d->cache)
+ d->cache->release();
+ delete d;
+}
+
+
+int QmlOpenMetaObjectType::propertyOffset() const
+{
+ return d->propertyOffset;
+}
+
+int QmlOpenMetaObjectType::signalOffset() const
+{
+ return d->signalOffset;
+}
+
+int QmlOpenMetaObjectType::createProperty(const QByteArray &name)
+{
+ int id = d->mob.propertyCount();
+ d->mob.addSignal("__" + QByteArray::number(id) + "()");
+ QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
+ build.setDynamic(true);
+ propertyCreated(id, build);
+ qFree(d->mem);
+ d->mem = d->mob.toMetaObject();
+ d->names.insert(name, id);
+ QSet<QmlOpenMetaObject*>::iterator it = d->referers.begin();
+ while (it != d->referers.end()) {
+ QmlOpenMetaObject *omo = *it;
+ *static_cast<QMetaObject *>(omo) = *d->mem;
+ if (d->cache)
+ d->cache->update(d->engine, omo);
+ ++it;
+ }
+
+ return d->propertyOffset + id;
+}
+
+void QmlOpenMetaObjectType::propertyCreated(int id, QMetaPropertyBuilder &builder)
+{
+ if (d->referers.count())
+ (*d->referers.begin())->propertyCreated(id, builder);
+}
+
+void QmlOpenMetaObjectTypePrivate::init(const QMetaObject *metaObj)
+{
+ if (!mem) {
+ mob.setSuperClass(metaObj);
+ mob.setClassName(metaObj->className());
+ mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+
+ mem = mob.toMetaObject();
+
+ propertyOffset = mem->propertyOffset();
+ signalOffset = mem->methodOffset();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+class QmlOpenMetaObjectPrivate
+{
+public:
+ QmlOpenMetaObjectPrivate(QmlOpenMetaObject *_q)
+ : q(_q), parent(0), type(0), cacheProperties(false) {}
+
+ inline QVariant &getData(int idx) {
+ while (data.count() <= idx)
+ data << QPair<QVariant, bool>(QVariant(), false);
+ QPair<QVariant, bool> &prop = data[idx];
+ if (!prop.second) {
+ prop.first = q->initialValue(idx);
+ prop.second = true;
+ }
+ return prop.first;
+ }
+
+ inline void writeData(int idx, const QVariant &value) {
+ while (data.count() <= idx)
+ data << QPair<QVariant, bool>(QVariant(), false);
+ QPair<QVariant, bool> &prop = data[idx];
+ prop.first = value;
+ prop.second = true;
+ }
+
+ bool autoCreate;
+ QmlOpenMetaObject *q;
+ QAbstractDynamicMetaObject *parent;
+ QList<QPair<QVariant, bool> > data;
+ QObject *object;
+ QmlOpenMetaObjectType *type;
+ bool cacheProperties;
+};
+
+QmlOpenMetaObject::QmlOpenMetaObject(QObject *obj, bool automatic)
+: d(new QmlOpenMetaObjectPrivate(this))
+{
+ d->autoCreate = automatic;
+ d->object = obj;
+
+ d->type = new QmlOpenMetaObjectType(obj->metaObject(), 0);
+ d->type->d->referers.insert(this);
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ *static_cast<QMetaObject *>(this) = *d->type->d->mem;
+ op->metaObject = this;
+}
+
+QmlOpenMetaObject::QmlOpenMetaObject(QObject *obj, QmlOpenMetaObjectType *type, bool automatic)
+: d(new QmlOpenMetaObjectPrivate(this))
+{
+ d->autoCreate = automatic;
+ d->object = obj;
+
+ d->type = type;
+ d->type->addref();
+ d->type->d->referers.insert(this);
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ *static_cast<QMetaObject *>(this) = *d->type->d->mem;
+ op->metaObject = this;
+}
+
+QmlOpenMetaObject::~QmlOpenMetaObject()
+{
+ if (d->parent)
+ delete d->parent;
+ d->type->d->referers.remove(this);
+ d->type->release();
+ delete d;
+}
+
+QmlOpenMetaObjectType *QmlOpenMetaObject::type() const
+{
+ return d->type;
+}
+
+int QmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
+ && id >= d->type->d->propertyOffset) {
+ int propId = id - d->type->d->propertyOffset;
+ if (c == QMetaObject::ReadProperty) {
+ propertyRead(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
+ } else if (c == QMetaObject::WriteProperty) {
+ if (d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ propertyWrite(propId);
+ d->writeData(propId, *reinterpret_cast<QVariant *>(a[0]));
+ activate(d->object, d->type->d->signalOffset + propId, 0);
+ }
+ }
+ return -1;
+ } else {
+ if (d->parent)
+ return d->parent->metaCall(c, id, a);
+ else
+ return d->object->qt_metacall(c, id, a);
+ }
+}
+
+QAbstractDynamicMetaObject *QmlOpenMetaObject::parent() const
+{
+ return d->parent;
+}
+
+QVariant QmlOpenMetaObject::value(int id) const
+{
+ return d->getData(id);
+}
+
+void QmlOpenMetaObject::setValue(int id, const QVariant &value)
+{
+ d->writeData(id, value);
+ activate(d->object, id + d->type->d->signalOffset, 0);
+}
+
+QVariant QmlOpenMetaObject::value(const QByteArray &name) const
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+ if (iter == d->type->d->names.end())
+ return QVariant();
+
+ return d->getData(*iter);
+}
+
+QVariant &QmlOpenMetaObject::operator[](const QByteArray &name)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+ Q_ASSERT(iter != d->type->d->names.end());
+
+ return d->getData(*iter);
+}
+
+void QmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+
+ int id = -1;
+ if (iter == d->type->d->names.end()) {
+ id = d->type->createProperty(name.constData()) - d->type->d->propertyOffset;
+ } else {
+ id = *iter;
+ }
+
+ QVariant &dataVal = d->getData(id);
+ if (dataVal == val)
+ return;
+
+ dataVal = val;
+ activate(d->object, id + d->type->d->signalOffset, 0);
+}
+
+void QmlOpenMetaObject::setCached(bool c)
+{
+ if (c == d->cacheProperties || !d->type->d->engine)
+ return;
+
+ d->cacheProperties = c;
+
+ QmlDeclarativeData *qmldata = QmlDeclarativeData::get(d->object, true);
+ if (d->cacheProperties) {
+ if (!d->type->d->cache)
+ d->type->d->cache = QmlPropertyCache::create(d->type->d->engine, this);
+ qmldata->propertyCache = d->type->d->cache;
+ d->type->d->cache->addref();
+ } else {
+ if (d->type->d->cache)
+ d->type->d->cache->release();
+ qmldata->propertyCache = 0;
+ }
+}
+
+
+int QmlOpenMetaObject::createProperty(const char *name, const char *)
+{
+ if (d->autoCreate)
+ return d->type->createProperty(name);
+ else
+ return -1;
+}
+
+void QmlOpenMetaObject::propertyRead(int)
+{
+}
+
+void QmlOpenMetaObject::propertyWrite(int)
+{
+}
+
+void QmlOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &)
+{
+}
+
+QVariant QmlOpenMetaObject::initialValue(int)
+{
+ return QVariant();
+}
+
+int QmlOpenMetaObject::count() const
+{
+ return d->type->d->names.count();
+}
+
+QByteArray QmlOpenMetaObject::name(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < d->type->d->names.count());
+
+ return d->type->d->mob.property(idx).name();
+}
+
+QObject *QmlOpenMetaObject::object() const
+{
+ return d->object;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlopenmetaobject_p.h b/src/declarative/util/qmlopenmetaobject_p.h
new file mode 100644
index 0000000..c6da71a
--- /dev/null
+++ b/src/declarative/util/qmlopenmetaobject_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOPENMETAOBJECT_H
+#define QMLOPENMETAOBJECT_H
+
+#include <private/qmlrefcount_p.h>
+#include <QtCore/QMetaObject>
+#include <QtCore/QObject>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlEngine;
+class QMetaPropertyBuilder;
+class QmlOpenMetaObjectTypePrivate;
+class Q_DECLARATIVE_EXPORT QmlOpenMetaObjectType : public QmlRefCount
+{
+public:
+ QmlOpenMetaObjectType(const QMetaObject *base, QmlEngine *engine);
+ ~QmlOpenMetaObjectType();
+
+ int createProperty(const QByteArray &name);
+
+ int propertyOffset() const;
+ int signalOffset() const;
+
+protected:
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
+
+private:
+ QmlOpenMetaObjectTypePrivate *d;
+ friend class QmlOpenMetaObject;
+ friend class QmlOpenMetaObjectPrivate;
+};
+
+class QmlOpenMetaObjectPrivate;
+class Q_DECLARATIVE_EXPORT QmlOpenMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlOpenMetaObject(QObject *, bool = true);
+ QmlOpenMetaObject(QObject *, QmlOpenMetaObjectType *, bool = true);
+ ~QmlOpenMetaObject();
+
+ QVariant value(const QByteArray &) const;
+ void setValue(const QByteArray &, const QVariant &);
+ QVariant value(int) const;
+ void setValue(int, const QVariant &);
+ QVariant &operator[](const QByteArray &);
+
+ int count() const;
+ QByteArray name(int) const;
+
+ QObject *object() const;
+ virtual QVariant initialValue(int);
+
+ // Be careful - once setCached(true) is called createProperty() is no
+ // longer automatically called for new properties.
+ void setCached(bool);
+
+ QmlOpenMetaObjectType *type() const;
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int createProperty(const char *, const char *);
+
+ virtual void propertyRead(int);
+ virtual void propertyWrite(int);
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
+
+ QAbstractDynamicMetaObject *parent() const;
+
+private:
+ QmlOpenMetaObjectPrivate *d;
+ friend class QmlOpenMetaObjectType;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLOPENMETAOBJECT_H
diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp
new file mode 100644
index 0000000..3214dc8
--- /dev/null
+++ b/src/declarative/util/qmlpackage.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpackage_p.h"
+
+#include <private/qobject_p.h>
+#include "private/qmlguard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlPackagePrivate : public QObjectPrivate
+{
+public:
+ QmlPackagePrivate() {}
+
+ class DataList;
+ struct DataGuard : public QmlGuard<QObject>
+ {
+ DataGuard(QObject *obj, DataList *l) : list(l) { (QmlGuard<QObject>&)*this = obj; }
+ DataList *list;
+ void objectDestroyed(QObject *) {
+ // we assume priv will always be destroyed after objectDestroyed calls
+ list->removeOne(*this);
+ }
+ };
+
+ class DataList : public QList<DataGuard>, public QmlList<QObject*>
+ {
+ public:
+ virtual void append(QObject* v) { QList<DataGuard>::append(DataGuard(v, this)); }
+ virtual void insert(int i, QObject* v) { QList<DataGuard>::insert(i, DataGuard(v, this)); }
+ virtual void clear() { QList<DataGuard>::clear(); }
+ virtual QObject* at(int i) const { return QList<DataGuard>::at(i); }
+ virtual void removeAt(int i) { QList<DataGuard>::removeAt(i); }
+ virtual int count() const { return QList<DataGuard>::count(); }
+ };
+ DataList dataList;
+};
+
+class QmlPackageAttached : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+public:
+ QmlPackageAttached(QObject *parent);
+ virtual ~QmlPackageAttached();
+
+ QString name() const;
+ void setName(const QString &n);
+
+ static QHash<QObject *, QmlPackageAttached *> attached;
+private:
+ QString _name;
+};
+
+QHash<QObject *, QmlPackageAttached *> QmlPackageAttached::attached;
+
+QmlPackageAttached::QmlPackageAttached(QObject *parent)
+: QObject(parent)
+{
+ attached.insert(parent, this);
+}
+
+QmlPackageAttached::~QmlPackageAttached()
+{
+ attached.remove(parent());
+}
+
+QString QmlPackageAttached::name() const
+{
+ return _name;
+}
+
+void QmlPackageAttached::setName(const QString &n)
+{
+ _name = n;
+}
+
+QmlPackage::QmlPackage(QObject *parent)
+ : QObject(*(new QmlPackagePrivate), parent)
+{
+}
+
+QmlPackage::~QmlPackage()
+{
+ Q_D(QmlPackage);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ obj->setParent(this);
+ }
+}
+
+QmlList<QObject *> *QmlPackage::data()
+{
+ Q_D(QmlPackage);
+ return &d->dataList;
+}
+
+bool QmlPackage::hasPart(const QString &name)
+{
+ Q_D(QmlPackage);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QmlPackageAttached *a = QmlPackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return true;
+ }
+ return false;
+}
+
+QObject *QmlPackage::part(const QString &name)
+{
+ Q_D(QmlPackage);
+ if (name.isEmpty() && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QmlPackageAttached *a = QmlPackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return obj;
+ }
+
+ if (name == QLatin1String("default") && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ return 0;
+}
+
+QmlPackageAttached *QmlPackage::qmlAttachedProperties(QObject *o)
+{
+ return new QmlPackageAttached(o);
+}
+
+QML_DEFINE_TYPE(Qt,4,6,Package,QmlPackage)
+
+QT_END_NAMESPACE
+
+#include <qmlpackage.moc>
diff --git a/src/declarative/util/qmlpackage_p.h b/src/declarative/util/qmlpackage_p.h
new file mode 100644
index 0000000..ff42aad
--- /dev/null
+++ b/src/declarative/util/qmlpackage_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPACKAGE_H
+#define QMLPACKAGE_H
+
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+/*****************************************************************************
+ *****************************************************************************
+ XXX Experimental
+ *****************************************************************************
+*****************************************************************************/
+
+class QmlPackagePrivate;
+class QmlPackageAttached;
+class QmlPackage : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPackage)
+
+ Q_CLASSINFO("DefaultProperty", "data")
+ Q_PROPERTY(QmlList<QObject *> *data READ data SCRIPTABLE false)
+
+public:
+ QmlPackage(QObject *parent=0);
+ virtual ~QmlPackage();
+
+ QmlList<QObject *> *data();
+
+ QObject *part(const QString & = QString());
+ bool hasPart(const QString &);
+
+ static QmlPackageAttached *qmlAttachedProperties(QObject *);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlPackage)
+QML_DECLARE_TYPEINFO(QmlPackage, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QMLPACKAGE_H
diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp
new file mode 100644
index 0000000..c03b5df
--- /dev/null
+++ b/src/declarative/util/qmlpixmapcache.cpp
@@ -0,0 +1,605 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpixmapcache_p.h"
+#include "qmlnetworkaccessmanagerfactory.h"
+
+#include "qfxperf_p_p.h"
+
+#include <qmlengine.h>
+#include <private/qmlglobal_p.h>
+
+#include <QCoreApplication>
+#include <QImageReader>
+#include <QHash>
+#include <QNetworkReply>
+#include <QPixmapCache>
+#include <QFile>
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QtCore/qdebug.h>
+#include <private/qobject_p.h>
+#include <QSslError>
+
+#ifdef Q_OS_LINUX
+#include <pthread.h>
+#include <linux/sched.h>
+#endif
+
+// Maximum number of simultaneous image requests to send.
+static const int maxImageRequestCount = 8;
+
+QT_BEGIN_NAMESPACE
+
+#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0))
+inline uint qHash(const QUrl &uri)
+{
+ return qHash(uri.toEncoded(QUrl::FormattingOption(0x100)));
+}
+#endif
+
+class QmlImageReaderEvent : public QEvent
+{
+public:
+ enum ReadError { NoError, Loading, Decoding };
+
+ QmlImageReaderEvent(QmlImageReaderEvent::ReadError err, const QString &errStr, QImage &img)
+ : QEvent(QEvent::User), error(err), errorString(errStr), image(img) {}
+
+ ReadError error;
+ QString errorString;
+ QImage image;
+};
+
+class QmlImageRequestHandler;
+class QmlImageReader : public QThread
+{
+ Q_OBJECT
+public:
+ QmlImageReader(QmlEngine *eng);
+ ~QmlImageReader();
+
+ QmlPixmapReply *getImage(const QUrl &url);
+ void cancel(QmlPixmapReply *rep);
+
+ static QmlImageReader *instance(QmlEngine *engine);
+
+protected:
+ void run();
+
+private:
+ QList<QmlPixmapReply*> jobs;
+ QList<QmlPixmapReply*> cancelled;
+ QmlEngine *engine;
+ QmlImageRequestHandler *handler;
+ QMutex mutex;
+
+ static QHash<QmlEngine *,QmlImageReader*> readers;
+ static QMutex readerMutex;
+ friend class QmlImageRequestHandler;
+};
+
+QHash<QmlEngine *,QmlImageReader*> QmlImageReader::readers;
+QMutex QmlImageReader::readerMutex;
+
+
+class QmlImageRequestHandler : public QObject
+{
+ Q_OBJECT
+public:
+ QmlImageRequestHandler(QmlImageReader *read, QmlEngine *eng)
+ : QObject(), accessManager(0), engine(eng), reader(read)
+ {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+
+ QmlPixmapReply *getImage(const QUrl &url);
+ void cancel(QmlPixmapReply *reply);
+
+protected:
+ bool event(QEvent *event);
+
+private slots:
+ void networkRequestDone();
+
+private:
+ QNetworkAccessManager *networkAccessManager() {
+ if (!accessManager) {
+ if (engine && engine->networkAccessManagerFactory()) {
+ accessManager = engine->networkAccessManagerFactory()->create(this);
+ } else {
+ accessManager = new QNetworkAccessManager(this);
+ }
+ }
+ return accessManager;
+ }
+
+ QHash<QNetworkReply*,QmlPixmapReply*> replies;
+ QNetworkAccessManager *accessManager;
+ QmlEngine *engine;
+ QmlImageReader *reader;
+};
+
+//===========================================================================
+
+bool QmlImageRequestHandler::event(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+ static int replyDownloadProgress = -1;
+ static int replyFinished = -1;
+ static int downloadProgress = -1;
+ static int thisNetworkRequestDone = -1;
+
+ if (replyDownloadProgress == -1) {
+ replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()");
+ downloadProgress = QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ thisNetworkRequestDone = QmlImageRequestHandler::staticMetaObject.indexOfSlot("networkRequestDone()");
+ }
+
+ while (1) {
+ reader->mutex.lock();
+
+ if (reader->cancelled.count()) {
+ for (int i = 0; i < reader->cancelled.count(); ++i) {
+ QmlPixmapReply *job = reader->cancelled.at(i);
+ QNetworkReply *reply = replies.key(job, 0);
+ if (reply && reply->isRunning()) {
+ replies.remove(reply);
+ reply->close();
+ job->release(true);
+ }
+ }
+ reader->cancelled.clear();
+ }
+
+ if (!reader->jobs.count() || replies.count() > maxImageRequestCount) {
+ reader->mutex.unlock();
+ break;
+ }
+
+ QmlPixmapReply *runningJob = reader->jobs.takeFirst();
+ runningJob->addRef();
+ runningJob->setLoading();
+ QUrl url = runningJob->url();
+ reader->mutex.unlock();
+
+ // fetch
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ QNetworkReply *reply = networkAccessManager()->get(req);
+
+ QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
+ QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone);
+
+ replies.insert(reply, runningJob);
+ }
+ return true;
+ }
+
+ return QObject::event(event);
+}
+
+void QmlImageRequestHandler::networkRequestDone()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+ QmlPixmapReply *job = replies.take(reply);
+ if (job) {
+ QImage image;
+ QmlImageReaderEvent::ReadError error;
+ QString errorString;
+ if (reply->error()) {
+ error = QmlImageReaderEvent::Loading;
+ errorString = reply->errorString();
+ } else {
+ QImageReader imgio(reply);
+ if (imgio.read(&image)) {
+ error = QmlImageReaderEvent::NoError;
+ } else {
+ errorString = QLatin1String("Error decoding: ") + reply->url().toString()
+ + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\"");
+ error = QmlImageReaderEvent::Decoding;
+ }
+ }
+ // send completion event to the QmlPixmapReply
+ QCoreApplication::postEvent(job, new QmlImageReaderEvent(error, errorString, image));
+ }
+ // kick off event loop again if we have dropped below max request count
+ if (replies.count() == maxImageRequestCount)
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ reply->deleteLater();
+}
+
+//===========================================================================
+
+QmlImageReader::QmlImageReader(QmlEngine *eng)
+ : QThread(eng), engine(eng), handler(0)
+{
+ start(QThread::LowPriority);
+}
+
+QmlImageReader::~QmlImageReader()
+{
+ quit();
+ wait();
+ readerMutex.lock();
+ readers.remove(engine);
+ readerMutex.unlock();
+ delete handler;
+}
+
+QmlImageReader *QmlImageReader::instance(QmlEngine *engine)
+{
+ readerMutex.lock();
+ QmlImageReader *reader = readers.value(engine);
+ if (!reader) {
+ reader = new QmlImageReader(engine);
+ readers.insert(engine, reader);
+ }
+ readerMutex.unlock();
+
+ return reader;
+}
+
+QmlPixmapReply *QmlImageReader::getImage(const QUrl &url)
+{
+ mutex.lock();
+ QmlPixmapReply *reply = new QmlPixmapReply(this, url);
+ jobs.append(reply);
+ if (jobs.count() == 1 && handler)
+ QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ mutex.unlock();
+ return reply;
+}
+
+void QmlImageReader::cancel(QmlPixmapReply *reply)
+{
+ mutex.lock();
+ if (reply->isLoading()) {
+ // Already requested. Add to cancel list to be cancelled in reader thread.
+ cancelled.append(reply);
+ if (cancelled.count() == 1 && handler)
+ QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ } else {
+ // Not yet processed - just remove from waiting list
+ QList<QmlPixmapReply*>::iterator it = jobs.begin();
+ while (it != jobs.end()) {
+ QmlPixmapReply *job = *it;
+ if (job == reply) {
+ jobs.erase(it);
+ break;
+ }
+ ++it;
+ }
+ }
+ mutex.unlock();
+}
+
+void QmlImageReader::run()
+{
+#if defined(Q_OS_LINUX) && defined(SCHED_IDLE)
+ struct sched_param param;
+ int policy;
+
+ pthread_getschedparam(pthread_self(), &policy, &param);
+ pthread_setschedparam(pthread_self(), SCHED_IDLE, &param);
+#endif
+
+ handler = new QmlImageRequestHandler(this, engine);
+
+ exec();
+}
+
+//===========================================================================
+
+static bool readImage(QIODevice *dev, QPixmap *pixmap, QString &errorString)
+{
+ QImageReader imgio(dev);
+
+//#define QT_TEST_SCALED_SIZE
+#ifdef QT_TEST_SCALED_SIZE
+ /*
+ Some mechanism is needed for loading images at a limited size, especially
+ for remote images. Loading only thumbnails of remote progressive JPEG
+ images can be efficient. (Qt jpeg handler does not do so currently)
+ */
+
+ QSize limit(60,60);
+ QSize sz = imgio.size();
+ if (sz.width() > limit.width() || sz.height() > limit.height()) {
+ sz.scale(limit,Qt::KeepAspectRatio);
+ imgio.setScaledSize(sz);
+ }
+#endif
+
+ QImage img;
+ if (imgio.read(&img)) {
+#ifdef QT_TEST_SCALED_SIZE
+ if (!sz.isValid())
+ img = img.scaled(limit,Qt::KeepAspectRatio);
+#endif
+ *pixmap = QPixmap::fromImage(img);
+ return true;
+ } else {
+ errorString = imgio.errorString();
+ return false;
+ }
+}
+
+/*!
+ \internal
+ \class QmlPixmapCache
+ \brief Enacapsultes a pixmap for QmlGraphics items.
+
+ This class is NOT reentrant.
+ */
+
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+typedef QHash<QUrl, QmlPixmapReply *> QmlPixmapReplyHash;
+Q_GLOBAL_STATIC(QmlPixmapReplyHash, qmlActivePixmapReplies);
+
+class QmlPixmapReplyPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPixmapReply)
+
+public:
+ QmlPixmapReplyPrivate(QmlImageReader *r, const QUrl &u)
+ : QObjectPrivate(), refCount(1), url(u), status(QmlPixmapReply::Loading), loading(false), reader(r) {
+ }
+
+ int refCount;
+ QUrl url;
+ QPixmap pixmap; // ensure reference to pixmap so QPixmapCache does not discard
+ QmlPixmapReply::Status status;
+ bool loading;
+ QmlImageReader *reader;
+};
+
+
+QmlPixmapReply::QmlPixmapReply(QmlImageReader *reader, const QUrl &url)
+ : QObject(*new QmlPixmapReplyPrivate(reader, url), 0)
+{
+}
+
+QmlPixmapReply::~QmlPixmapReply()
+{
+}
+
+const QUrl &QmlPixmapReply::url() const
+{
+ Q_D(const QmlPixmapReply);
+ return d->url;
+}
+
+bool QmlPixmapReply::event(QEvent *event)
+{
+ Q_D(QmlPixmapReply);
+ if (event->type() == QEvent::User) {
+ d->loading = false;
+ if (!release(true)) {
+ QmlImageReaderEvent *de = static_cast<QmlImageReaderEvent*>(event);
+ d->status = (de->error == QmlImageReaderEvent::NoError) ? Ready : Error;
+ if (d->status == Ready)
+ d->pixmap = QPixmap::fromImage(de->image);
+ else
+ qWarning() << de->errorString;
+ QByteArray key = d->url.toEncoded(QUrl::FormattingOption(0x100));
+ QString strKey = QString::fromLatin1(key.constData(), key.count());
+ QPixmapCache::insert(strKey, d->pixmap); // note: may fail (returns false)
+ emit finished();
+ }
+ return true;
+ }
+
+ return QObject::event(event);
+}
+
+QmlPixmapReply::Status QmlPixmapReply::status() const
+{
+ Q_D(const QmlPixmapReply);
+ return d->status;
+}
+
+bool QmlPixmapReply::isLoading() const
+{
+ Q_D(const QmlPixmapReply);
+ return d->loading;
+}
+
+void QmlPixmapReply::setLoading()
+{
+ Q_D(QmlPixmapReply);
+ d->loading = true;
+}
+
+void QmlPixmapReply::addRef()
+{
+ Q_D(QmlPixmapReply);
+ ++d->refCount;
+}
+
+bool QmlPixmapReply::release(bool defer)
+{
+ Q_D(QmlPixmapReply);
+ Q_ASSERT(d->refCount > 0);
+ --d->refCount;
+ if (d->refCount == 0) {
+ qmlActivePixmapReplies()->remove(d->url);
+ if (d->status == Loading && !d->loading)
+ d->reader->cancel(this);
+ if (defer)
+ deleteLater();
+ else
+ delete this;
+ return true;
+ } else if (d->refCount == 1 && d->loading) {
+ // The only reference left is the reader thread.
+ qmlActivePixmapReplies()->remove(d->url);
+ d->reader->cancel(this);
+ }
+
+ return false;
+}
+
+/*!
+ Finds the cached pixmap corresponding to \a url.
+ If the image is a network resource and has not yet
+ been retrieved and cached, request() must be called.
+
+ Returns Ready, or Error if the image has been retrieved,
+ otherwise the current retrieval status.
+*/
+QmlPixmapReply::Status QmlPixmapCache::get(const QUrl& url, QPixmap *pixmap)
+{
+ QmlPixmapReply::Status status = QmlPixmapReply::Unrequested;
+
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ status = QmlPixmapReply::Ready;
+ if (!QPixmapCache::find(lf,pixmap)) {
+ QFile f(lf);
+ if (f.open(QIODevice::ReadOnly)) {
+ QString errorString;
+ if (!readImage(&f, pixmap, errorString)) {
+ errorString = QLatin1String("Error decoding: ") + url.toString()
+ + QLatin1String(" \"") + errorString + QLatin1String("\"");
+ qWarning() << errorString;
+ *pixmap = QPixmap();
+ status = QmlPixmapReply::Error;
+ }
+ } else {
+ qWarning() << "Cannot open" << url;
+ *pixmap = QPixmap();
+ status = QmlPixmapReply::Error;
+ }
+ if (status == QmlPixmapReply::Ready)
+ QPixmapCache::insert(lf, *pixmap);
+ }
+ return status;
+ }
+#endif
+
+ QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100));
+ QString strKey = QString::fromLatin1(key.constData(), key.count());
+ QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
+ if (iter != qmlActivePixmapReplies()->end() && (*iter)->status() == QmlPixmapReply::Ready) {
+ // Must check this, since QPixmapCache::insert may have failed.
+ *pixmap = (*iter)->d_func()->pixmap;
+ status = (*iter)->status();
+ (*iter)->release();
+ } else if (QPixmapCache::find(strKey, pixmap)) {
+ if (iter != qmlActivePixmapReplies()->end()) {
+ status = (*iter)->status();
+ (*iter)->release();
+ } else {
+ status = pixmap->isNull() ? QmlPixmapReply::Error : QmlPixmapReply::Ready;
+ }
+ } else if (iter != qmlActivePixmapReplies()->end()) {
+ status = QmlPixmapReply::Loading;
+ }
+
+ return status;
+}
+
+/*!
+ Starts a network request to load \a url.
+
+ Returns a QmlPixmapReply. Caller should connect to QmlPixmapReply::finished()
+ and call get() when the image is available.
+
+ The returned QmlPixmapReply will be deleted when all request() calls are
+ matched by a corresponding get() call.
+*/
+QmlPixmapReply *QmlPixmapCache::request(QmlEngine *engine, const QUrl &url)
+{
+ QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
+ if (iter == qmlActivePixmapReplies()->end()) {
+ QmlImageReader *reader = QmlImageReader::instance(engine);
+ QmlPixmapReply *item = reader->getImage(url);
+ iter = qmlActivePixmapReplies()->insert(url, item);
+ } else {
+ (*iter)->addRef();
+ }
+
+ return (*iter);
+}
+
+/*!
+ Cancels a previous call to request().
+
+ May also cancel loading (eg. if no other pending request).
+
+ Any connections from the QmlPixmapReply returned by request() to \a obj will be
+ disconnected.
+*/
+void QmlPixmapCache::cancel(const QUrl& url, QObject *obj)
+{
+ QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
+ if (iter == qmlActivePixmapReplies()->end())
+ return;
+
+ QmlPixmapReply *reply = *iter;
+ if (obj)
+ QObject::disconnect(reply, 0, obj, 0);
+ reply->release();
+}
+
+/*!
+ This function is mainly for test verification. It returns the number of
+ requests that are still unfinished.
+*/
+int QmlPixmapCache::pendingRequests()
+{
+ return qmlActivePixmapReplies()->count();
+}
+
+#include <qmlpixmapcache.moc>
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlpixmapcache_p.h b/src/declarative/util/qmlpixmapcache_p.h
new file mode 100644
index 0000000..462faf6
--- /dev/null
+++ b/src/declarative/util/qmlpixmapcache_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPIXMAPCACHE_H
+#define QMLPIXMAPCACHE_H
+
+#include <QtCore/QString>
+#include <QtGui/QPixmap>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlEngine;
+class QNetworkReply;
+class QmlImageReader;
+
+class QmlPixmapReplyPrivate;
+class Q_DECLARATIVE_EXPORT QmlPixmapReply : public QObject
+{
+ Q_OBJECT
+public:
+ ~QmlPixmapReply();
+
+ enum Status { Ready, Error, Unrequested, Loading };
+ Status status() const;
+
+ const QUrl &url() const;
+
+Q_SIGNALS:
+ void finished();
+ void downloadProgress(qint64, qint64);
+
+protected:
+ bool event(QEvent *event);
+
+private:
+ void addRef();
+ bool release(bool defer=false);
+ bool isLoading() const;
+ void setLoading();
+
+private:
+ QmlPixmapReply(QmlImageReader *reader, const QUrl &url);
+ Q_DISABLE_COPY(QmlPixmapReply)
+ Q_DECLARE_PRIVATE(QmlPixmapReply)
+ friend class QmlImageRequestHandler;
+ friend class QmlImageReader;
+ friend class QmlPixmapCache;
+};
+
+class Q_DECLARATIVE_EXPORT QmlPixmapCache
+{
+public:
+ static QmlPixmapReply::Status get(const QUrl& url, QPixmap *pixmap);
+ static QmlPixmapReply *request(QmlEngine *, const QUrl& url);
+ static void cancel(const QUrl& url, QObject *obj);
+ static int pendingRequests();
+};
+
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPIXMAPCACHE_H
diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp
new file mode 100644
index 0000000..68fc5cc
--- /dev/null
+++ b/src/declarative/util/qmlpropertychanges.cpp
@@ -0,0 +1,468 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertychanges_p.h"
+
+#include "qmlopenmetaobject_p.h"
+
+#include <qmlinfo.h>
+#include <qmlcustomparser_p.h>
+#include <qmlparser_p.h>
+#include <qmlexpression.h>
+#include <qmlbinding.h>
+#include <qmlcontext.h>
+#include <qmlguard_p.h>
+
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass PropertyChanges QmlPropertyChanges
+ \brief The PropertyChanges element describes new property values for a state.
+
+ PropertyChanges provides a state change that modifies the properties of an item.
+
+ Here is a property change that modifies the text and color of a Text element
+ when it is clicked:
+
+ \qml
+ Text {
+ id: myText
+ width: 100; height: 100
+ text: "Hello"
+ color: "blue"
+
+ states: State {
+ name: "myState"
+
+ PropertyChanges {
+ target: myText
+ text: "Goodbye"
+ color: "red"
+ }
+ }
+
+ MouseRegion { anchors.fill: parent; onClicked: myText.state = 'myState' }
+ }
+ \endqml
+
+ State-specific script for signal handlers can also be specified:
+
+ \qml
+ PropertyChanges {
+ target: myMouseRegion
+ onClicked: doSomethingDifferent()
+ }
+ \endqml
+
+ Changes to an Item's parent or anchors should be done using the associated change elements
+ (ParentChange and AnchorChanges, respectively) rather than PropertyChanges.
+
+ \sa {qmlstate}{States}
+*/
+
+/*!
+ \internal
+ \class QmlPropertyChanges
+ \brief The QmlPropertyChanges class describes new property values for a state.
+*/
+
+/*!
+ \qmlproperty Object PropertyChanges::target
+ This property holds the object which contains the properties to be changed.
+*/
+
+class QmlReplaceSignalHandler : public QmlActionEvent
+{
+public:
+ QmlReplaceSignalHandler() : expression(0), reverseExpression(0),
+ rewindExpression(0), ownedExpression(0) {}
+ ~QmlReplaceSignalHandler() {
+ delete ownedExpression;
+ }
+
+ virtual QString typeName() const { return QLatin1String("ReplaceSignalHandler"); }
+
+ QmlMetaProperty property;
+ QmlExpression *expression;
+ QmlExpression *reverseExpression;
+ QmlExpression *rewindExpression;
+ QmlGuard<QmlExpression> ownedExpression;
+
+ virtual void execute() {
+ ownedExpression = property.setSignalExpression(expression);
+ }
+
+ virtual bool isReversable() { return true; }
+ virtual void reverse() {
+ ownedExpression = property.setSignalExpression(reverseExpression);
+ }
+
+ virtual void saveOriginals() {
+ saveCurrentValues();
+ reverseExpression = rewindExpression;
+ }
+
+ virtual void rewind() {
+ ownedExpression = property.setSignalExpression(rewindExpression);
+ }
+ virtual void saveCurrentValues() { rewindExpression = property.signalExpression(); }
+
+ virtual bool override(QmlActionEvent*other) {
+ if (other == this)
+ return true;
+ if (other->typeName() != typeName())
+ return false;
+ if (static_cast<QmlReplaceSignalHandler*>(other)->property == property)
+ return true;
+ return false;
+ }
+};
+
+
+class QmlPropertyChangesPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPropertyChanges)
+public:
+ QmlPropertyChangesPrivate() : object(0), decoded(true), restore(true),
+ isExplicit(false) {}
+
+ QObject *object;
+ QByteArray data;
+
+ bool decoded : 1;
+ bool restore : 1;
+ bool isExplicit : 1;
+
+ void decode();
+
+ QList<QPair<QByteArray, QVariant> > properties;
+ QList<QPair<QByteArray, QmlExpression *> > expressions;
+ QList<QmlReplaceSignalHandler*> signalReplacements;
+
+ QmlMetaProperty property(const QByteArray &);
+};
+
+class QmlPropertyChangesParser : public QmlCustomParser
+{
+public:
+ void compileList(QList<QPair<QByteArray, QVariant> > &list, const QByteArray &pre, const QmlCustomParserProperty &prop);
+
+ virtual QByteArray compile(const QList<QmlCustomParserProperty> &);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+void
+QmlPropertyChangesParser::compileList(QList<QPair<QByteArray, QVariant> > &list,
+ const QByteArray &pre,
+ const QmlCustomParserProperty &prop)
+{
+ QByteArray propName = pre + prop.name();
+
+ QList<QVariant> values = prop.assignedValues();
+ for (int ii = 0; ii < values.count(); ++ii) {
+ const QVariant &value = values.at(ii);
+
+ if (value.userType() == qMetaTypeId<QmlCustomParserNode>()) {
+ continue;
+ } else if(value.userType() == qMetaTypeId<QmlCustomParserProperty>()) {
+
+ QmlCustomParserProperty prop =
+ qvariant_cast<QmlCustomParserProperty>(value);
+ QByteArray pre = propName + '.';
+ compileList(list, pre, prop);
+
+ } else {
+ list << qMakePair(propName, value);
+ }
+ }
+}
+
+QByteArray
+QmlPropertyChangesParser::compile(const QList<QmlCustomParserProperty> &props)
+{
+ QList<QPair<QByteArray, QVariant> > data;
+ for(int ii = 0; ii < props.count(); ++ii)
+ compileList(data, QByteArray(), props.at(ii));
+
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ ds << data.count();
+ for(int ii = 0; ii < data.count(); ++ii) {
+ QmlParser::Variant v = qvariant_cast<QmlParser::Variant>(data.at(ii).second);
+ QVariant var;
+ bool isScript = v.isScript();
+ switch(v.type()) {
+ case QmlParser::Variant::Boolean:
+ var = QVariant(v.asBoolean());
+ break;
+ case QmlParser::Variant::Number:
+ var = QVariant(v.asNumber());
+ break;
+ case QmlParser::Variant::String:
+ var = QVariant(v.asString());
+ break;
+ case QmlParser::Variant::Invalid:
+ case QmlParser::Variant::Script:
+ var = QVariant(v.asScript());
+ break;
+ }
+
+ ds << data.at(ii).first << isScript << var;
+ }
+
+ return rv;
+}
+
+void QmlPropertyChangesPrivate::decode()
+{
+ Q_Q(QmlPropertyChanges);
+ if (decoded)
+ return;
+
+ QDataStream ds(&data, QIODevice::ReadOnly);
+
+ int count;
+ ds >> count;
+ for (int ii = 0; ii < count; ++ii) {
+ QByteArray name;
+ bool isScript;
+ QVariant data;
+ ds >> name;
+ ds >> isScript;
+ ds >> data;
+
+ QmlMetaProperty prop = property(name); //### better way to check for signal property?
+ if (prop.type() & QmlMetaProperty::SignalProperty) {
+ QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object);
+ expression->setTrackChange(false);
+ QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler;
+ handler->property = prop;
+ handler->expression = expression;
+ signalReplacements << handler;
+ } else if (isScript) {
+ QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object);
+ expression->setTrackChange(false);
+ expressions << qMakePair(name, expression);
+ } else {
+ properties << qMakePair(name, data);
+ }
+ }
+
+ decoded = true;
+ data.clear();
+}
+
+void QmlPropertyChangesParser::setCustomData(QObject *object,
+ const QByteArray &data)
+{
+ QmlPropertyChangesPrivate *p =
+ static_cast<QmlPropertyChangesPrivate *>(QObjectPrivate::get(object));
+ p->data = data;
+ p->decoded = false;
+}
+
+QmlPropertyChanges::QmlPropertyChanges()
+: QmlStateOperation(*(new QmlPropertyChangesPrivate))
+{
+}
+
+QmlPropertyChanges::~QmlPropertyChanges()
+{
+ Q_D(QmlPropertyChanges);
+ for(int ii = 0; ii < d->expressions.count(); ++ii)
+ delete d->expressions.at(ii).second;
+ for(int ii = 0; ii < d->signalReplacements.count(); ++ii)
+ delete d->signalReplacements.at(ii);
+}
+
+QObject *QmlPropertyChanges::object() const
+{
+ Q_D(const QmlPropertyChanges);
+ return d->object;
+}
+
+void QmlPropertyChanges::setObject(QObject *o)
+{
+ Q_D(QmlPropertyChanges);
+ d->object = o;
+}
+
+/*!
+ \qmlproperty bool PropertyChanges::restoreEntryValues
+
+ Whether or not the previous values should be restored when
+ leaving the state. By default, restoreEntryValues is true.
+
+ By setting restoreEntryValues to false, you can create a temporary state
+ that has permanent effects on property values.
+*/
+bool QmlPropertyChanges::restoreEntryValues() const
+{
+ Q_D(const QmlPropertyChanges);
+ return d->restore;
+}
+
+void QmlPropertyChanges::setRestoreEntryValues(bool v)
+{
+ Q_D(QmlPropertyChanges);
+ d->restore = v;
+}
+
+QmlMetaProperty
+QmlPropertyChangesPrivate::property(const QByteArray &property)
+{
+ Q_Q(QmlPropertyChanges);
+ QmlMetaProperty prop = QmlMetaProperty::createProperty(object, QString::fromUtf8(property));
+ if (!prop.isValid()) {
+ qmlInfo(q) << QmlPropertyChanges::tr("Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(property));
+ return QmlMetaProperty();
+ } else if (!(prop.type() & QmlMetaProperty::SignalProperty) && !prop.isWritable()) {
+ qmlInfo(q) << QmlPropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(QString::fromUtf8(property));
+ return QmlMetaProperty();
+ }
+ return prop;
+}
+
+QmlPropertyChanges::ActionList QmlPropertyChanges::actions()
+{
+ Q_D(QmlPropertyChanges);
+
+ d->decode();
+
+ ActionList list;
+
+ for (int ii = 0; ii < d->properties.count(); ++ii) {
+
+ QByteArray property = d->properties.at(ii).first;
+
+ QmlAction a(d->object, QString::fromLatin1(property),
+ d->properties.at(ii).second);
+
+ if (a.property.isValid()) {
+ a.restore = restoreEntryValues();
+
+ if (a.property.propertyType() == QVariant::Url &&
+ (a.toValue.userType() == QVariant::String || a.toValue.userType() == QVariant::ByteArray) && !a.toValue.isNull())
+ a.toValue.setValue(qmlContext(this)->resolvedUrl(QUrl(a.toValue.toString())));
+
+ list << a;
+ }
+ }
+
+ for (int ii = 0; ii < d->signalReplacements.count(); ++ii) {
+
+ QmlReplaceSignalHandler *handler = d->signalReplacements.at(ii);
+
+ if (handler->property.isValid()) {
+ QmlAction a;
+ a.event = handler;
+ list << a;
+ }
+ }
+
+ for (int ii = 0; ii < d->expressions.count(); ++ii) {
+
+ QByteArray property = d->expressions.at(ii).first;
+ QmlMetaProperty prop = d->property(property);
+
+ if (prop.isValid()) {
+ QmlAction a;
+ a.restore = restoreEntryValues();
+ a.property = prop;
+ a.fromValue = a.property.read();
+ a.specifiedObject = d->object;
+ a.specifiedProperty = QString::fromLatin1(property);
+
+ if (d->isExplicit) {
+ a.toValue = d->expressions.at(ii).second->value();
+ } else {
+ QmlBinding *newBinding = new QmlBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this));
+ newBinding->setTarget(prop);
+ a.toBinding = newBinding;
+ a.deletableToBinding = true;
+ }
+
+ list << a;
+ }
+ }
+
+ return list;
+}
+
+/*!
+ \qmlproperty bool PropertyChanges::explicit
+
+ If explicit is set to true, any potential bindings will be interpreted as
+ once-off assignments that occur when the state is entered.
+
+ In the following example, the addition of explicit prevents myItem.width from
+ being bound to parent.width. Instead, it is assigned the value of parent.width
+ at the time of the state change.
+ \qml
+ PropertyChanges {
+ target: myItem
+ explicit: true
+ width: parent.width
+ }
+ \endqml
+
+ By default, explicit is false.
+*/
+bool QmlPropertyChanges::isExplicit() const
+{
+ Q_D(const QmlPropertyChanges);
+ return d->isExplicit;
+}
+
+void QmlPropertyChanges::setIsExplicit(bool e)
+{
+ Q_D(QmlPropertyChanges);
+ d->isExplicit = e;
+}
+
+QML_DEFINE_CUSTOM_TYPE(Qt, 4,6, PropertyChanges, QmlPropertyChanges, QmlPropertyChangesParser)
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlpropertychanges_p.h b/src/declarative/util/qmlpropertychanges_p.h
new file mode 100644
index 0000000..461730d
--- /dev/null
+++ b/src/declarative/util/qmlpropertychanges_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYCHANGES_H
+#define QMLPROPERTYCHANGES_H
+
+#include "qmlstateoperations_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlPropertyChangesPrivate;
+class Q_DECLARATIVE_EXPORT QmlPropertyChanges : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPropertyChanges)
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
+ Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
+public:
+ QmlPropertyChanges();
+ ~QmlPropertyChanges();
+
+ QObject *object() const;
+ void setObject(QObject *);
+
+ bool restoreEntryValues() const;
+ void setRestoreEntryValues(bool);
+
+ bool isExplicit() const;
+ void setIsExplicit(bool);
+
+ virtual ActionList actions();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlPropertyChanges)
+
+QT_END_HEADER
+
+#endif // QMLPROPERTYCHANGES_H
diff --git a/src/declarative/util/qmlpropertymap.cpp b/src/declarative/util/qmlpropertymap.cpp
new file mode 100644
index 0000000..226f82e
--- /dev/null
+++ b/src/declarative/util/qmlpropertymap.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertymap.h"
+
+#include "qmlopenmetaobject_p.h"
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+//QmlPropertyMapMetaObject lets us listen for changes coming from QML
+//so we can emit the changed signal.
+class QmlPropertyMapMetaObject : public QmlOpenMetaObject
+{
+public:
+ QmlPropertyMapMetaObject(QmlPropertyMap *obj, QmlPropertyMapPrivate *objPriv);
+
+protected:
+ virtual void propertyWrite(int index);
+
+private:
+ QmlPropertyMap *map;
+ QmlPropertyMapPrivate *priv;
+};
+
+class QmlPropertyMapPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPropertyMap)
+public:
+ QmlPropertyMapMetaObject *mo;
+ QStringList keys;
+ void emitChanged(const QString &key);
+};
+
+void QmlPropertyMapPrivate::emitChanged(const QString &key)
+{
+ Q_Q(QmlPropertyMap);
+ emit q->valueChanged(key);
+}
+
+QmlPropertyMapMetaObject::QmlPropertyMapMetaObject(QmlPropertyMap *obj, QmlPropertyMapPrivate *objPriv) : QmlOpenMetaObject(obj)
+{
+ map = obj;
+ priv = objPriv;
+}
+
+void QmlPropertyMapMetaObject::propertyWrite(int index)
+{
+ priv->emitChanged(QString::fromUtf8(name(index)));
+}
+
+/*!
+ \class QmlPropertyMap
+ \brief The QmlPropertyMap class allows you to set key-value pairs that can be used in bindings.
+
+ QmlPropertyMap provides a convenient way to expose domain data to the UI layer.
+ The following example shows how you might declare data in C++ and then
+ access it in QML.
+
+ Setup in C++:
+ \code
+ //create our data
+ QmlPropertyMap ownerData;
+ ownerData.insert("name", QVariant(QString("John Smith")));
+ ownerData.insert("phone", QVariant(QString("555-5555")));
+
+ //expose it to the UI layer
+ QmlContext *ctxt = view->bindContext();
+ ctxt->setProperty("owner", &data);
+ \endcode
+
+ Then, in QML:
+ \code
+ Text { text: owner.name }
+ Text { text: owner.phone }
+ \endcode
+
+ The binding is dynamic - whenever a key's value is updated, anything bound to that
+ key will be updated as well.
+
+ To detect value changes made in the UI layer you can connect to the valueChanged() signal.
+ However, note that valueChanged() is \bold NOT emitted when changes are made by calling insert()
+ or clear() - it is only emitted when a value is updated from QML.
+
+ \note It is not possible to remove keys from the map; once a key has been added, you can only
+ modify or clear its associated value.
+*/
+
+/*!
+ Constructs a bindable map with parent object \a parent.
+*/
+QmlPropertyMap::QmlPropertyMap(QObject *parent)
+: QObject(*(new QmlPropertyMapPrivate), parent)
+{
+ Q_D(QmlPropertyMap);
+ d->mo = new QmlPropertyMapMetaObject(this, d);
+}
+
+/*!
+ Destroys the bindable map.
+*/
+QmlPropertyMap::~QmlPropertyMap()
+{
+}
+
+/*!
+ Clears the value (if any) associated with \a key.
+*/
+void QmlPropertyMap::clear(const QString &key)
+{
+ Q_D(QmlPropertyMap);
+ d->mo->setValue(key.toUtf8(), QVariant());
+}
+
+/*!
+ Returns the value associated with \a key.
+
+ If no value has been set for this key (or if the value has been cleared),
+ an invalid QVariant is returned.
+*/
+QVariant QmlPropertyMap::value(const QString &key) const
+{
+ Q_D(const QmlPropertyMap);
+ return d->mo->value(key.toUtf8());
+}
+
+/*!
+ Sets the value associated with \a key to \a value.
+
+ If the key doesn't exist, it is automatically created.
+*/
+void QmlPropertyMap::insert(const QString &key, const QVariant &value)
+{
+ Q_D(QmlPropertyMap);
+ if (!d->keys.contains(key))
+ d->keys.append(key);
+ d->mo->setValue(key.toUtf8(), value);
+}
+
+/*!
+ Returns the list of keys.
+
+ Keys that have been cleared will still appear in this list, even though their
+ associated values are invalid QVariants.
+*/
+QStringList QmlPropertyMap::keys() const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys;
+}
+
+/*!
+ \overload
+
+ Same as size().
+*/
+int QmlPropertyMap::count() const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.count();
+}
+
+/*!
+ Returns the number of keys in the map.
+
+ \sa isEmpty(), count()
+*/
+int QmlPropertyMap::size() const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.size();
+}
+
+/*!
+ Returns true if the map contains no keys; otherwise returns
+ false.
+
+ \sa size()
+*/
+bool QmlPropertyMap::isEmpty() const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.isEmpty();
+}
+
+/*!
+ Returns true if the map contains \a key.
+
+ \sa size()
+*/
+bool QmlPropertyMap::contains(const QString &key) const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.contains(key);
+}
+
+/*!
+ Returns the value associated with the key \a key as a modifiable
+ reference.
+
+ If the map contains no item with key \a key, the function inserts
+ an invalid QVariant into the map with key \a key, and
+ returns a reference to it.
+
+ \sa insert(), value()
+*/
+QVariant &QmlPropertyMap::operator[](const QString &key)
+{
+ //### optimize
+ Q_D(QmlPropertyMap);
+ QByteArray utf8key = key.toUtf8();
+ if (!d->keys.contains(key)) {
+ d->keys.append(key);
+ d->mo->setValue(utf8key, QVariant()); //force creation -- needed below
+ }
+
+ return (*(d->mo))[utf8key];
+}
+
+/*!
+ \overload
+
+ Same as value().
+*/
+const QVariant QmlPropertyMap::operator[](const QString &key) const
+{
+ return value(key);
+}
+
+/*!
+ \fn void QmlPropertyMap::valueChanged(const QString &key)
+ This signal is emitted whenever one of the values in the map is changed. \a key
+ is the key corresponding to the value that was changed.
+
+ \note valueChanged() is \bold NOT emitted when changes are made by calling insert()
+ or clear() - it is only emitted when a value is updated from QML.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlpropertymap.h b/src/declarative/util/qmlpropertymap.h
new file mode 100644
index 0000000..bb397fe
--- /dev/null
+++ b/src/declarative/util/qmlpropertymap.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYMAP_H
+#define QMLPROPERTYMAP_H
+
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlPropertyMapPrivate;
+class Q_DECLARATIVE_EXPORT QmlPropertyMap : public QObject
+{
+ Q_OBJECT
+public:
+ QmlPropertyMap(QObject *parent = 0);
+ virtual ~QmlPropertyMap();
+
+ QVariant value(const QString &key) const;
+ void insert(const QString &key, const QVariant &value);
+ void clear(const QString &key);
+
+ Q_INVOKABLE QStringList keys() const;
+
+ int count() const;
+ int size() const;
+ bool isEmpty() const;
+ bool contains(const QString &key) const;
+
+ QVariant &operator[](const QString &key);
+ const QVariant operator[](const QString &key) const;
+
+Q_SIGNALS:
+ void valueChanged(const QString &key);
+
+private:
+ Q_DECLARE_PRIVATE(QmlPropertyMap)
+ Q_DISABLE_COPY(QmlPropertyMap)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qmlspringfollow.cpp b/src/declarative/util/qmlspringfollow.cpp
new file mode 100644
index 0000000..764d7f9
--- /dev/null
+++ b/src/declarative/util/qmlspringfollow.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlspringfollow_p.h"
+
+#include "qmlanimation_p_p.h"
+
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+#include <limits.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,SpringFollow,QmlSpringFollow)
+
+class QmlSpringFollowPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSpringFollow)
+public:
+ QmlSpringFollowPrivate()
+ : currentValue(0), sourceValue(0), maxVelocity(0), lastTime(0)
+ , mass(1.0), spring(0.), damping(0.), velocity(0), epsilon(0.01)
+ , modulus(0.0), useMass(false), haveModulus(false), enabled(true), mode(Track), clock(this) {}
+
+ QmlMetaProperty property;
+ qreal currentValue;
+ qreal sourceValue;
+ qreal maxVelocity;
+ qreal velocityms;
+ int lastTime;
+ qreal mass;
+ qreal spring;
+ qreal damping;
+ qreal velocity;
+ qreal epsilon;
+ qreal modulus;
+
+ bool useMass : 1;
+ bool haveModulus : 1;
+ bool enabled : 1;
+
+ enum Mode {
+ Track,
+ Velocity,
+ Spring
+ };
+ Mode mode;
+
+ void tick(int);
+ void updateMode();
+ void start();
+ void stop();
+
+ QTickAnimationProxy<QmlSpringFollowPrivate, &QmlSpringFollowPrivate::tick> clock;
+};
+
+void QmlSpringFollowPrivate::tick(int time)
+{
+ Q_Q(QmlSpringFollow);
+
+ int elapsed = time - lastTime;
+ if (!elapsed)
+ return;
+ qreal srcVal = sourceValue;
+ if (haveModulus) {
+ currentValue = fmod(currentValue, modulus);
+ srcVal = fmod(srcVal, modulus);
+ }
+ if (mode == Spring) {
+ if (elapsed < 16) // capped at 62fps.
+ return;
+ // Real men solve the spring DEs using RK4.
+ // We'll do something much simpler which gives a result that looks fine.
+ int count = elapsed / 16;
+ for (int i = 0; i < count; ++i) {
+ qreal diff = srcVal - currentValue;
+ if (haveModulus && qAbs(diff) > modulus / 2) {
+ if (diff < 0)
+ diff += modulus;
+ else
+ diff -= modulus;
+ }
+ if (useMass)
+ velocity = velocity + (spring * diff - damping * velocity) / mass;
+ else
+ velocity = velocity + spring * diff - damping * velocity;
+ if (maxVelocity > 0.) {
+ // limit velocity
+ if (velocity > maxVelocity)
+ velocity = maxVelocity;
+ else if (velocity < -maxVelocity)
+ velocity = -maxVelocity;
+ }
+ currentValue += velocity * 16.0 / 1000.0;
+ if (haveModulus) {
+ currentValue = fmod(currentValue, modulus);
+ if (currentValue < 0.0)
+ currentValue += modulus;
+ }
+ }
+ if (qAbs(velocity) < epsilon && qAbs(srcVal - currentValue) < epsilon) {
+ velocity = 0.0;
+ currentValue = srcVal;
+ clock.stop();
+ }
+ lastTime = time - (elapsed - count * 16);
+ } else {
+ qreal moveBy = elapsed * velocityms;
+ qreal diff = srcVal - currentValue;
+ if (haveModulus && qAbs(diff) > modulus / 2) {
+ if (diff < 0)
+ diff += modulus;
+ else
+ diff -= modulus;
+ }
+ if (diff > 0) {
+ currentValue += moveBy;
+ if (haveModulus)
+ currentValue = fmod(currentValue, modulus);
+ if (currentValue > sourceValue) {
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ } else {
+ currentValue -= moveBy;
+ if (haveModulus && currentValue < 0.0)
+ currentValue = fmod(currentValue, modulus) + modulus;
+ if (currentValue < sourceValue) {
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ }
+ lastTime = time;
+ }
+ property.write(currentValue);
+ emit q->valueChanged(currentValue);
+ if (clock.state() != QAbstractAnimation::Running)
+ emit q->syncChanged();
+}
+
+void QmlSpringFollowPrivate::updateMode()
+{
+ if (spring == 0. && maxVelocity == 0.)
+ mode = Track;
+ else if (spring > 0.)
+ mode = Spring;
+ else
+ mode = Velocity;
+}
+
+void QmlSpringFollowPrivate::start()
+{
+ if (!enabled)
+ return;
+
+ Q_Q(QmlSpringFollow);
+ if (mode == QmlSpringFollowPrivate::Track) {
+ currentValue = sourceValue;
+ property.write(currentValue);
+ } else if (sourceValue != currentValue && clock.state() != QAbstractAnimation::Running) {
+ lastTime = 0;
+ currentValue = property.read().toReal();
+ clock.start(); // infinity??
+ emit q->syncChanged();
+ }
+}
+
+void QmlSpringFollowPrivate::stop()
+{
+ clock.stop();
+}
+
+/*!
+ \qmlclass SpringFollow QmlSpringFollow
+ \brief The SpringFollow element allows a property to track a value.
+
+ In example below, \e rect2 will follow \e rect1 moving with a velocity of up to 200:
+ \code
+ Rectangle {
+ id: rect1
+ width: 20; height: 20
+ color: "#00ff00"
+ y: 200 //initial value
+ y: SequentialAnimation {
+ running: true
+ repeat: true
+ NumberAnimation {
+ to: 200
+ easing: "easeOutBounce(amplitude:100)"
+ duration: 2000
+ }
+ PauseAnimation { duration: 1000 }
+ }
+ }
+ Rectangle {
+ id: rect2
+ x: rect1.width
+ width: 20; height: 20
+ color: "#ff0000"
+ y: SpringFollow { source: rect1.y; velocity: 200 }
+ }
+ \endcode
+
+ \sa EaseFollow
+*/
+
+QmlSpringFollow::QmlSpringFollow(QObject *parent)
+: QObject(*(new QmlSpringFollowPrivate),parent)
+{
+}
+
+QmlSpringFollow::~QmlSpringFollow()
+{
+}
+
+void QmlSpringFollow::setTarget(const QmlMetaProperty &property)
+{
+ Q_D(QmlSpringFollow);
+ d->property = property;
+ d->currentValue = property.read().toReal();
+}
+
+qreal QmlSpringFollow::sourceValue() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->sourceValue;
+}
+
+/*!
+ \qmlproperty qreal SpringFollow::source
+ This property holds the source value which will be tracked.
+
+ Bind to a property in order to track its changes.
+*/
+
+void QmlSpringFollow::setSourceValue(qreal value)
+{
+ Q_D(QmlSpringFollow);
+ if (d->clock.state() == QAbstractAnimation::Running && d->sourceValue == value)
+ return;
+
+ d->sourceValue = value;
+ d->start();
+}
+
+/*!
+ \qmlproperty qreal SpringFollow::velocity
+ This property holds the maximum velocity allowed when tracking the source.
+*/
+
+qreal QmlSpringFollow::velocity() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->maxVelocity;
+}
+
+void QmlSpringFollow::setVelocity(qreal velocity)
+{
+ Q_D(QmlSpringFollow);
+ d->maxVelocity = velocity;
+ d->velocityms = velocity / 1000.0;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty qreal SpringFollow::spring
+ This property holds the spring constant
+
+ The spring constant describes how strongly the target is pulled towards the
+ source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0
+
+ When a spring constant is set and the velocity property is greater than 0,
+ velocity limits the maximum speed.
+*/
+qreal QmlSpringFollow::spring() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->spring;
+}
+
+void QmlSpringFollow::setSpring(qreal spring)
+{
+ Q_D(QmlSpringFollow);
+ d->spring = spring;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty qreal SpringFollow::damping
+ This property holds the spring damping constant
+
+ The damping constant describes how quickly a sprung follower comes to rest.
+ Useful range is 0 - 1.0
+*/
+qreal QmlSpringFollow::damping() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->damping;
+}
+
+void QmlSpringFollow::setDamping(qreal damping)
+{
+ Q_D(QmlSpringFollow);
+ if (damping > 1.)
+ damping = 1.;
+
+ d->damping = damping;
+}
+
+
+/*!
+ \qmlproperty qreal SpringFollow::epsilon
+ This property holds the spring epsilon
+
+ The epsilon is the rate and amount of change in the value which is close enough
+ to 0 to be considered equal to zero. This will depend on the usage of the value.
+ For pixel positions, 0.25 would suffice. For scale, 0.005 will suffice.
+
+ The default is 0.01. Tuning this value can provide small performance improvements.
+*/
+qreal QmlSpringFollow::epsilon() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->epsilon;
+}
+
+void QmlSpringFollow::setEpsilon(qreal epsilon)
+{
+ Q_D(QmlSpringFollow);
+ d->epsilon = epsilon;
+}
+
+/*!
+ \qmlproperty qreal SpringFollow::modulus
+ This property holds the modulus value.
+
+ Setting a \a modulus forces the target value to "wrap around" at the modulus.
+ For example, setting the modulus to 360 will cause a value of 370 to wrap around to 10.
+*/
+qreal QmlSpringFollow::modulus() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->modulus;
+}
+
+void QmlSpringFollow::setModulus(qreal modulus)
+{
+ Q_D(QmlSpringFollow);
+ if (d->modulus != modulus) {
+ d->haveModulus = modulus != 0.0;
+ d->modulus = modulus;
+ emit modulusChanged();
+ }
+}
+
+/*!
+ \qmlproperty qreal SpringFollow::mass
+ This property holds the "mass" of the property being moved.
+
+ mass is 1.0 by default. Setting a different mass changes the dynamics of
+ a \l spring follow.
+*/
+qreal QmlSpringFollow::mass() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->mass;
+}
+
+void QmlSpringFollow::setMass(qreal mass)
+{
+ Q_D(QmlSpringFollow);
+ if (d->mass != mass && mass > 0.0) {
+ d->useMass = mass != 1.0;
+ d->mass = mass;
+ emit massChanged();
+ }
+}
+
+/*!
+ \qmlproperty qreal SpringFollow::value
+ The current value.
+*/
+
+/*!
+ \qmlproperty bool SpringFollow::enabled
+ This property holds whether the target will track the source.
+*/
+bool QmlSpringFollow::enabled() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->enabled;
+}
+
+void QmlSpringFollow::setEnabled(bool enabled)
+{
+ Q_D(QmlSpringFollow);
+ d->enabled = enabled;
+ if (enabled)
+ d->start();
+ else
+ d->stop();
+}
+
+/*!
+ \qmlproperty bool SpringFollow::inSync
+ This property is true when target is equal to the source; otherwise
+ false. If inSync is true the target is not being animated.
+
+ If \l enabled is false then inSync will also be false.
+*/
+bool QmlSpringFollow::inSync() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->enabled && d->clock.state() != QAbstractAnimation::Running;
+}
+
+qreal QmlSpringFollow::value() const
+{
+ Q_D(const QmlSpringFollow);
+ return d->currentValue;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlspringfollow_p.h b/src/declarative/util/qmlspringfollow_p.h
new file mode 100644
index 0000000..7731b9e
--- /dev/null
+++ b/src/declarative/util/qmlspringfollow_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSMOOTHFOLLOW_H
+#define QMLSMOOTHFOLLOW_H
+
+#include <qmlpropertyvaluesource.h>
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlSpringFollowPrivate;
+class Q_DECLARATIVE_EXPORT QmlSpringFollow : public QObject,
+ public QmlPropertyValueSource
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlSpringFollow)
+ Q_INTERFACES(QmlPropertyValueSource)
+
+ Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue)
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity)
+ Q_PROPERTY(qreal spring READ spring WRITE setSpring)
+ Q_PROPERTY(qreal damping READ damping WRITE setDamping)
+ Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
+ Q_PROPERTY(qreal value READ value NOTIFY valueChanged)
+ Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged)
+ Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged)
+ Q_PROPERTY(bool inSync READ inSync NOTIFY syncChanged)
+
+public:
+ QmlSpringFollow(QObject *parent=0);
+ ~QmlSpringFollow();
+
+ virtual void setTarget(const QmlMetaProperty &);
+
+ qreal sourceValue() const;
+ void setSourceValue(qreal value);
+ qreal velocity() const;
+ void setVelocity(qreal velocity);
+ qreal spring() const;
+ void setSpring(qreal spring);
+ qreal damping() const;
+ void setDamping(qreal damping);
+ qreal epsilon() const;
+ void setEpsilon(qreal epsilon);
+ qreal mass() const;
+ void setMass(qreal modulus);
+ qreal modulus() const;
+ void setModulus(qreal modulus);
+ bool enabled() const;
+ void setEnabled(bool enabled);
+ bool inSync() const;
+
+ qreal value() const;
+
+Q_SIGNALS:
+ void valueChanged(qreal);
+ void modulusChanged();
+ void massChanged();
+ void syncChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlSpringFollow)
+
+QT_END_HEADER
+
+#endif // QMLSMOOTHFOLLOW_H
diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp
new file mode 100644
index 0000000..cae8054
--- /dev/null
+++ b/src/declarative/util/qmlstate.cpp
@@ -0,0 +1,468 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlstate_p_p.h"
+#include "qmlstate_p.h"
+
+#include "qmltransition_p.h"
+#include "qmlstategroup_p.h"
+#include "qmlstateoperations_p.h"
+#include "qmlanimation_p.h"
+#include "qmlanimation_p_p.h"
+
+#include <qmlbinding.h>
+#include <qmlglobal_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+QmlAction::QmlAction()
+: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), fromBinding(0), toBinding(0), event(0),
+ specifiedObject(0)
+{
+}
+
+QmlAction::QmlAction(QObject *target, const QString &propertyName,
+ const QVariant &value)
+: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), toValue(value), fromBinding(0),
+ toBinding(0), event(0), specifiedObject(target),
+ specifiedProperty(propertyName)
+{
+ property = QmlMetaProperty::createProperty(target, propertyName);
+ if (property.isValid())
+ fromValue = property.read();
+}
+
+QmlActionEvent::~QmlActionEvent()
+{
+}
+
+QString QmlActionEvent::typeName() const
+{
+ return QString();
+}
+
+void QmlActionEvent::execute()
+{
+}
+
+bool QmlActionEvent::isReversable()
+{
+ return false;
+}
+
+void QmlActionEvent::reverse()
+{
+}
+
+QList<QmlAction> QmlActionEvent::extraActions()
+{
+ return QList<QmlAction>();
+}
+
+bool QmlActionEvent::changesBindings()
+{
+ return false;
+}
+
+void QmlActionEvent::clearForwardBindings()
+{
+}
+
+void QmlActionEvent::clearReverseBindings()
+{
+}
+
+bool QmlActionEvent::override(QmlActionEvent *other)
+{
+ Q_UNUSED(other);
+ return false;
+}
+
+/*!
+ \internal
+*/
+QmlStateOperation::QmlStateOperation(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ \qmlclass State QmlState
+ \brief The State element defines configurations of objects and properties.
+
+ A state is specified as a set of batched changes from the default configuration.
+
+ Note that setting the state of an object from within another state of the same object is
+ inadvisible. Not only would this have the same effect as going directly to the second state
+ it may cause the program to crash.
+
+ \sa {qmlstates}{States}, {state-transitions}{Transitions}
+*/
+
+/*!
+ \internal
+ \class QmlState
+ \brief The QmlState class allows you to define configurations of objects and properties.
+
+ \ingroup group_states
+
+ QmlState allows you to specify a state as a set of batched changes from the default
+ configuration.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,State,QmlState)
+QmlState::QmlState(QObject *parent)
+: QObject(*(new QmlStatePrivate), parent)
+{
+ Q_D(QmlState);
+ d->transitionManager.setState(this);
+}
+
+QmlState::~QmlState()
+{
+ Q_D(QmlState);
+ if (d->group)
+ d->group->removeState(this);
+}
+
+/*!
+ \qmlproperty string State::name
+ This property holds the name of the state
+
+ Each state should have a unique name.
+*/
+QString QmlState::name() const
+{
+ Q_D(const QmlState);
+ return d->name;
+}
+
+void QmlState::setName(const QString &n)
+{
+ Q_D(QmlState);
+ d->name = n;
+}
+
+bool QmlState::isWhenKnown() const
+{
+ Q_D(const QmlState);
+ return d->when != 0;
+}
+
+/*!
+ \qmlproperty bool State::when
+ This property holds when the state should be applied
+
+ This should be set to an expression that evaluates to true when you want the state to
+ be applied.
+*/
+QmlBinding *QmlState::when() const
+{
+ Q_D(const QmlState);
+ return d->when;
+}
+
+void QmlState::setWhen(QmlBinding *when)
+{
+ Q_D(QmlState);
+ d->when = when;
+ if (d->group)
+ d->group->updateAutoState();
+}
+
+/*!
+ \qmlproperty string State::extend
+ This property holds the state that this state extends
+
+ The state being extended is treated as the base state in regards to
+ the changes specified by the extending state.
+*/
+QString QmlState::extends() const
+{
+ Q_D(const QmlState);
+ return d->extends;
+}
+
+void QmlState::setExtends(const QString &extends)
+{
+ Q_D(QmlState);
+ d->extends = extends;
+}
+
+/*!
+ \qmlproperty list<Change> State::changes
+ This property holds the changes to apply for this state
+ \default
+
+ By default these changes are applied against the default state. If the state
+ extends another state, then the changes are applied against the state being
+ extended.
+*/
+QmlList<QmlStateOperation *> *QmlState::changes()
+{
+ Q_D(QmlState);
+ return &d->operations;
+}
+
+QmlState &QmlState::operator<<(QmlStateOperation *op)
+{
+ Q_D(QmlState);
+ d->operations.append(op);
+ return *this;
+}
+
+void QmlStatePrivate::complete()
+{
+ Q_Q(QmlState);
+
+ for (int ii = 0; ii < reverting.count(); ++ii) {
+ for (int jj = 0; jj < revertList.count(); ++jj) {
+ if (revertList.at(jj).property == reverting.at(ii)) {
+ revertList.removeAt(jj);
+ break;
+ }
+ }
+ }
+ reverting.clear();
+
+ emit q->completed();
+}
+
+// Generate a list of actions for this state. This includes coelescing state
+// actions that this state "extends"
+QmlStateOperation::ActionList
+QmlStatePrivate::generateActionList(QmlStateGroup *group) const
+{
+ QmlStateOperation::ActionList applyList;
+ if (inState)
+ return applyList;
+
+ // Prevent "extends" recursion
+ inState = true;
+
+ if (!extends.isEmpty()) {
+ QList<QmlState *> states = group->states();
+ for (int ii = 0; ii < states.count(); ++ii)
+ if (states.at(ii)->name() == extends)
+ applyList = static_cast<QmlStatePrivate*>(states.at(ii)->d_func())->generateActionList(group);
+ }
+
+ foreach(QmlStateOperation *op, operations)
+ applyList << op->actions();
+
+ inState = false;
+ return applyList;
+}
+
+QmlStateGroup *QmlState::stateGroup() const
+{
+ Q_D(const QmlState);
+ return d->group;
+}
+
+void QmlState::setStateGroup(QmlStateGroup *group)
+{
+ Q_D(QmlState);
+ d->group = group;
+}
+
+void QmlState::cancel()
+{
+ Q_D(QmlState);
+ d->transitionManager.cancel();
+}
+
+void QmlAction::deleteFromBinding()
+{
+ if (fromBinding) {
+ property.setBinding(0);
+ fromBinding->destroy();
+ fromBinding = 0;
+ }
+}
+
+void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *revert)
+{
+ Q_D(QmlState);
+
+ qmlExecuteDeferred(this);
+
+ cancel();
+ if (revert)
+ revert->cancel();
+ d->revertList.clear();
+ d->reverting.clear();
+
+ if (revert) {
+ QmlStatePrivate *revertPrivate =
+ static_cast<QmlStatePrivate*>(revert->d_func());
+ d->revertList = revertPrivate->revertList;
+ revertPrivate->revertList.clear();
+ }
+
+ // List of actions caused by this state
+ QmlStateOperation::ActionList applyList = d->generateActionList(group);
+
+ // List of actions that need to be reverted to roll back (just) this state
+ QmlStatePrivate::SimpleActionList additionalReverts;
+ // First add the reverse of all the applyList actions
+ for (int ii = 0; ii < applyList.count(); ++ii) {
+ QmlAction &action = applyList[ii];
+
+ bool found = false;
+
+ int jj;
+ if (action.event) {
+ if (!action.event->isReversable())
+ continue;
+ for (jj = 0; jj < d->revertList.count(); ++jj) {
+ QmlActionEvent *event = d->revertList.at(jj).event;
+ if (event && event->typeName() == action.event->typeName()) {
+ if (action.event->override(event)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found || action.event != d->revertList.at(jj).event)
+ action.event->saveOriginals();
+ else if (action.event->isRewindable())
+ action.event->saveCurrentValues();
+ } else {
+ action.fromBinding = action.property.binding();
+
+ for (jj = 0; jj < d->revertList.count(); ++jj) {
+ if (d->revertList.at(jj).property == action.property) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ if (!action.restore) {
+ action.deleteFromBinding();
+ } else {
+ // Only need to revert the applyList action if the previous
+ // state doesn't have a higher priority revert already
+ QmlSimpleAction r(action);
+ additionalReverts << r;
+ }
+ } else if (d->revertList.at(jj).binding != action.fromBinding) {
+ action.deleteFromBinding();
+ }
+ }
+
+ // Any reverts from a previous state that aren't carried forth
+ // into this state need to be translated into apply actions
+ for (int ii = 0; ii < d->revertList.count(); ++ii) {
+ bool found = false;
+ if (d->revertList.at(ii).event) {
+ QmlActionEvent *event = d->revertList.at(ii).event;
+ if (!event->isReversable())
+ continue;
+ for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ const QmlAction &action = applyList.at(jj);
+ if (action.event && action.event->typeName() == event->typeName()) {
+ if (action.event->override(event))
+ found = true;
+ }
+ }
+ } else {
+ for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ const QmlAction &action = applyList.at(jj);
+ if (action.property == d->revertList.at(ii).property)
+ found = true;
+ }
+ }
+ if (!found) {
+ QVariant cur = d->revertList.at(ii).property.read();
+ QmlAbstractBinding *delBinding = d->revertList.at(ii).property.setBinding(0);
+ if (delBinding)
+ delBinding->destroy();
+
+ QmlAction a;
+ a.property = d->revertList.at(ii).property;
+ a.fromValue = cur;
+ a.toValue = d->revertList.at(ii).value;
+ a.toBinding = d->revertList.at(ii).binding;
+ a.specifiedObject = d->revertList.at(ii).specifiedObject;
+ a.specifiedProperty = d->revertList.at(ii).specifiedProperty;
+ a.event = d->revertList.at(ii).event;
+ a.reverseEvent = d->revertList.at(ii).reverseEvent;
+ if (a.event && a.event->isRewindable())
+ a.event->saveCurrentValues();
+ applyList << a;
+ // Store these special reverts in the reverting list
+ d->reverting << d->revertList.at(ii).property;
+ }
+ }
+ // All the local reverts now become part of the ongoing revertList
+ d->revertList << additionalReverts;
+
+ // Output for debugging
+ if (stateChangeDebug()) {
+ foreach(const QmlAction &action, applyList) {
+ if (action.event)
+ qWarning() << " QmlAction event:" << action.event->typeName();
+ else
+ qWarning() << " QmlAction:" << action.property.object()
+ << action.property.name() << "From:" << action.fromValue
+ << "To:" << action.toValue;
+ }
+ }
+
+ d->transitionManager.transition(applyList, trans);
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlStateOperation)
+QmlStateOperation::ActionList QmlStateOperation::actions()
+{
+ return ActionList();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h
new file mode 100644
index 0000000..5862c02
--- /dev/null
+++ b/src/declarative/util/qmlstate_p.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATE_H
+#define QMLSTATE_H
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlActionEvent;
+class QmlBinding;
+class Q_DECLARATIVE_EXPORT QmlAction
+{
+public:
+ QmlAction();
+ QmlAction(QObject *, const QString &, const QVariant &);
+
+ bool restore:1;
+ bool actionDone:1;
+ bool reverseEvent:1;
+ bool deletableToBinding:1;
+
+ QmlMetaProperty property;
+ QVariant fromValue;
+ QVariant toValue;
+
+ QmlAbstractBinding *fromBinding;
+ QmlAbstractBinding *toBinding;
+ QmlActionEvent *event;
+
+ //strictly for matching
+ QObject *specifiedObject;
+ QString specifiedProperty;
+
+ void deleteFromBinding();
+};
+
+class QmlActionEvent
+{
+public:
+ virtual ~QmlActionEvent();
+ virtual QString typeName() const;
+
+ virtual void execute();
+ virtual bool isReversable();
+ virtual void reverse();
+ virtual void saveOriginals() {}
+
+ virtual bool isRewindable() { return isReversable(); }
+ virtual void rewind() {}
+ virtual void saveCurrentValues() {}
+
+ //virtual bool hasExtraActions();
+ virtual QList<QmlAction> extraActions();
+
+ virtual bool changesBindings();
+ virtual void clearForwardBindings();
+ virtual void clearReverseBindings();
+ virtual bool override(QmlActionEvent*other);
+};
+
+//### rename to QmlStateChange?
+class QmlStateGroup;
+class Q_DECLARATIVE_EXPORT QmlStateOperation : public QObject
+{
+ Q_OBJECT
+public:
+ QmlStateOperation(QObject *parent = 0)
+ : QObject(parent) {}
+ typedef QList<QmlAction> ActionList;
+
+ virtual ActionList actions();
+
+protected:
+ QmlStateOperation(QObjectPrivate &dd, QObject *parent = 0);
+};
+
+typedef QmlStateOperation::ActionList QmlStateActions;
+
+class QmlTransition;
+class QmlStatePrivate;
+class Q_DECLARATIVE_EXPORT QmlState : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QmlBinding *when READ when WRITE setWhen)
+ Q_PROPERTY(QString extend READ extends WRITE setExtends)
+ Q_PROPERTY(QmlList<QmlStateOperation *>* changes READ changes)
+ Q_CLASSINFO("DefaultProperty", "changes")
+ Q_CLASSINFO("DeferredPropertyNames", "changes")
+
+public:
+ QmlState(QObject *parent=0);
+ virtual ~QmlState();
+
+ QString name() const;
+ void setName(const QString &);
+
+ /*'when' is a QmlBinding to limit state changes oscillation
+ due to the unpredictable order of evaluation of bound expressions*/
+ bool isWhenKnown() const;
+ QmlBinding *when() const;
+ void setWhen(QmlBinding *);
+
+ QString extends() const;
+ void setExtends(const QString &);
+
+ QmlList<QmlStateOperation *> *changes();
+ QmlState &operator<<(QmlStateOperation *);
+
+ void apply(QmlStateGroup *, QmlTransition *, QmlState *revert);
+ void cancel();
+
+ QmlStateGroup *stateGroup() const;
+ void setStateGroup(QmlStateGroup *);
+
+Q_SIGNALS:
+ void completed();
+
+private:
+ Q_DECLARE_PRIVATE(QmlState)
+ Q_DISABLE_COPY(QmlState)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlStateOperation)
+QML_DECLARE_TYPE(QmlState)
+
+QT_END_HEADER
+
+#endif // QMLSTATE_H
diff --git a/src/declarative/util/qmlstate_p_p.h b/src/declarative/util/qmlstate_p_p.h
new file mode 100644
index 0000000..235fe62
--- /dev/null
+++ b/src/declarative/util/qmlstate_p_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATE_P_H
+#define QMLSTATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlstate_p.h"
+
+#include "qmlanimation_p_p.h"
+#include "qmltransitionmanager_p_p.h"
+
+#include <qmlguard_p.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlSimpleAction
+{
+public:
+ enum State { StartState, EndState };
+ QmlSimpleAction(const QmlAction &a, State state = StartState)
+ {
+ property = a.property;
+ specifiedObject = a.specifiedObject;
+ specifiedProperty = a.specifiedProperty;
+ event = a.event;
+ if (state == StartState) {
+ value = a.fromValue;
+ binding = property.binding();
+ reverseEvent = true;
+ } else {
+ value = a.toValue;
+ binding = a.toBinding;
+ reverseEvent = false;
+ }
+ }
+
+ QmlMetaProperty property;
+ QVariant value;
+ QmlAbstractBinding *binding;
+ QObject *specifiedObject;
+ QString specifiedProperty;
+ QmlActionEvent *event;
+ bool reverseEvent;
+};
+
+class QmlStatePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlState)
+
+public:
+ QmlStatePrivate()
+ : when(0), inState(false), group(0) {}
+
+ typedef QList<QmlSimpleAction> SimpleActionList;
+
+ QString name;
+ QmlBinding *when;
+
+ class OperationList;
+ struct OperationGuard : public QmlGuard<QmlStateOperation>
+ {
+ OperationGuard(QObject *obj, OperationList *l) : list(l) { (QmlGuard<QObject>&)*this = obj; }
+ OperationList *list;
+ void objectDestroyed(QmlStateOperation *) {
+ // we assume priv will always be destroyed after objectDestroyed calls
+ list->removeOne(*this);
+ }
+ };
+
+ class OperationList : public QList<OperationGuard>, public QmlList<QmlStateOperation*>
+ {
+ public:
+ virtual void append(QmlStateOperation* v) { QList<OperationGuard>::append(OperationGuard(v, this)); }
+ virtual void insert(int i, QmlStateOperation* v) { QList<OperationGuard>::insert(i, OperationGuard(v, this)); }
+ virtual void clear() { QList<OperationGuard>::clear(); }
+ virtual QmlStateOperation* at(int i) const { return QList<OperationGuard>::at(i); }
+ virtual void removeAt(int i) { QList<OperationGuard>::removeAt(i); }
+ virtual int count() const { return QList<OperationGuard>::count(); }
+ };
+ OperationList operations;
+
+ QmlTransitionManager transitionManager;
+
+ SimpleActionList revertList;
+ QList<QmlMetaProperty> reverting;
+ QString extends;
+ mutable bool inState;
+ QmlStateGroup *group;
+
+ QmlStateOperation::ActionList generateActionList(QmlStateGroup *) const;
+ void complete();
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTATE_P_H
diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp
new file mode 100644
index 0000000..d4db2b9
--- /dev/null
+++ b/src/declarative/util/qmlstategroup.cpp
@@ -0,0 +1,423 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlstategroup_p.h"
+
+#include "qmltransition_p.h"
+#include "qmlstate_p_p.h"
+
+#include <qmlbinding.h>
+#include <qmlglobal_p.h>
+
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+QML_DEFINE_TYPE(Qt,4,6,StateGroup,QmlStateGroup)
+
+class QmlStateGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlStateGroup)
+public:
+ QmlStateGroupPrivate(QmlStateGroup *p)
+ : nullState(0), states(p), componentComplete(true),
+ ignoreTrans(false), applyingState(false) {}
+
+ QString currentState;
+ QmlState *nullState;
+
+ struct StateList : public QmlConcreteList<QmlState *>
+ {
+ StateList(QmlStateGroup *g)
+ :group(g) {}
+ void append(QmlState *s) {
+ QmlConcreteList<QmlState *>::append(s);
+ if (s) s->setStateGroup(group);
+ }
+ private:
+ QmlStateGroup *group;
+ };
+ StateList states;
+
+ QmlConcreteList<QmlTransition *> transitions;
+ bool componentComplete;
+ bool ignoreTrans;
+ bool applyingState;
+
+ QmlTransition *findTransition(const QString &from, const QString &to);
+ void setCurrentStateInternal(const QString &state, bool = false);
+ bool updateAutoState();
+};
+
+/*!
+ \qmlclass StateGroup QmlStateGroup
+ \brief The StateGroup element provides state support for non-Item elements.
+
+ Item (and all dervied elements) provides built in support for states and transitions
+ via its state, states and transitions properties. StateGroup provides an easy way to
+ use this support in other (non-Item-derived) elements.
+
+ \qml
+ MyCustomObject {
+ StateGroup {
+ id: myStateGroup
+ states: State {
+ name: "state1"
+ ...
+ }
+ transitions: Transition {
+ ...
+ }
+ }
+
+ onSomethingHappened: myStateGroup.state = "state1";
+ }
+ \endqml
+
+ \sa {qmlstate}{States} {state-transitions}{Transitions}
+*/
+
+QmlStateGroup::QmlStateGroup(QObject *parent)
+ : QObject(*(new QmlStateGroupPrivate(this)), parent)
+{
+}
+
+QmlStateGroup::~QmlStateGroup()
+{
+ Q_D(const QmlStateGroup);
+ for (int i = 0; i < d->states.count(); ++i)
+ d->states.at(i)->setStateGroup(0);
+}
+
+QList<QmlState *> QmlStateGroup::states() const
+{
+ Q_D(const QmlStateGroup);
+ return d->states;
+}
+
+/*!
+ \qmlproperty list<State> StateGroup::states
+ This property holds a list of states defined by the state group.
+
+ \qml
+ StateGroup {
+ states: [
+ State { ... },
+ State { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {qmlstate}{States}
+*/
+QmlList<QmlState *>* QmlStateGroup::statesProperty()
+{
+ Q_D(QmlStateGroup);
+ return &(d->states);
+}
+
+/*!
+ \qmlproperty list<Transition> StateGroup::transitions
+ This property holds a list of transitions defined by the state group.
+
+ \qml
+ StateGroup {
+ transitions: [
+ Transition { ... },
+ Transition { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {state-transitions}{Transitions}
+*/
+QmlList<QmlTransition *>* QmlStateGroup::transitionsProperty()
+{
+ Q_D(QmlStateGroup);
+ return &(d->transitions);
+}
+
+/*!
+ \qmlproperty string StateGroup::state
+
+ This property holds the name of the current state of the state group.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ Script {
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ }
+ \endqml
+
+ If the state group is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return a
+ state group to its base state by setting its current state to \c ''.
+
+ \sa {qmlstates}{States}
+*/
+QString QmlStateGroup::state() const
+{
+ Q_D(const QmlStateGroup);
+ return d->currentState;
+}
+
+void QmlStateGroup::setState(const QString &state)
+{
+ Q_D(QmlStateGroup);
+ if (d->currentState == state)
+ return;
+
+ d->setCurrentStateInternal(state);
+}
+
+void QmlStateGroup::classBegin()
+{
+ Q_D(QmlStateGroup);
+ d->componentComplete = false;
+}
+
+void QmlStateGroup::componentComplete()
+{
+ Q_D(QmlStateGroup);
+ d->componentComplete = true;
+
+ if (d->updateAutoState()) {
+ return;
+ } else if (!d->currentState.isEmpty()) {
+ QString cs = d->currentState;
+ d->currentState = QString();
+ d->setCurrentStateInternal(cs, true);
+ }
+}
+
+/*!
+ Returns true if the state was changed, otherwise false.
+*/
+bool QmlStateGroup::updateAutoState()
+{
+ Q_D(QmlStateGroup);
+ return d->updateAutoState();
+}
+
+bool QmlStateGroupPrivate::updateAutoState()
+{
+ Q_Q(QmlStateGroup);
+ if (!componentComplete)
+ return false;
+
+ bool revert = false;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ QmlState *state = states.at(ii);
+ if (state->isWhenKnown()) {
+ if (!state->name().isEmpty()) {
+ if (state->when() && state->when()->value().toBool()) {
+ if (stateChangeDebug())
+ qWarning() << "Setting auto state due to:"
+ << state->when()->expression();
+ if (currentState != state->name()) {
+ q->setState(state->name());
+ return true;
+ } else {
+ return false;
+ }
+ } else if (state->name() == currentState) {
+ revert = true;
+ }
+ }
+ }
+ }
+ if (revert) {
+ bool rv = currentState != QString();
+ q->setState(QString());
+ return rv;
+ } else {
+ return false;
+ }
+}
+
+QmlTransition *QmlStateGroupPrivate::findTransition(const QString &from, const QString &to)
+{
+ QmlTransition *highest = 0;
+ int score = 0;
+ bool reversed = false;
+ bool done = false;
+
+ for (int ii = 0; !done && ii < transitions.count(); ++ii) {
+ QmlTransition *t = transitions.at(ii);
+ for (int ii = 0; ii < 2; ++ii)
+ {
+ if (ii && (!t->reversible() ||
+ (t->fromState() == QLatin1String("*") &&
+ t->toState() == QLatin1String("*"))))
+ break;
+ QStringList fromState;
+ QStringList toState;
+
+ fromState = t->fromState().split(QLatin1Char(','));
+ toState = t->toState().split(QLatin1Char(','));
+ if (ii == 1)
+ qSwap(fromState, toState);
+ int tScore = 0;
+ if (fromState.contains(from))
+ tScore += 2;
+ else if (fromState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (toState.contains(to))
+ tScore += 2;
+ else if (toState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (ii == 1)
+ reversed = true;
+ else
+ reversed = false;
+
+ if (tScore == 4) {
+ highest = t;
+ done = true;
+ break;
+ } else if (tScore > score) {
+ score = tScore;
+ highest = t;
+ }
+ }
+ }
+
+ if (highest)
+ highest->setReversed(reversed);
+
+ return highest;
+}
+
+void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state,
+ bool ignoreTrans)
+{
+ Q_Q(QmlStateGroup);
+ if (!componentComplete) {
+ currentState = state;
+ return;
+ }
+
+ if (applyingState) {
+ qWarning() << "Can't apply a state change as part of a state definition.";
+ return;
+ }
+
+ applyingState = true;
+
+ QmlTransition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state);
+ if (stateChangeDebug()) {
+ qWarning() << this << "Changing state. From" << currentState << ". To" << state;
+ if (transition)
+ qWarning() << " using transition" << transition->fromState()
+ << transition->toState();
+ }
+
+ QmlState *oldState = 0;
+ if (!currentState.isEmpty()) {
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ oldState = states.at(ii);
+ break;
+ }
+ }
+ }
+
+ currentState = state;
+ emit q->stateChanged(currentState);
+
+ QmlState *newState = 0;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ newState = states.at(ii);
+ break;
+ }
+ }
+
+ if (oldState == 0 || newState == 0) {
+ if (!nullState) { nullState = new QmlState; QmlGraphics_setParent_noEvent(nullState, q); }
+ if (!oldState) oldState = nullState;
+ if (!newState) newState = nullState;
+ }
+
+ newState->apply(q, transition, oldState);
+ applyingState = false;
+ if (!transition)
+ static_cast<QmlStatePrivate*>(QObjectPrivate::get(newState))->complete();
+}
+
+QmlState *QmlStateGroup::findState(const QString &name) const
+{
+ Q_D(const QmlStateGroup);
+ for (int i = 0; i < d->states.count(); ++i) {
+ QmlState *state = d->states.at(i);
+ if (state->name() == name)
+ return state;
+ }
+
+ return 0;
+}
+
+void QmlStateGroup::removeState(QmlState *state)
+{
+ Q_D(QmlStateGroup);
+ d->states.removeOne(state);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstategroup_p.h b/src/declarative/util/qmlstategroup_p.h
new file mode 100644
index 0000000..112c9eb
--- /dev/null
+++ b/src/declarative/util/qmlstategroup_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATEGROUP_H
+#define QMLSTATEGROUP_H
+
+#include "qmlstate_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlStateGroupPrivate;
+class Q_DECLARATIVE_EXPORT QmlStateGroup : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+ Q_DECLARE_PRIVATE(QmlStateGroup)
+
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QmlList<QmlState *>* states READ statesProperty DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitionsProperty DESIGNABLE false)
+
+public:
+ QmlStateGroup(QObject * = 0);
+ virtual ~QmlStateGroup();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QmlList<QmlState *>* statesProperty();
+ QList<QmlState *> states() const;
+
+ QmlList<QmlTransition *>* transitionsProperty();
+
+ QmlState *findState(const QString &name) const;
+
+ virtual void classBegin();
+ virtual void componentComplete();
+Q_SIGNALS:
+ void stateChanged(const QString &);
+
+private:
+ friend class QmlState;
+ bool updateAutoState();
+ void removeState(QmlState *state);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlStateGroup)
+
+QT_END_HEADER
+
+#endif // QMLSTATEGROUP_H
diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp
new file mode 100644
index 0000000..35c8f7d
--- /dev/null
+++ b/src/declarative/util/qmlstateoperations.cpp
@@ -0,0 +1,834 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlstateoperations_p.h"
+
+#include <qml.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+#include <qmlinfo.h>
+#include <qmlgraphicsanchors_p_p.h>
+#include <qmlgraphicsitem_p.h>
+#include <qmlguard_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtGui/qgraphicsitem.h>
+#include <QtCore/qmath.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlParentChangePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlParentChange)
+public:
+ QmlParentChangePrivate() : target(0), parent(0), origParent(0), origStackBefore(0),
+ rewindParent(0), rewindStackBefore(0) {}
+
+ QmlGraphicsItem *target;
+ QmlGraphicsItem *parent;
+ QmlGuard<QmlGraphicsItem> origParent;
+ QmlGuard<QmlGraphicsItem> origStackBefore;
+ QmlGraphicsItem *rewindParent;
+ QmlGraphicsItem *rewindStackBefore;
+
+ void doChange(QmlGraphicsItem *targetParent, QmlGraphicsItem *stackBefore = 0);
+};
+
+void QmlParentChangePrivate::doChange(QmlGraphicsItem *targetParent, QmlGraphicsItem *stackBefore)
+{
+ if (targetParent && target && target->parentItem()) {
+ //### for backwards direction, can we just restore original x, y, scale, rotation
+ Q_Q(QmlParentChange);
+ bool ok;
+ const QTransform &transform = target->itemTransform(targetParent, &ok);
+ if (transform.type() >= QTransform::TxShear || !ok) {
+ qmlInfo(q) << QObject::tr("Unable to preserve appearance under complex transform");
+ ok = false;
+ }
+
+ qreal scale = 1;
+ qreal rotation = 0;
+ if (ok && transform.type() != QTransform::TxRotate) {
+ if (transform.m11() == transform.m22())
+ scale = transform.m11();
+ else {
+ qmlInfo(q) << QObject::tr("Unable to preserve appearance under non-uniform scale");
+ ok = false;
+ }
+ } else if (ok && transform.type() == QTransform::TxRotate) {
+ if (transform.m11() == transform.m22())
+ scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
+ else {
+ qmlInfo(q) << QObject::tr("Unable to preserve appearance under non-uniform scale");
+ ok = false;
+ }
+
+ if (scale != 0)
+ rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
+ else {
+ qmlInfo(q) << QObject::tr("Unable to preserve appearance under scale of 0");
+ ok = false;
+ }
+ }
+
+ qreal xt = transform.dx();
+ qreal yt = transform.dy();
+ if (ok && target->transformOrigin() != QmlGraphicsItem::TopLeft) {
+ qreal tempxt = target->transformOriginPoint().x();
+ qreal tempyt = target->transformOriginPoint().y();
+ QTransform t;
+ t.translate(-tempxt, -tempyt);
+ t.rotate(rotation);
+ t.scale(scale, scale);
+ t.translate(tempxt, tempyt);
+ QPointF offset = t.map(QPointF(0,0));
+ xt += offset.x();
+ yt += offset.y();
+ }
+
+ target->setParentItem(targetParent);
+ if (ok) {
+ //qDebug() << xt << yt << rotation << scale;
+ target->setX(xt);
+ target->setY(yt);
+ target->setRotation(rotation);
+ target->setScale(scale);
+ }
+ } else if (target) {
+ target->setParentItem(targetParent);
+ }
+
+ //restore the original stack position.
+ //### if stackBefore has also been reparented this won't work
+ if (stackBefore)
+ target->stackBefore(stackBefore);
+}
+
+/*!
+ \preliminary
+ \qmlclass ParentChange QmlParentChange
+ \brief The ParentChange element allows you to reparent an Item in a state change.
+
+ ParentChange reparents an Item while preserving its visual appearance (position, rotation,
+ and scale) on screen. You can then specify a transition to move/rotate/scale the Item to
+ its final intended appearance.
+
+ ParentChange can only preserve visual appearance if no complex transforms are involved.
+ More specifically, it will not work if the transform property has been set for any
+ Items involved in the reparenting (defined as any Items in the common ancestor tree
+ for the original and new parent).
+
+ You can specify at which point in a transition you want a ParentChange to occur by
+ using a ParentAction.
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,ParentChange,QmlParentChange)
+QmlParentChange::QmlParentChange(QObject *parent)
+ : QmlStateOperation(*(new QmlParentChangePrivate), parent)
+{
+}
+
+QmlParentChange::~QmlParentChange()
+{
+}
+
+/*!
+ \qmlproperty Item ParentChange::target
+ This property holds the item to be reparented
+*/
+
+QmlGraphicsItem *QmlParentChange::object() const
+{
+ Q_D(const QmlParentChange);
+ return d->target;
+}
+
+void QmlParentChange::setObject(QmlGraphicsItem *target)
+{
+ Q_D(QmlParentChange);
+ d->target = target;
+}
+
+/*!
+ \qmlproperty Item ParentChange::parent
+ This property holds the parent for the item in this state
+*/
+
+QmlGraphicsItem *QmlParentChange::parent() const
+{
+ Q_D(const QmlParentChange);
+ return d->parent;
+}
+
+void QmlParentChange::setParent(QmlGraphicsItem *parent)
+{
+ Q_D(QmlParentChange);
+ d->parent = parent;
+}
+
+QmlStateOperation::ActionList QmlParentChange::actions()
+{
+ Q_D(QmlParentChange);
+ if (!d->target || !d->parent)
+ return ActionList();
+
+ QmlAction a;
+ a.event = this;
+
+ return ActionList() << a;
+}
+
+class AccessibleFxItem : public QmlGraphicsItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QmlGraphicsItem)
+public:
+ int siblingIndex() {
+ Q_D(QmlGraphicsItem);
+ return d->siblingIndex;
+ }
+};
+
+void QmlParentChange::saveOriginals()
+{
+ Q_D(QmlParentChange);
+ saveCurrentValues();
+ d->origParent = d->rewindParent;
+ d->origStackBefore = d->rewindStackBefore;
+}
+
+void QmlParentChange::execute()
+{
+ Q_D(QmlParentChange);
+ d->doChange(d->parent);
+}
+
+bool QmlParentChange::isReversable()
+{
+ return true;
+}
+
+void QmlParentChange::reverse()
+{
+ Q_D(QmlParentChange);
+ d->doChange(d->origParent, d->origStackBefore);
+}
+
+QString QmlParentChange::typeName() const
+{
+ return QLatin1String("ParentChange");
+}
+
+bool QmlParentChange::override(QmlActionEvent*other)
+{
+ Q_D(QmlParentChange);
+ if (other->typeName() != QLatin1String("ParentChange"))
+ return false;
+ if (QmlParentChange *otherPC = static_cast<QmlParentChange*>(other))
+ return (d->target == otherPC->object());
+ return false;
+}
+
+void QmlParentChange::saveCurrentValues()
+{
+ Q_D(QmlParentChange);
+ if (!d->target) {
+ d->rewindParent = 0;
+ d->rewindStackBefore = 0;
+ return;
+ }
+
+ d->rewindParent = d->target->parentItem();
+
+ if (!d->rewindParent) {
+ d->rewindStackBefore = 0;
+ return;
+ }
+
+ //try to determine the item's original stack position so we can restore it
+ int siblingIndex = ((AccessibleFxItem*)d->target)->siblingIndex() + 1;
+ QList<QGraphicsItem*> children = d->rewindParent->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem*>(children.at(i));
+ if (!child)
+ continue;
+ if (((AccessibleFxItem*)child)->siblingIndex() == siblingIndex) {
+ d->rewindStackBefore = child;
+ break;
+ }
+ }
+}
+
+void QmlParentChange::rewind()
+{
+ Q_D(QmlParentChange);
+ d->doChange(d->rewindParent, d->rewindStackBefore);
+}
+
+class QmlStateChangeScriptPrivate : public QObjectPrivate
+{
+public:
+ QmlStateChangeScriptPrivate() {}
+
+ QmlScriptString script;
+ QString name;
+};
+
+/*!
+ \qmlclass StateChangeScript QmlStateChangeScript
+ \brief The StateChangeScript element allows you to run a script in a state.
+
+ The script specified will be run immediately when the state is made current.
+ Alternatively you can use a ScriptAction to specify at which point in the transition
+ you want the StateChangeScript to be run.
+*/
+QML_DEFINE_TYPE(Qt,4,6,StateChangeScript,QmlStateChangeScript)
+QmlStateChangeScript::QmlStateChangeScript(QObject *parent)
+: QmlStateOperation(*(new QmlStateChangeScriptPrivate), parent)
+{
+}
+
+QmlStateChangeScript::~QmlStateChangeScript()
+{
+}
+
+/*!
+ \qmlproperty script StateChangeScript::script
+ This property holds the script to run when the state is current.
+*/
+QmlScriptString QmlStateChangeScript::script() const
+{
+ Q_D(const QmlStateChangeScript);
+ return d->script;
+}
+
+void QmlStateChangeScript::setScript(const QmlScriptString &s)
+{
+ Q_D(QmlStateChangeScript);
+ d->script = s;
+}
+
+/*!
+ \qmlproperty script StateChangeScript::script
+ This property holds the name of the script. This name can be used by a
+ ScriptAction to target a specific script.
+
+ \sa ScriptAction::stateChangeScriptName
+*/
+QString QmlStateChangeScript::name() const
+{
+ Q_D(const QmlStateChangeScript);
+ return d->name;
+}
+
+void QmlStateChangeScript::setName(const QString &n)
+{
+ Q_D(QmlStateChangeScript);
+ d->name = n;
+}
+
+void QmlStateChangeScript::execute()
+{
+ Q_D(QmlStateChangeScript);
+ const QString &script = d->script.script();
+ if (!script.isEmpty()) {
+ QmlExpression expr(d->script.context(), script, d->script.scopeObject());
+ expr.setTrackChange(false);
+ expr.value();
+ }
+}
+
+QmlStateChangeScript::ActionList QmlStateChangeScript::actions()
+{
+ ActionList rv;
+ QmlAction a;
+ a.event = this;
+ rv << a;
+ return rv;
+}
+
+QString QmlStateChangeScript::typeName() const
+{
+ return QLatin1String("StateChangeScript");
+}
+
+/*!
+ \qmlclass AnchorChanges QmlAnchorChanges
+ \brief The AnchorChanges element allows you to change the anchors of an item in a state.
+
+ In the following example we change the top and bottom anchors of an item:
+ \snippet examples/declarative/anchors/anchor-changes.qml 0
+
+ AnchorChanges will 'inject' \c x, \c y, \c width, and \c height changes into the transition,
+ so you can animate them as you would normally changes to these properties:
+ \qml
+ //animate our anchor changes
+ NumberAnimation { matchTargets: content; matchProperties: "x,y,width,height" }
+ \endqml
+
+ For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+QML_DEFINE_TYPE(Qt,4,6,AnchorChanges,QmlAnchorChanges)
+
+class QmlAnchorChangesPrivate : public QObjectPrivate
+{
+public:
+ QmlAnchorChangesPrivate() : target(0) {}
+
+ QString name;
+ QmlGraphicsItem *target;
+ QString resetString;
+ QStringList resetList;
+ QmlGraphicsAnchorLine left;
+ QmlGraphicsAnchorLine right;
+ QmlGraphicsAnchorLine horizontalCenter;
+ QmlGraphicsAnchorLine top;
+ QmlGraphicsAnchorLine bottom;
+ QmlGraphicsAnchorLine verticalCenter;
+ QmlGraphicsAnchorLine baseline;
+
+ QmlGraphicsAnchorLine origLeft;
+ QmlGraphicsAnchorLine origRight;
+ QmlGraphicsAnchorLine origHCenter;
+ QmlGraphicsAnchorLine origTop;
+ QmlGraphicsAnchorLine origBottom;
+ QmlGraphicsAnchorLine origVCenter;
+ QmlGraphicsAnchorLine origBaseline;
+
+ QmlGraphicsAnchorLine rewindLeft;
+ QmlGraphicsAnchorLine rewindRight;
+ QmlGraphicsAnchorLine rewindHCenter;
+ QmlGraphicsAnchorLine rewindTop;
+ QmlGraphicsAnchorLine rewindBottom;
+ QmlGraphicsAnchorLine rewindVCenter;
+ QmlGraphicsAnchorLine rewindBaseline;
+
+ qreal fromX;
+ qreal fromY;
+ qreal fromWidth;
+ qreal fromHeight;
+};
+
+/*!
+ \qmlproperty Item AnchorChanges::target
+ This property holds the Item whose anchors will change
+*/
+
+QmlAnchorChanges::QmlAnchorChanges(QObject *parent)
+ : QmlStateOperation(*(new QmlAnchorChangesPrivate), parent)
+{
+}
+
+QmlAnchorChanges::~QmlAnchorChanges()
+{
+}
+
+QmlAnchorChanges::ActionList QmlAnchorChanges::actions()
+{
+ QmlAction a;
+ a.event = this;
+ return ActionList() << a;
+}
+
+QmlGraphicsItem *QmlAnchorChanges::object() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->target;
+}
+
+void QmlAnchorChanges::setObject(QmlGraphicsItem *target)
+{
+ Q_D(QmlAnchorChanges);
+ d->target = target;
+}
+
+QString QmlAnchorChanges::reset() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->resetString;
+}
+
+void QmlAnchorChanges::setReset(const QString &reset)
+{
+ Q_D(QmlAnchorChanges);
+ d->resetString = reset;
+ d->resetList = d->resetString.split(QLatin1Char(','));
+ for (int i = 0; i < d->resetList.count(); ++i)
+ d->resetList[i] = d->resetList.at(i).trimmed();
+}
+
+/*!
+ \qmlproperty AnchorLine AnchorChanges::left
+ \qmlproperty AnchorLine AnchorChanges::right
+ \qmlproperty AnchorLine AnchorChanges::horizontalCenter
+ \qmlproperty AnchorLine AnchorChanges::top
+ \qmlproperty AnchorLine AnchorChanges::bottom
+ \qmlproperty AnchorLine AnchorChanges::verticalCenter
+ \qmlproperty AnchorLine AnchorChanges::baseline
+
+ These properties change the respective anchors of the item.
+*/
+
+QmlGraphicsAnchorLine QmlAnchorChanges::left() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->left;
+}
+
+void QmlAnchorChanges::setLeft(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlAnchorChanges);
+ d->left = edge;
+}
+
+QmlGraphicsAnchorLine QmlAnchorChanges::right() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->right;
+}
+
+void QmlAnchorChanges::setRight(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlAnchorChanges);
+ d->right = edge;
+}
+
+QmlGraphicsAnchorLine QmlAnchorChanges::horizontalCenter() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->horizontalCenter;
+}
+
+void QmlAnchorChanges::setHorizontalCenter(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlAnchorChanges);
+ d->horizontalCenter = edge;
+}
+
+QmlGraphicsAnchorLine QmlAnchorChanges::top() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->top;
+}
+
+void QmlAnchorChanges::setTop(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlAnchorChanges);
+ d->top = edge;
+}
+
+QmlGraphicsAnchorLine QmlAnchorChanges::bottom() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->bottom;
+}
+
+void QmlAnchorChanges::setBottom(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlAnchorChanges);
+ d->bottom = edge;
+}
+
+QmlGraphicsAnchorLine QmlAnchorChanges::verticalCenter() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->verticalCenter;
+}
+
+void QmlAnchorChanges::setVerticalCenter(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlAnchorChanges);
+ d->verticalCenter = edge;
+}
+
+QmlGraphicsAnchorLine QmlAnchorChanges::baseline() const
+{
+ Q_D(const QmlAnchorChanges);
+ return d->baseline;
+}
+
+void QmlAnchorChanges::setBaseline(const QmlGraphicsAnchorLine &edge)
+{
+ Q_D(QmlAnchorChanges);
+ d->baseline = edge;
+}
+
+void QmlAnchorChanges::execute()
+{
+ Q_D(QmlAnchorChanges);
+ if (!d->target)
+ return;
+
+ //set any anchors that have been specified
+ if (d->left.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setLeft(d->left);
+ if (d->right.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setRight(d->right);
+ if (d->horizontalCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setHorizontalCenter(d->horizontalCenter);
+ if (d->top.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setTop(d->top);
+ if (d->bottom.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setBottom(d->bottom);
+ if (d->verticalCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setVerticalCenter(d->verticalCenter);
+ if (d->baseline.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setBaseline(d->baseline);
+}
+
+bool QmlAnchorChanges::isReversable()
+{
+ return true;
+}
+
+void QmlAnchorChanges::reverse()
+{
+ Q_D(QmlAnchorChanges);
+ if (!d->target)
+ return;
+
+ //restore previous anchors
+ if (d->origLeft.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setLeft(d->origLeft);
+ if (d->origRight.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setRight(d->origRight);
+ if (d->origHCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setHorizontalCenter(d->origHCenter);
+ if (d->origTop.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setTop(d->origTop);
+ if (d->origBottom.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setBottom(d->origBottom);
+ if (d->origVCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setVerticalCenter(d->origVCenter);
+ if (d->origBaseline.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setBaseline(d->origBaseline);
+}
+
+QString QmlAnchorChanges::typeName() const
+{
+ return QLatin1String("AnchorChanges");
+}
+
+QList<QmlAction> QmlAnchorChanges::extraActions()
+{
+ Q_D(QmlAnchorChanges);
+ QList<QmlAction> extra;
+
+ //### try to be smarter about which ones we add.
+ // or short-circuit later on if they haven't actually changed.
+ // we shouldn't set explicit width if there wasn't one before.
+ if (d->target) {
+ QmlAction a;
+ a.fromValue = d->fromX;
+ a.property = QmlMetaProperty(d->target, QLatin1String("x"));
+ extra << a;
+
+ a.fromValue = d->fromY;
+ a.property = QmlMetaProperty(d->target, QLatin1String("y"));
+ extra << a;
+
+ a.fromValue = d->fromWidth;
+ a.property = QmlMetaProperty(d->target, QLatin1String("width"));
+ extra << a;
+
+ a.fromValue = d->fromHeight;
+ a.property = QmlMetaProperty(d->target, QLatin1String("height"));
+ extra << a;
+ }
+
+ return extra;
+}
+
+bool QmlAnchorChanges::changesBindings()
+{
+ return true;
+}
+
+void QmlAnchorChanges::saveOriginals()
+{
+ Q_D(QmlAnchorChanges);
+ d->origLeft = d->target->anchors()->left();
+ d->origRight = d->target->anchors()->right();
+ d->origHCenter = d->target->anchors()->horizontalCenter();
+ d->origTop = d->target->anchors()->top();
+ d->origBottom = d->target->anchors()->bottom();
+ d->origVCenter = d->target->anchors()->verticalCenter();
+ d->origBaseline = d->target->anchors()->baseline();
+
+ saveCurrentValues();
+}
+
+void QmlAnchorChanges::clearForwardBindings()
+{
+ Q_D(QmlAnchorChanges);
+ d->fromX = d->target->x();
+ d->fromY = d->target->y();
+ d->fromWidth = d->target->width();
+ d->fromHeight = d->target->height();
+
+ //reset any anchors that have been specified
+ if (d->resetList.contains(QLatin1String("left")))
+ d->target->anchors()->resetLeft();
+ if (d->resetList.contains(QLatin1String("right")))
+ d->target->anchors()->resetRight();
+ if (d->resetList.contains(QLatin1String("horizontalCenter")))
+ d->target->anchors()->resetHorizontalCenter();
+ if (d->resetList.contains(QLatin1String("top")))
+ d->target->anchors()->resetTop();
+ if (d->resetList.contains(QLatin1String("bottom")))
+ d->target->anchors()->resetBottom();
+ if (d->resetList.contains(QLatin1String("verticalCenter")))
+ d->target->anchors()->resetVerticalCenter();
+ if (d->resetList.contains(QLatin1String("baseline")))
+ d->target->anchors()->resetBaseline();
+
+ //reset any anchors that we'll be setting in the state
+ if (d->left.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetLeft();
+ if (d->right.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetRight();
+ if (d->horizontalCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetHorizontalCenter();
+ if (d->top.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetTop();
+ if (d->bottom.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetBottom();
+ if (d->verticalCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetVerticalCenter();
+ if (d->baseline.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetBaseline();
+}
+
+void QmlAnchorChanges::clearReverseBindings()
+{
+ Q_D(QmlAnchorChanges);
+ d->fromX = d->target->x();
+ d->fromY = d->target->y();
+ d->fromWidth = d->target->width();
+ d->fromHeight = d->target->height();
+
+ //reset any anchors that were set in the state
+ if (d->left.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetLeft();
+ if (d->right.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetRight();
+ if (d->horizontalCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetHorizontalCenter();
+ if (d->top.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetTop();
+ if (d->bottom.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetBottom();
+ if (d->verticalCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetVerticalCenter();
+ if (d->baseline.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetBaseline();
+
+ //reset any anchors that were set in the original state
+ if (d->origLeft.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetLeft();
+ if (d->origRight.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetRight();
+ if (d->origHCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetHorizontalCenter();
+ if (d->origTop.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetTop();
+ if (d->origBottom.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetBottom();
+ if (d->origVCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetVerticalCenter();
+ if (d->origBaseline.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->resetBaseline();
+}
+
+bool QmlAnchorChanges::override(QmlActionEvent*other)
+{
+ if (other->typeName() != QLatin1String("AnchorChanges"))
+ return false;
+ if (static_cast<QmlActionEvent*>(this) == other)
+ return true;
+ if (static_cast<QmlAnchorChanges*>(other)->object() == object())
+ return true;
+ return false;
+}
+
+void QmlAnchorChanges::rewind()
+{
+ Q_D(QmlAnchorChanges);
+ if (!d->target)
+ return;
+
+ //restore previous anchors
+ if (d->rewindLeft.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setLeft(d->rewindLeft);
+ if (d->rewindRight.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setRight(d->rewindRight);
+ if (d->rewindHCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setHorizontalCenter(d->rewindHCenter);
+ if (d->rewindTop.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setTop(d->rewindTop);
+ if (d->rewindBottom.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setBottom(d->rewindBottom);
+ if (d->rewindVCenter.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setVerticalCenter(d->rewindVCenter);
+ if (d->rewindBaseline.anchorLine != QmlGraphicsAnchorLine::Invalid)
+ d->target->anchors()->setBaseline(d->rewindBaseline);
+}
+
+void QmlAnchorChanges::saveCurrentValues()
+{
+ Q_D(QmlAnchorChanges);
+ d->rewindLeft = d->target->anchors()->left();
+ d->rewindRight = d->target->anchors()->right();
+ d->rewindHCenter = d->target->anchors()->horizontalCenter();
+ d->rewindTop = d->target->anchors()->top();
+ d->rewindBottom = d->target->anchors()->bottom();
+ d->rewindVCenter = d->target->anchors()->verticalCenter();
+ d->rewindBaseline = d->target->anchors()->baseline();
+}
+
+#include <qmlstateoperations.moc>
+#include <moc_qmlstateoperations_p.cpp>
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/util/qmlstateoperations_p.h b/src/declarative/util/qmlstateoperations_p.h
new file mode 100644
index 0000000..1a9f76f
--- /dev/null
+++ b/src/declarative/util/qmlstateoperations_p.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATEOPERATIONS_H
+#define QMLSTATEOPERATIONS_H
+
+#include "qmlstate_p.h"
+
+#include <qmlgraphicsitem.h>
+#include "private/qmlgraphicsanchors_p.h"
+#include <qmlscriptstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlParentChangePrivate;
+class Q_DECLARATIVE_EXPORT QmlParentChange : public QmlStateOperation, public QmlActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlParentChange)
+
+ Q_PROPERTY(QmlGraphicsItem *target READ object WRITE setObject)
+ Q_PROPERTY(QmlGraphicsItem *parent READ parent WRITE setParent)
+public:
+ QmlParentChange(QObject *parent=0);
+ ~QmlParentChange();
+
+ QmlGraphicsItem *object() const;
+ void setObject(QmlGraphicsItem *);
+
+ QmlGraphicsItem *parent() const;
+ void setParent(QmlGraphicsItem *);
+
+ virtual ActionList actions();
+
+ virtual void saveOriginals();
+ virtual void execute();
+ virtual bool isReversable();
+ virtual void reverse();
+ virtual QString typeName() const;
+ virtual bool override(QmlActionEvent*other);
+ virtual void rewind();
+ virtual void saveCurrentValues();
+};
+
+class QmlStateChangeScriptPrivate;
+class Q_DECLARATIVE_EXPORT QmlStateChangeScript : public QmlStateOperation, public QmlActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlStateChangeScript)
+
+ Q_PROPERTY(QmlScriptString script READ script WRITE setScript)
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ QmlStateChangeScript(QObject *parent=0);
+ ~QmlStateChangeScript();
+
+ virtual ActionList actions();
+
+ virtual QString typeName() const;
+
+ QmlScriptString script() const;
+ void setScript(const QmlScriptString &);
+
+ QString name() const;
+ void setName(const QString &);
+
+ virtual void execute();
+};
+
+class QmlAnchorChangesPrivate;
+class Q_DECLARATIVE_EXPORT QmlAnchorChanges : public QmlStateOperation, public QmlActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnchorChanges)
+
+ Q_PROPERTY(QmlGraphicsItem *target READ object WRITE setObject)
+ Q_PROPERTY(QString reset READ reset WRITE setReset)
+ Q_PROPERTY(QmlGraphicsAnchorLine left READ left WRITE setLeft)
+ Q_PROPERTY(QmlGraphicsAnchorLine right READ right WRITE setRight)
+ Q_PROPERTY(QmlGraphicsAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter)
+ Q_PROPERTY(QmlGraphicsAnchorLine top READ top WRITE setTop)
+ Q_PROPERTY(QmlGraphicsAnchorLine bottom READ bottom WRITE setBottom)
+ Q_PROPERTY(QmlGraphicsAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter)
+ Q_PROPERTY(QmlGraphicsAnchorLine baseline READ baseline WRITE setBaseline)
+
+public:
+ QmlAnchorChanges(QObject *parent=0);
+ ~QmlAnchorChanges();
+
+ virtual ActionList actions();
+
+ QmlGraphicsItem *object() const;
+ void setObject(QmlGraphicsItem *);
+
+ QString reset() const;
+ void setReset(const QString &);
+
+ QmlGraphicsAnchorLine left() const;
+ void setLeft(const QmlGraphicsAnchorLine &edge);
+
+ QmlGraphicsAnchorLine right() const;
+ void setRight(const QmlGraphicsAnchorLine &edge);
+
+ QmlGraphicsAnchorLine horizontalCenter() const;
+ void setHorizontalCenter(const QmlGraphicsAnchorLine &edge);
+
+ QmlGraphicsAnchorLine top() const;
+ void setTop(const QmlGraphicsAnchorLine &edge);
+
+ QmlGraphicsAnchorLine bottom() const;
+ void setBottom(const QmlGraphicsAnchorLine &edge);
+
+ QmlGraphicsAnchorLine verticalCenter() const;
+ void setVerticalCenter(const QmlGraphicsAnchorLine &edge);
+
+ QmlGraphicsAnchorLine baseline() const;
+ void setBaseline(const QmlGraphicsAnchorLine &edge);
+
+ virtual void execute();
+ virtual bool isReversable();
+ virtual void reverse();
+ virtual QString typeName() const;
+ virtual bool override(QmlActionEvent*other);
+ virtual QList<QmlAction> extraActions();
+ virtual bool changesBindings();
+ virtual void saveOriginals();
+ virtual void clearForwardBindings();
+ virtual void clearReverseBindings();
+ virtual void rewind();
+ virtual void saveCurrentValues();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlParentChange)
+QML_DECLARE_TYPE(QmlStateChangeScript)
+QML_DECLARE_TYPE(QmlAnchorChanges)
+
+QT_END_HEADER
+
+#endif // QMLSTATEOPERATIONS_H
diff --git a/src/declarative/util/qmlstyledtext.cpp b/src/declarative/util/qmlstyledtext.cpp
new file mode 100644
index 0000000..36b5e49
--- /dev/null
+++ b/src/declarative/util/qmlstyledtext.cpp
@@ -0,0 +1,343 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QStack>
+#include <QVector>
+#include <QPainter>
+#include <QTextLayout>
+#include <QDebug>
+#include <qmath.h>
+#include "qmlstyledtext_p.h"
+
+/*
+ QmlStyledText supports few tags:
+
+ <b></b> - bold
+ <i></i> - italic
+ <br> - new line
+ <font color="color_name" size="1-7"></font>
+
+ The opening and closing tags must be correctly nested.
+*/
+
+class QmlStyledTextPrivate
+{
+public:
+ QmlStyledTextPrivate(const QString &t, QTextLayout &l) : text(t), layout(l), baseFont(layout.font()) {}
+
+ void parse();
+ bool parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format);
+ bool parseCloseTag(const QChar *&ch, const QString &textIn);
+ void parseEntity(const QChar *&ch, const QString &textIn, QString &textOut);
+ bool parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
+ QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn);
+ QStringRef parseValue(const QChar *&ch, const QString &textIn);
+
+ inline void skipSpace(const QChar *&ch) {
+ while (ch->isSpace() && !ch->isNull())
+ ++ch;
+ }
+
+ QString text;
+ QTextLayout &layout;
+ QFont baseFont;
+
+ static const QChar lessThan;
+ static const QChar greaterThan;
+ static const QChar equals;
+ static const QChar singleQuote;
+ static const QChar doubleQuote;
+ static const QChar slash;
+ static const QChar ampersand;
+};
+
+const QChar QmlStyledTextPrivate::lessThan(QLatin1Char('<'));
+const QChar QmlStyledTextPrivate::greaterThan(QLatin1Char('>'));
+const QChar QmlStyledTextPrivate::equals(QLatin1Char('='));
+const QChar QmlStyledTextPrivate::singleQuote(QLatin1Char('\''));
+const QChar QmlStyledTextPrivate::doubleQuote(QLatin1Char('\"'));
+const QChar QmlStyledTextPrivate::slash(QLatin1Char('/'));
+const QChar QmlStyledTextPrivate::ampersand(QLatin1Char('&'));
+
+QmlStyledText::QmlStyledText(const QString &string, QTextLayout &layout)
+: d(new QmlStyledTextPrivate(string, layout))
+{
+}
+
+QmlStyledText::~QmlStyledText()
+{
+ delete d;
+}
+
+void QmlStyledText::parse(const QString &string, QTextLayout &layout)
+{
+ QmlStyledText styledText(string, layout);
+ styledText.d->parse();
+}
+
+void QmlStyledTextPrivate::parse()
+{
+ QList<QTextLayout::FormatRange> ranges;
+ QStack<QTextCharFormat> formatStack;
+
+ QString drawText;
+ drawText.reserve(text.count());
+
+ int textStart = 0;
+ int textLength = 0;
+ int rangeStart = 0;
+ const QChar *ch = text.constData();
+ while (!ch->isNull()) {
+ if (*ch == lessThan) {
+ if (textLength)
+ drawText.append(QStringRef(&text, textStart, textLength));
+ if (rangeStart != drawText.length() && formatStack.count()) {
+ QTextLayout::FormatRange formatRange;
+ formatRange.format = formatStack.top();
+ formatRange.start = rangeStart;
+ formatRange.length = drawText.length() - rangeStart;
+ ranges.append(formatRange);
+ }
+ rangeStart = drawText.length();
+ ++ch;
+ if (*ch == slash) {
+ ++ch;
+ if (parseCloseTag(ch, text))
+ formatStack.pop();
+ } else {
+ QTextCharFormat format;
+ if (formatStack.count())
+ format = formatStack.top();
+ else
+ format.setFont(baseFont);
+ if (parseTag(ch, text, drawText, format))
+ formatStack.push(format);
+ }
+ textStart = ch - text.constData() + 1;
+ textLength = 0;
+ } else if (*ch == ampersand) {
+ ++ch;
+ drawText.append(QStringRef(&text, textStart, textLength));
+ parseEntity(ch, text, drawText);
+ textStart = ch - text.constData() + 1;
+ textLength = 0;
+ } else {
+ ++textLength;
+ }
+ ++ch;
+ }
+ if (textLength)
+ drawText.append(QStringRef(&text, textStart, textLength));
+ if (rangeStart != drawText.length() && formatStack.count()) {
+ QTextLayout::FormatRange formatRange;
+ formatRange.format = formatStack.top();
+ formatRange.start = rangeStart;
+ formatRange.length = drawText.length() - rangeStart;
+ ranges.append(formatRange);
+ }
+
+ layout.setText(drawText);
+ layout.setAdditionalFormats(ranges);
+}
+
+bool QmlStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format)
+{
+ skipSpace(ch);
+
+ int tagStart = ch - textIn.constData();
+ int tagLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == greaterThan) {
+ QStringRef tag(&textIn, tagStart, tagLength);
+ const QChar char0 = tag.at(0);
+ if (char0 == QLatin1Char('b')) {
+ if (tagLength == 1) {
+ format.setFontWeight(QFont::Bold);
+ return true;
+ } else if (tagLength == 2 && tag.at(1) == QLatin1Char('r')) {
+ textOut.append(QChar(QChar::LineSeparator));
+ return true;
+ }
+ } else if (char0 == QLatin1Char('i')) {
+ if (tagLength == 1) {
+ format.setFontItalic(true);
+ return true;
+ }
+ }
+ return false;
+ } else if (ch->isSpace()) {
+ // may have params.
+ QStringRef tag(&textIn, tagStart, tagLength);
+ if (tag == QLatin1String("font"))
+ return parseFontAttributes(ch, textIn, format);
+ if (*ch == greaterThan || ch->isNull())
+ continue;
+ } else if (*ch != slash){
+ tagLength++;
+ }
+ ++ch;
+ }
+
+ return false;
+}
+
+bool QmlStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn)
+{
+ skipSpace(ch);
+
+ int tagStart = ch - textIn.constData();
+ int tagLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == greaterThan) {
+ QStringRef tag(&textIn, tagStart, tagLength);
+ const QChar char0 = tag.at(0);
+ if (char0 == QLatin1Char('b')) {
+ if (tagLength == 1)
+ return true;
+ else if (tag.at(1) == QLatin1Char('r') && tagLength == 2)
+ return true;
+ } else if (char0 == QLatin1Char('i')) {
+ if (tagLength == 1)
+ return true;
+ } else if (tag == QLatin1String("font")) {
+ return true;
+ }
+ return false;
+ } else if (!ch->isSpace()){
+ tagLength++;
+ }
+ ++ch;
+ }
+
+ return false;
+}
+
+void QmlStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textIn, QString &textOut)
+{
+ int entityStart = ch - textIn.constData();
+ int entityLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == QLatin1Char(';')) {
+ QStringRef entity(&textIn, entityStart, entityLength);
+ if (entity == QLatin1String("gt"))
+ textOut += QChar(62);
+ else if (entity == QLatin1String("lt"))
+ textOut += QChar(60);
+ else if (entity == QLatin1String("amp"))
+ textOut += QChar(38);
+ return;
+ }
+ ++entityLength;
+ ++ch;
+ }
+}
+
+bool QmlStyledTextPrivate::parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format)
+{
+ bool valid = false;
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ if (attr.first == QLatin1String("color")) {
+ valid = true;
+ format.setForeground(QColor(attr.second.toString()));
+ } else if (attr.first == QLatin1String("size")) {
+ valid = true;
+ int size = attr.second.toString().toInt();
+ if (attr.second.at(0) == QLatin1Char('-') || attr.second.at(0) == QLatin1Char('+'))
+ size += 3;
+ if (size >= 1 && size <= 7) {
+ static const qreal scaling[] = { 0.7, 0.8, 1.0, 1.2, 1.5, 2.0, 2.4 };
+ format.setFontPointSize(baseFont.pointSize() * scaling[size-1]);
+ }
+ }
+ } while (!ch->isNull() && !attr.first.isEmpty());
+
+ return valid;
+}
+
+QPair<QStringRef,QStringRef> QmlStyledTextPrivate::parseAttribute(const QChar *&ch, const QString &textIn)
+{
+ skipSpace(ch);
+
+ int attrStart = ch - textIn.constData();
+ int attrLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == greaterThan) {
+ break;
+ } else if (*ch == equals) {
+ ++ch;
+ if (*ch != singleQuote && *ch != doubleQuote) {
+ while (*ch != greaterThan && !ch->isNull())
+ ++ch;
+ break;
+ }
+ ++ch;
+ if (!attrLength)
+ break;
+ QStringRef attr(&textIn, attrStart, attrLength);
+ QStringRef val = parseValue(ch, textIn);
+ if (!val.isEmpty())
+ return QPair<QStringRef,QStringRef>(attr,val);
+ break;
+ } else {
+ ++attrLength;
+ }
+ ++ch;
+ }
+
+ return QPair<QStringRef,QStringRef>();
+}
+
+QStringRef QmlStyledTextPrivate::parseValue(const QChar *&ch, const QString &textIn)
+{
+ int valStart = ch - textIn.constData();
+ int valLength = 0;
+ while (*ch != singleQuote && *ch != doubleQuote && !ch->isNull()) {
+ ++valLength;
+ ++ch;
+ }
+ if (ch->isNull())
+ return QStringRef();
+ ++ch; // skip quote
+
+ return QStringRef(&textIn, valStart, valLength);
+}
diff --git a/src/declarative/util/qmlstyledtext_p.h b/src/declarative/util/qmlstyledtext_p.h
new file mode 100644
index 0000000..0cfb43e
--- /dev/null
+++ b/src/declarative/util/qmlstyledtext_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTYLEDTEXT_H
+#define QMLSTYLEDTEXT_H
+
+#include <QSizeF>
+
+class QPainter;
+class QPointF;
+class QString;
+class QmlStyledTextPrivate;
+class Q_DECLARATIVE_EXPORT QmlStyledText
+{
+public:
+ static void parse(const QString &string, QTextLayout &layout);
+
+private:
+ QmlStyledText(const QString &string, QTextLayout &layout);
+ ~QmlStyledText();
+
+ QmlStyledTextPrivate *d;
+};
+
+#endif
diff --git a/src/declarative/util/qmlsystempalette.cpp b/src/declarative/util/qmlsystempalette.cpp
new file mode 100644
index 0000000..39d8f3e
--- /dev/null
+++ b/src/declarative/util/qmlsystempalette.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlsystempalette_p.h"
+
+#include <QApplication>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlSystemPalettePrivate : public QObjectPrivate
+{
+public:
+ QPalette palette;
+ QPalette::ColorGroup group;
+};
+
+QML_DEFINE_TYPE(Qt,4,6,SystemPalette,QmlSystemPalette)
+
+/*!
+ \qmlclass SystemPalette QmlSystemPalette
+ \ingroup group_utility
+ \brief The SystemPalette item gives access to the Qt palettes.
+ \sa QPalette
+
+ Example:
+ \qml
+ SystemPalette { id: myPalette; colorGroup: Qt.Active }
+
+ Rectangle {
+ width: 640; height: 480
+ color: myPalette.window
+ Text {
+ anchors.fill: parent
+ text: "Hello!"; color: myPalette.windowText
+ }
+ }
+ \endqml
+*/
+QmlSystemPalette::QmlSystemPalette(QObject *parent)
+ : QObject(*(new QmlSystemPalettePrivate), parent)
+{
+ Q_D(QmlSystemPalette);
+ d->palette = QApplication::palette();
+ d->group = QPalette::Active;
+ qApp->installEventFilter(this);
+}
+
+QmlSystemPalette::~QmlSystemPalette()
+{
+}
+
+/*!
+ \qmlproperty color SystemPalette::window
+ The window (general background) color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::window() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Window);
+}
+
+/*!
+ \qmlproperty color SystemPalette::windowText
+ The window text (general foreground) color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::windowText() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::WindowText);
+}
+
+/*!
+ \qmlproperty color SystemPalette::base
+ The base color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::base() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Base);
+}
+
+/*!
+ \qmlproperty color SystemPalette::text
+ The text color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::text() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Text);
+}
+
+/*!
+ \qmlproperty color SystemPalette::alternateBase
+ The alternate base color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::alternateBase() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::AlternateBase);
+}
+
+/*!
+ \qmlproperty color SystemPalette::button
+ The button color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::button() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Button);
+}
+
+/*!
+ \qmlproperty color SystemPalette::buttonText
+ The button text foreground color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::buttonText() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::ButtonText);
+}
+
+/*!
+ \qmlproperty color SystemPalette::light
+ The light color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::light() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Light);
+}
+
+/*!
+ \qmlproperty color SystemPalette::midlight
+ The midlight color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::midlight() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Midlight);
+}
+
+/*!
+ \qmlproperty color SystemPalette::dark
+ The dark color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::dark() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Dark);
+}
+
+/*!
+ \qmlproperty color SystemPalette::mid
+ The mid color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::mid() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Mid);
+}
+
+/*!
+ \qmlproperty color SystemPalette::shadow
+ The shadow color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::shadow() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Shadow);
+}
+
+/*!
+ \qmlproperty color SystemPalette::highlight
+ The highlight color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::highlight() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::Highlight);
+}
+
+/*!
+ \qmlproperty color SystemPalette::highlightedText
+ The highlighted text color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QmlSystemPalette::highlightedText() const
+{
+ Q_D(const QmlSystemPalette);
+ return d->palette.color(d->group, QPalette::HighlightedText);
+}
+
+/*!
+ \qmlproperty QmlSystemPalette::ColorGroup SystemPalette::colorGroup
+
+ The color group of the palette. It can be Active, Inactive or Disabled.
+ Active is the default.
+
+ \sa QPalette::ColorGroup
+*/
+QmlSystemPalette::ColorGroup QmlSystemPalette::colorGroup() const
+{
+ Q_D(const QmlSystemPalette);
+ return (QmlSystemPalette::ColorGroup)d->group;
+}
+
+void QmlSystemPalette::setColorGroup(QmlSystemPalette::ColorGroup colorGroup)
+{
+ Q_D(QmlSystemPalette);
+ d->group = (QPalette::ColorGroup)colorGroup;
+ emit paletteChanged();
+}
+
+bool QmlSystemPalette::eventFilter(QObject *watched, QEvent *event)
+{
+ if (watched == qApp) {
+ if (event->type() == QEvent::ApplicationPaletteChange) {
+ QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
+ return false;
+ }
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+bool QmlSystemPalette::event(QEvent *event)
+{
+ Q_D(QmlSystemPalette);
+ if (event->type() == QEvent::ApplicationPaletteChange) {
+ d->palette = QApplication::palette();
+ emit paletteChanged();
+ return true;
+ }
+ return QObject::event(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlsystempalette_p.h b/src/declarative/util/qmlsystempalette_p.h
new file mode 100644
index 0000000..7c39d4a
--- /dev/null
+++ b/src/declarative/util/qmlsystempalette_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSYSTEMPALETTE_H
+#define QMLSYSTEMPALETTE_H
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+#include <QPalette>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlSystemPalettePrivate;
+class Q_DECLARATIVE_EXPORT QmlSystemPalette : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(ColorGroup)
+ Q_DECLARE_PRIVATE(QmlSystemPalette)
+
+ Q_PROPERTY(QmlSystemPalette::ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY paletteChanged)
+ Q_PROPERTY(QColor window READ window NOTIFY paletteChanged)
+ Q_PROPERTY(QColor windowText READ windowText NOTIFY paletteChanged)
+ Q_PROPERTY(QColor base READ base NOTIFY paletteChanged)
+ Q_PROPERTY(QColor text READ text NOTIFY paletteChanged)
+ Q_PROPERTY(QColor alternateBase READ alternateBase NOTIFY paletteChanged)
+ Q_PROPERTY(QColor button READ button NOTIFY paletteChanged)
+ Q_PROPERTY(QColor buttonText READ buttonText NOTIFY paletteChanged)
+ Q_PROPERTY(QColor light READ light NOTIFY paletteChanged)
+ Q_PROPERTY(QColor midlight READ midlight NOTIFY paletteChanged)
+ Q_PROPERTY(QColor dark READ dark NOTIFY paletteChanged)
+ Q_PROPERTY(QColor mid READ mid NOTIFY paletteChanged)
+ Q_PROPERTY(QColor shadow READ shadow NOTIFY paletteChanged)
+ Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged)
+ Q_PROPERTY(QColor highlightedText READ highlightedText NOTIFY paletteChanged)
+
+public:
+ QmlSystemPalette(QObject *parent=0);
+ ~QmlSystemPalette();
+
+ enum ColorGroup { Active = QPalette::Active, Inactive = QPalette::Inactive, Disabled = QPalette::Disabled };
+
+ QColor window() const;
+ QColor windowText() const;
+
+ QColor base() const;
+ QColor text() const;
+ QColor alternateBase() const;
+
+ QColor button() const;
+ QColor buttonText() const;
+
+ QColor light() const;
+ QColor midlight() const;
+ QColor dark() const;
+ QColor mid() const;
+ QColor shadow() const;
+
+ QColor highlight() const;
+ QColor highlightedText() const;
+
+ QmlSystemPalette::ColorGroup colorGroup() const;
+ void setColorGroup(QmlSystemPalette::ColorGroup);
+
+Q_SIGNALS:
+ void paletteChanged();
+
+private:
+ bool eventFilter(QObject *watched, QEvent *event);
+ bool event(QEvent *event);
+
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlSystemPalette)
+
+QT_END_HEADER
+
+#endif // QMLSYSTEMPALETTE_H
diff --git a/src/declarative/util/qmltimeline.cpp b/src/declarative/util/qmltimeline.cpp
new file mode 100644
index 0000000..130e02d
--- /dev/null
+++ b/src/declarative/util/qmltimeline.cpp
@@ -0,0 +1,941 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltimeline_p_p.h"
+
+#include <QDebug>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+#include <QEvent>
+#include <QCoreApplication>
+#include <QEasingCurve>
+#include <QTime>
+
+QT_BEGIN_NAMESPACE
+
+struct Update {
+ Update(QmlTimeLineValue *_g, qreal _v)
+ : g(_g), v(_v) {}
+ Update(const QmlTimeLineEvent &_e)
+ : g(0), v(0), e(_e) {}
+
+ QmlTimeLineValue *g;
+ qreal v;
+ QmlTimeLineEvent e;
+};
+
+struct QmlTimeLinePrivate
+{
+ QmlTimeLinePrivate(QmlTimeLine *);
+
+ struct Op {
+ enum Type {
+ Pause,
+ Set,
+ Move,
+ MoveBy,
+ Accel,
+ AccelDistance,
+ Execute
+ };
+ Op() {}
+ Op(Type t, int l, qreal v, qreal v2, int o,
+ const QmlTimeLineEvent &ev = QmlTimeLineEvent(), const QEasingCurve &es = QEasingCurve())
+ : type(t), length(l), value(v), value2(v2), order(o), event(ev),
+ easing(es) {}
+ Op(const Op &o)
+ : type(o.type), length(o.length), value(o.value), value2(o.value2),
+ order(o.order), event(o.event), easing(o.easing) {}
+ Op &operator=(const Op &o) {
+ type = o.type; length = o.length; value = o.value;
+ value2 = o.value2; order = o.order; event = o.event;
+ easing = o.easing;
+ return *this;
+ }
+
+ Type type;
+ int length;
+ qreal value;
+ qreal value2;
+
+ int order;
+ QmlTimeLineEvent event;
+ QEasingCurve easing;
+ };
+ struct TimeLine
+ {
+ TimeLine() : length(0), consumedOpLength(0), base(0.) {}
+ QList<Op> ops;
+ int length;
+ int consumedOpLength;
+ qreal base;
+ };
+
+ int length;
+ int syncPoint;
+ typedef QHash<QmlTimeLineObject *, TimeLine> Ops;
+ Ops ops;
+ QmlTimeLine *q;
+
+ void add(QmlTimeLineObject &, const Op &);
+ qreal value(const Op &op, int time, qreal base, bool *) const;
+
+ int advance(int);
+
+ bool clockRunning;
+ int prevTime;
+
+ int order;
+
+ QmlTimeLine::SyncMode syncMode;
+ int syncAdj;
+ QList<QPair<int, Update> > *updateQueue;
+};
+
+QmlTimeLinePrivate::QmlTimeLinePrivate(QmlTimeLine *parent)
+: length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(QmlTimeLine::LocalSync), syncAdj(0), updateQueue(0)
+{
+}
+
+void QmlTimeLinePrivate::add(QmlTimeLineObject &g, const Op &o)
+{
+ if (g._t && g._t != q) {
+ qWarning() << "QmlTimeLine: Cannot modify a QmlTimeLineValue owned by"
+ << "another timeline.";
+ return;
+ }
+ g._t = q;
+
+ Ops::Iterator iter = ops.find(&g);
+ if (iter == ops.end()) {
+ iter = ops.insert(&g, TimeLine());
+ if (syncPoint > 0)
+ q->pause(g, syncPoint);
+ }
+ if (!iter->ops.isEmpty() &&
+ o.type == Op::Pause &&
+ iter->ops.last().type == Op::Pause) {
+ iter->ops.last().length += o.length;
+ iter->length += o.length;
+ } else {
+ iter->ops.append(o);
+ iter->length += o.length;
+ }
+
+ if (iter->length > length)
+ length = iter->length;
+
+ if (!clockRunning) {
+ q->stop();
+ prevTime = 0;
+ clockRunning = true;
+
+ if (syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ q->start();
+/* q->tick(0);
+ if (syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ */
+ }
+}
+
+qreal QmlTimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
+{
+ Q_ASSERT(time >= 0);
+ Q_ASSERT(time <= op.length);
+ *changed = true;
+
+ switch(op.type) {
+ case Op::Pause:
+ *changed = false;
+ return base;
+ case Op::Set:
+ return op.value;
+ case Op::Move:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return op.value;
+ } else {
+ qreal delta = op.value - base;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::MoveBy:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value;
+ } else {
+ qreal delta = op.value;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::Accel:
+ if (time == 0) {
+ return base;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal delta = op.value * t + 0.5f * op.value2 * t * t;
+ return base + delta;
+ }
+ case Op::AccelDistance:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value2;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
+ qreal delta = op.value * t + 0.5f * accel * t * t;
+ return base + delta;
+
+ }
+ case Op::Execute:
+ op.event.execute();
+ *changed = false;
+ return -1;
+ }
+
+ return base;
+}
+
+/*!
+ \internal
+ \class QmlTimeLine
+ \ingroup group_animation
+ \brief The QmlTimeLine class provides a timeline for controlling animations.
+
+ QmlTimeLine is similar to QTimeLine except:
+ \list
+ \i It updates QmlTimeLineValue instances directly, rather than maintaining a single
+ current value.
+
+ For example, the following animates a simple value over 200 milliseconds:
+ \code
+ QmlTimeLineValue v(<starting value>);
+ QmlTimeLine tl;
+ tl.move(v, 100., 200);
+ tl.start()
+ \endcode
+
+ If your program needs to know when values are changed, it can either
+ connect to the QmlTimeLine's updated() signal, or inherit from QmlTimeLineValue
+ and reimplement the QmlTimeLineValue::setValue() method.
+
+ \i Supports multiple QmlTimeLineValue, arbitrary start and end values and allows
+ animations to be strung together for more complex effects.
+
+ For example, the following animation moves the x and y coordinates of
+ an object from wherever they are to the position (100, 100) in 50
+ milliseconds and then further animates them to (100, 200) in 50
+ milliseconds:
+
+ \code
+ QmlTimeLineValue x(<starting value>);
+ QmlTimeLineValue y(<starting value>);
+
+ QmlTimeLine tl;
+ tl.start();
+
+ tl.move(x, 100., 50);
+ tl.move(y, 100., 50);
+ tl.move(y, 200., 50);
+ \endcode
+
+ \i All QmlTimeLine instances share a single, synchronized clock.
+
+ Actions scheduled within the same event loop tick are scheduled
+ synchronously against each other, regardless of the wall time between the
+ scheduling. Synchronized scheduling applies both to within the same
+ QmlTimeLine and across separate QmlTimeLine's within the same process.
+
+ \endlist
+
+ Currently easing functions are not supported.
+*/
+
+
+/*!
+ Construct a new QmlTimeLine with the specified \a parent.
+*/
+QmlTimeLine::QmlTimeLine(QObject *parent)
+: QAbstractAnimation(parent)
+{
+ d = new QmlTimeLinePrivate(this);
+}
+
+/*!
+ Destroys the time line. Any inprogress animations are canceled, but not
+ completed.
+*/
+QmlTimeLine::~QmlTimeLine()
+{
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ iter.key()->_t = 0;
+
+ delete d; d = 0;
+}
+
+/*!
+ \enum QmlTimeLine::SyncMode
+ */
+
+/*!
+ Return the timeline's synchronization mode.
+ */
+QmlTimeLine::SyncMode QmlTimeLine::syncMode() const
+{
+ return d->syncMode;
+}
+
+/*!
+ Set the timeline's synchronization mode to \a syncMode.
+ */
+void QmlTimeLine::setSyncMode(SyncMode syncMode)
+{
+ d->syncMode = syncMode;
+}
+
+/*!
+ Pause \a obj for \a time milliseconds.
+*/
+void QmlTimeLine::pause(QmlTimeLineObject &obj, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
+ d->add(obj, op);
+}
+
+/*!
+ Execute the \a event.
+ */
+void QmlTimeLine::execute(const QmlTimeLineEvent &event)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, event);
+ d->add(*event.eventObject(), op);
+}
+
+/*!
+ Set the \a value of \a timeLineValue.
+*/
+void QmlTimeLine::set(QmlTimeLineValue &timeLineValue, qreal value)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Set, 0, value, 0., d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate. Although the \a acceleration is technically
+ a deceleration, it should always be positive. The QmlTimeLine will ensure
+ that the deceleration is in the opposite direction to the initial velocity.
+*/
+int QmlTimeLine::accel(QmlTimeLineValue &timeLineValue, qreal velocity, qreal acceleration)
+{
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ \overload
+
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate over a maximum distance of maxDistance.
+
+ If necessary, QmlTimeLine will reduce the acceleration to ensure that the
+ entire operation does not require a move of more than \a maxDistance.
+ \a maxDistance should always be positive.
+*/
+int QmlTimeLine::accel(QmlTimeLineValue &timeLineValue, qreal velocity, qreal acceleration, qreal maxDistance)
+{
+ Q_ASSERT(acceleration >= 0.0f && maxDistance >= 0.0f);
+
+ qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
+ if (maxAccel > acceleration)
+ acceleration = maxAccel;
+
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero over the given
+ \a distance. This is like accel(), but the QmlTimeLine calculates the exact
+ deceleration to use.
+
+ \a distance should be positive.
+*/
+int QmlTimeLine::accelDistance(QmlTimeLineValue &timeLineValue, qreal velocity, qreal distance)
+{
+ if (distance == 0.0f || velocity == 0.0f)
+ return -1;
+ Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
+
+ int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value to the given
+ \a destination value over \a time milliseconds.
+*/
+void QmlTimeLine::move(QmlTimeLineValue &timeLineValue, qreal destination, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value to the given \a destination
+ value over \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::move(QmlTimeLineValue &timeLineValue, qreal destination, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, QmlTimeLineEvent(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value by the \a change amount
+ over \a time milliseconds.
+*/
+void QmlTimeLine::moveBy(QmlTimeLineValue &timeLineValue, qreal change, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value by the \a change amount over
+ \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::moveBy(QmlTimeLineValue &timeLineValue, qreal change, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, QmlTimeLineEvent(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Cancel (but don't complete) all scheduled actions for \a timeLineValue.
+*/
+void QmlTimeLine::reset(QmlTimeLineValue &timeLineValue)
+{
+ if (!timeLineValue._t)
+ return;
+ if (timeLineValue._t != this) {
+ qWarning() << "QmlTimeLine: Cannot reset a QmlTimeLineValue owned by another timeline.";
+ return;
+ }
+ remove(&timeLineValue);
+ timeLineValue._t = 0;
+}
+
+int QmlTimeLine::duration() const
+{
+ return -1;
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of \a syncTo
+ within this timeline.
+
+ Following operations on \a timeLineValue in this timeline will be scheduled after
+ all the currently scheduled actions on \a syncTo are complete. In
+ psuedo-code this is equivalent to:
+ \code
+ QmlTimeLine::pause(timeLineValue, min(0, length_of(syncTo) - length_of(timeLineValue)))
+ \endcode
+*/
+void QmlTimeLine::sync(QmlTimeLineValue &timeLineValue, QmlTimeLineValue &syncTo)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
+ if (iter == d->ops.end())
+ return;
+ int length = iter->length;
+
+ iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, length);
+ } else {
+ int glength = iter->length;
+ pause(timeLineValue, length - glength);
+ }
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of the longest
+ action cursrently scheduled in the timeline.
+
+ In psuedo-code, this is equivalent to:
+ \code
+ QmlTimeLine::pause(timeLineValue, length_of(timeline) - length_of(timeLineValue))
+ \endcode
+*/
+void QmlTimeLine::sync(QmlTimeLineValue &timeLineValue)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, d->length);
+ } else {
+ pause(timeLineValue, d->length - iter->length);
+ }
+}
+
+/*
+ Synchronize all currently and future scheduled values in this timeline to
+ the longest action currently scheduled.
+
+ For example:
+ \code
+ value1->setValue(0.);
+ value2->setValue(0.);
+ value3->setValue(0.);
+ QmlTimeLine tl;
+ ...
+ tl.move(value1, 10, 200);
+ tl.move(value2, 10, 100);
+ tl.sync();
+ tl.move(value2, 20, 100);
+ tl.move(value3, 20, 100);
+ \endcode
+
+ will result in:
+
+ \table
+ \header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms
+ \row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10
+ \row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0
+ \row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0
+ \endtable
+*/
+
+/*void QmlTimeLine::sync()
+{
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ pause(*iter.key(), d->length - iter->length);
+ d->syncPoint = d->length;
+}*/
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+void QmlTimeLine::setSyncPoint(int sp)
+{
+ d->syncPoint = sp;
+}
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+int QmlTimeLine::syncPoint() const
+{
+ return d->syncPoint;
+}
+
+/*!
+ Returns true if the timeline is active. An active timeline is one where
+ QmlTimeLineValue actions are still pending.
+*/
+bool QmlTimeLine::isActive() const
+{
+ return !d->ops.isEmpty();
+}
+
+/*!
+ Completes the timeline. All queued actions are played to completion, and then discarded. For example,
+ \code
+ QmlTimeLineValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.complete();
+ // v.value() == 100.
+ \endcode
+*/
+void QmlTimeLine::complete()
+{
+ d->advance(d->length);
+}
+
+/*!
+ Resets the timeline. All queued actions are discarded and QmlTimeLineValue's retain their current value. For example,
+ \code
+ QmlTimeLineValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.clear();
+ // v.value() == 50.
+ \endcode
+*/
+void QmlTimeLine::clear()
+{
+ for (QmlTimeLinePrivate::Ops::ConstIterator iter = d->ops.begin(); iter != d->ops.end(); ++iter)
+ iter.key()->_t = 0;
+ d->ops.clear();
+ d->length = 0;
+ d->syncPoint = 0;
+ //XXX need stop here?
+}
+
+int QmlTimeLine::time() const
+{
+ return d->prevTime;
+}
+
+/*!
+ \fn void QmlTimeLine::updated()
+
+ Emitted each time the timeline modifies QmlTimeLineValues. Even if multiple
+ QmlTimeLineValues are changed, this signal is only emitted once for each clock tick.
+*/
+
+void QmlTimeLine::updateCurrentTime(int v)
+{
+ if (d->syncAdj == -1)
+ d->syncAdj = v;
+ v -= d->syncAdj;
+
+ int timeChanged = v - d->prevTime;
+#if 0
+ if (!timeChanged)
+ return;
+#endif
+ d->prevTime = v;
+ d->advance(timeChanged);
+ emit updated();
+
+ // Do we need to stop the clock?
+ if (d->ops.isEmpty()) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = false;
+ emit completed();
+ } /*else if (pauseTime > 0) {
+ GfxClock::cancelClock();
+ d->prevTime = 0;
+ GfxClock::pauseFor(pauseTime);
+ d->syncAdj = 0;
+ d->clockRunning = false;
+ }*/ else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+ d->syncAdj = 0;
+ start();
+ }
+}
+
+bool operator<(const QPair<int, Update> &lhs,
+ const QPair<int, Update> &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+int QmlTimeLinePrivate::advance(int t)
+{
+ int pauseTime = -1;
+
+ // XXX - surely there is a more efficient way?
+ do {
+ pauseTime = -1;
+ // Minimal advance time
+ int advanceTime = t;
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ++iter) {
+ TimeLine &tl = *iter;
+ Op &op = tl.ops.first();
+ int length = op.length - tl.consumedOpLength;
+
+ if (length < advanceTime) {
+ advanceTime = length;
+ if (advanceTime == 0)
+ break;
+ }
+ }
+ t -= advanceTime;
+
+ // Process until then. A zero length advance time will only process
+ // sets.
+ QList<QPair<int, Update> > updates;
+
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
+ QmlTimeLineValue *v = static_cast<QmlTimeLineValue *>(iter.key());
+ TimeLine &tl = *iter;
+ Q_ASSERT(!tl.ops.isEmpty());
+
+ do {
+ Op &op = tl.ops.first();
+ if (advanceTime == 0 && op.length != 0)
+ continue;
+
+ if (tl.consumedOpLength == 0 &&
+ op.type != Op::Pause &&
+ op.type != Op::Execute)
+ tl.base = v->value();
+
+ if ((tl.consumedOpLength + advanceTime) == op.length) {
+ if (op.type == Op::Execute) {
+ updates << qMakePair(op.order, Update(op.event));
+ } else {
+ bool changed = false;
+ qreal val = value(op, op.length, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ }
+ tl.length -= qMin(advanceTime, tl.length);
+ tl.consumedOpLength = 0;
+ tl.ops.removeFirst();
+ } else {
+ tl.consumedOpLength += advanceTime;
+ bool changed = false;
+ qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ tl.length -= qMin(advanceTime, tl.length);
+ break;
+ }
+
+ } while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
+
+
+ if (tl.ops.isEmpty()) {
+ iter = ops.erase(iter);
+ v->_t = 0;
+ } else {
+ if (tl.ops.first().type == Op::Pause && pauseTime != 0) {
+ int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
+ if (pauseTime == -1 || opPauseTime < pauseTime)
+ pauseTime = opPauseTime;
+ } else {
+ pauseTime = 0;
+ }
+ ++iter;
+ }
+ }
+
+ length -= qMin(length, advanceTime);
+ syncPoint -= advanceTime;
+
+ qSort(updates.begin(), updates.end());
+ updateQueue = &updates;
+ for (int ii = 0; ii < updates.count(); ++ii) {
+ const Update &v = updates.at(ii).second;
+ if (v.g)
+ v.g->setValue(v.v);
+ else
+ v.e.execute();
+ }
+ updateQueue = 0;
+ } while(t);
+
+ return pauseTime;
+}
+
+void QmlTimeLine::remove(QmlTimeLineObject *v)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
+ Q_ASSERT(iter != d->ops.end());
+
+ int len = iter->length;
+ d->ops.erase(iter);
+ if (len == d->length) {
+ // We need to recalculate the length
+ d->length = 0;
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter) {
+
+ if (iter->length > d->length)
+ d->length = iter->length;
+
+ }
+ }
+ if (d->ops.isEmpty()) {
+ stop();
+ d->clockRunning = false;
+ } else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+
+ if (d->syncMode == QmlTimeLine::LocalSync) {
+ d->syncAdj = -1;
+ } else {
+ d->syncAdj = 0;
+ }
+ start();
+ }
+
+ if (d->updateQueue) {
+ for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
+ if (d->updateQueue->at(ii).second.g == v ||
+ d->updateQueue->at(ii).second.e.eventObject() == v) {
+ d->updateQueue->removeAt(ii);
+ --ii;
+ }
+ }
+ }
+
+
+}
+
+/*!
+ \internal
+ \class QmlTimeLineValue
+ \ingroup group_animation
+ \brief The QmlTimeLineValue class provides a value that can be modified by QmlTimeLine.
+*/
+
+/*!
+ \fn QmlTimeLineValue::QmlTimeLineValue(qreal value = 0)
+
+ Construct a new QmlTimeLineValue with an initial \a value.
+*/
+
+/*!
+ \fn qreal QmlTimeLineValue::value() const
+
+ Return the current value.
+*/
+
+/*!
+ \fn void QmlTimeLineValue::setValue(qreal value)
+
+ Set the current \a value.
+*/
+
+/*!
+ \fn QmlTimeLine *QmlTimeLineValue::timeLine() const
+
+ If a QmlTimeLine is operating on this value, return a pointer to it,
+ otherwise return null.
+*/
+
+
+QmlTimeLineObject::QmlTimeLineObject()
+: _t(0)
+{
+}
+
+QmlTimeLineObject::~QmlTimeLineObject()
+{
+ if (_t) {
+ _t->remove(this);
+ _t = 0;
+ }
+}
+
+QmlTimeLineEvent::QmlTimeLineEvent()
+: d0(0), d1(0), d2(0)
+{
+}
+
+QmlTimeLineEvent::QmlTimeLineEvent(const QmlTimeLineEvent &o)
+: d0(o.d0), d1(o.d1), d2(o.d2)
+{
+}
+
+QmlTimeLineEvent &QmlTimeLineEvent::operator=(const QmlTimeLineEvent &o)
+{
+ d0 = o.d0;
+ d1 = o.d1;
+ d2 = o.d2;
+ return *this;
+}
+
+void QmlTimeLineEvent::execute() const
+{
+ d0(d1);
+}
+
+QmlTimeLineObject *QmlTimeLineEvent::eventObject() const
+{
+ return d2;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmltimeline_p_p.h b/src/declarative/util/qmltimeline_p_p.h
new file mode 100644
index 0000000..09d46ba
--- /dev/null
+++ b/src/declarative/util/qmltimeline_p_p.h
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTIMELINE_H
+#define QMLTIMELINE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+#include <QtCore/QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+class QEasingCurve;
+class QmlTimeLineValue;
+class QmlTimeLineEvent;
+struct QmlTimeLinePrivate;
+class QmlTimeLineObject;
+class Q_DECLARATIVE_EXPORT QmlTimeLine : public QAbstractAnimation
+{
+Q_OBJECT
+public:
+ QmlTimeLine(QObject *parent = 0);
+ ~QmlTimeLine();
+
+ enum SyncMode { LocalSync, GlobalSync };
+ SyncMode syncMode() const;
+ void setSyncMode(SyncMode);
+
+ void pause(QmlTimeLineObject &, int);
+ void execute(const QmlTimeLineEvent &);
+ void set(QmlTimeLineValue &, qreal);
+
+ int accel(QmlTimeLineValue &, qreal velocity, qreal accel);
+ int accel(QmlTimeLineValue &, qreal velocity, qreal accel, qreal maxDistance);
+ int accelDistance(QmlTimeLineValue &, qreal velocity, qreal distance);
+
+ void move(QmlTimeLineValue &, qreal destination, int time = 500);
+ void move(QmlTimeLineValue &, qreal destination, const QEasingCurve &, int time = 500);
+ void moveBy(QmlTimeLineValue &, qreal change, int time = 500);
+ void moveBy(QmlTimeLineValue &, qreal change, const QEasingCurve &, int time = 500);
+
+ void sync();
+ void setSyncPoint(int);
+ int syncPoint() const;
+
+ void sync(QmlTimeLineValue &);
+ void sync(QmlTimeLineValue &, QmlTimeLineValue &);
+
+ void reset(QmlTimeLineValue &);
+
+ void complete();
+ void clear();
+ bool isActive() const;
+
+ int time() const;
+
+ virtual int duration() const;
+Q_SIGNALS:
+ void updated();
+ void completed();
+
+protected:
+ virtual void updateCurrentTime(int);
+
+private:
+ void remove(QmlTimeLineObject *);
+ friend class QmlTimeLineObject;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLinePrivate *d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineObject
+{
+public:
+ QmlTimeLineObject();
+ virtual ~QmlTimeLineObject();
+
+protected:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLine *_t;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineValue : public QmlTimeLineObject
+{
+public:
+ QmlTimeLineValue(qreal v = 0.) : _v(v) {}
+
+ virtual qreal value() const { return _v; }
+ virtual void setValue(qreal v) { _v = v; }
+
+ QmlTimeLine *timeLine() const { return _t; }
+
+ operator qreal() const { return _v; }
+ QmlTimeLineValue &operator=(qreal v) { setValue(v); return *this; }
+private:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ qreal _v;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineEvent
+{
+public:
+ QmlTimeLineEvent();
+ QmlTimeLineEvent(const QmlTimeLineEvent &o);
+
+ template<class T, void (T::*method)()>
+ QmlTimeLineEvent(QmlTimeLineObject *b, T *c)
+ {
+ d0 = &callFunc<T, method>;
+ d1 = (void *)c;
+ d2 = b;
+ }
+
+ template<class T, void (T::*method)()>
+ static QmlTimeLineEvent timeLineEvent(QmlTimeLineObject *b, T *c)
+ {
+ QmlTimeLineEvent rv;
+ rv.d0 = &callFunc<T, method>;
+ rv.d1 = (void *)c;
+ rv.d2 = b;
+ return rv;
+ }
+
+ QmlTimeLineEvent &operator=(const QmlTimeLineEvent &o);
+ void execute() const;
+ QmlTimeLineObject *eventObject() const;
+
+private:
+ typedef void (*CallFunc)(void *c);
+
+ template <class T, void (T::*method)()>
+ static void callFunc(void *c)
+ {
+ T *cls = (T *)c;
+ (cls->*method)();
+ }
+ CallFunc d0;
+ void *d1;
+ QmlTimeLineObject *d2;
+};
+
+template<class T>
+class QmlTimeLineValueProxy : public QmlTimeLineValue
+{
+public:
+ QmlTimeLineValueProxy(T *cls, void (T::*func)(qreal), qreal v = 0.)
+ : QmlTimeLineValue(v), _class(cls), _setFunctionReal(func), _setFunctionInt(0)
+ {
+ Q_ASSERT(_class);
+ }
+
+ QmlTimeLineValueProxy(T *cls, void (T::*func)(int), qreal v = 0.)
+ : QmlTimeLineValue(v), _class(cls), _setFunctionReal(0), _setFunctionInt(func)
+ {
+ Q_ASSERT(_class);
+ }
+
+ virtual void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ if (_setFunctionReal) (_class->*_setFunctionReal)(v);
+ else if (_setFunctionInt) (_class->*_setFunctionInt)((int)v);
+ }
+
+private:
+ T *_class;
+ void (T::*_setFunctionReal)(qreal);
+ void (T::*_setFunctionInt)(int);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/util/qmltimer.cpp b/src/declarative/util/qmltimer.cpp
new file mode 100644
index 0000000..046dfe9
--- /dev/null
+++ b/src/declarative/util/qmltimer.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltimer_p.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qpauseanimation.h>
+#include <qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,Timer,QmlTimer)
+
+class QmlTimerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlTimer)
+public:
+ QmlTimerPrivate()
+ : interval(1000), running(false), repeating(false), triggeredOnStart(false)
+ , classBegun(false), componentComplete(false), firstTick(true) {}
+ int interval;
+ QPauseAnimation pause;
+ bool running : 1;
+ bool repeating : 1;
+ bool triggeredOnStart : 1;
+ bool classBegun : 1;
+ bool componentComplete : 1;
+ bool firstTick : 1;
+};
+
+/*!
+ \qmlclass Timer QmlTimer
+ \brief The Timer item triggers a handler at a specified interval.
+
+ A timer can be used to trigger an action either once, or repeatedly
+ at a given interval.
+
+ Here is a timer that shows the current date and time, and updates
+ the text every 500 milliseconds:
+
+ \qml
+ Timer {
+ interval: 500; running: true; repeat: true
+ onTriggered: time.text = Date().toString()
+ }
+ Text {
+ id: time
+ }
+ \endqml
+
+ QmlTimer is synchronized with the animation timer. Since the animation
+ timer is usually set to 60fps, the resolution of QmlTimer will be
+ at best 16ms.
+
+ If the Timer is running and one of its properties is changed, the
+ elapsed time will be reset. For example, if a Timer with interval of
+ 1000ms has its \e repeat property changed 500ms after starting, the
+ elapsed time will be reset to 0, and the Timer will be triggered
+ 1000ms later.
+*/
+
+QmlTimer::QmlTimer(QObject *parent)
+ : QObject(*(new QmlTimerPrivate), parent)
+{
+ Q_D(QmlTimer);
+ connect(&d->pause, SIGNAL(currentLoopChanged(int)), this, SLOT(ticked()));
+ connect(&d->pause, SIGNAL(finished()), this, SLOT(finished()));
+ d->pause.setLoopCount(1);
+ d->pause.setDuration(d->interval);
+}
+
+/*!
+ \qmlproperty int Timer::interval
+
+ Sets the \a interval between triggers, in milliseconds.
+
+ The default interval is 1000 milliseconds.
+*/
+void QmlTimer::setInterval(int interval)
+{
+ Q_D(QmlTimer);
+ if (interval != d->interval) {
+ d->interval = interval;
+ update();
+ }
+}
+
+int QmlTimer::interval() const
+{
+ Q_D(const QmlTimer);
+ return d->interval;
+}
+
+/*!
+ \qmlproperty bool Timer::running
+
+ If set to true, starts the timer; otherwise stops the timer.
+ For a non-repeating timer, \a running is set to false after the
+ timer has been triggered.
+
+ \a running defaults to false.
+
+ \sa repeat
+*/
+bool QmlTimer::isRunning() const
+{
+ Q_D(const QmlTimer);
+ return d->running;
+}
+
+void QmlTimer::setRunning(bool running)
+{
+ Q_D(QmlTimer);
+ if (d->running != running) {
+ d->running = running;
+ d->firstTick = true;
+ emit runningChanged();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty bool Timer::repeat
+
+ If \a repeat is true the timer is triggered repeatedly at the
+ specified interval; otherwise, the timer will trigger once at the
+ specified interval and then stop (i.e. running will be set to false).
+
+ \a repeat defaults to false.
+
+ \sa running
+*/
+bool QmlTimer::isRepeating() const
+{
+ Q_D(const QmlTimer);
+ return d->repeating;
+}
+
+void QmlTimer::setRepeating(bool repeating)
+{
+ Q_D(QmlTimer);
+ if (repeating != d->repeating) {
+ d->repeating = repeating;
+ update();
+ }
+}
+
+/*!
+ \qmlproperty bool Timer::triggeredOnStart
+
+ When a timer is started, the first trigger is usually after the specified
+ interval has elapsed. It is sometimes desirable to trigger immediately
+ when the timer is started; for example, to establish an initial
+ state.
+
+ If \a triggeredOnStart is true, the timer is triggered immediately
+ when started, and subsequently at the specified interval. Note that if
+ \e repeat is set to false, the timer is triggered twice; once on start,
+ and again at the interval.
+
+ \a triggeredOnStart defaults to false.
+
+ \sa running
+*/
+bool QmlTimer::triggeredOnStart() const
+{
+ Q_D(const QmlTimer);
+ return d->triggeredOnStart;
+}
+
+void QmlTimer::setTriggeredOnStart(bool triggeredOnStart)
+{
+ Q_D(QmlTimer);
+ if (d->triggeredOnStart != triggeredOnStart) {
+ d->triggeredOnStart = triggeredOnStart;
+ update();
+ }
+}
+
+/*!
+ \qmlmethod Timer::start()
+ \brief Starts the timer.
+
+ If the timer is already running, calling this method has no effect. The
+ \c running property will be true following a call to \c start().
+*/
+void QmlTimer::start()
+{
+ setRunning(true);
+}
+
+/*!
+ \qmlmethod Timer::stop()
+ \brief Stops the timer.
+
+ If the timer is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c stop().
+*/
+void QmlTimer::stop()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlmethod Timer::restart()
+ \brief Restarts the timer.
+
+ If the Timer is not running it will be started, otherwise it will be
+ stopped, reset to initial state and started. The \c running property
+ will be true following a call to \c restart().
+*/
+void QmlTimer::restart()
+{
+ setRunning(false);
+ setRunning(true);
+}
+
+void QmlTimer::update()
+{
+ Q_D(QmlTimer);
+ if (d->classBegun && !d->componentComplete)
+ return;
+ d->pause.stop();
+ if (d->running) {
+ d->pause.setCurrentTime(0);
+ d->pause.setLoopCount(d->repeating ? -1 : 1);
+ d->pause.setDuration(d->interval);
+ d->pause.start();
+ if (d->triggeredOnStart && d->firstTick) {
+ QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
+ QMetaObject::invokeMethod(this, "ticked", Qt::QueuedConnection);
+ }
+ }
+}
+
+void QmlTimer::classBegin()
+{
+ Q_D(QmlTimer);
+ d->classBegun = true;
+}
+
+void QmlTimer::componentComplete()
+{
+ Q_D(QmlTimer);
+ d->componentComplete = true;
+ update();
+}
+
+/*!
+ \qmlsignal Timer::onTriggered()
+
+ This handler is called when the Timer is triggered.
+*/
+void QmlTimer::ticked()
+{
+ Q_D(QmlTimer);
+ if (d->running && (d->pause.currentTime() > 0 || (d->triggeredOnStart && d->firstTick)))
+ emit triggered();
+ d->firstTick = false;
+}
+
+void QmlTimer::finished()
+{
+ Q_D(QmlTimer);
+ if (d->repeating || !d->running)
+ return;
+ emit triggered();
+ d->running = false;
+ d->firstTick = false;
+ emit runningChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmltimer_p.h b/src/declarative/util/qmltimer_p.h
new file mode 100644
index 0000000..fcd6c84
--- /dev/null
+++ b/src/declarative/util/qmltimer_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTIMER_H
+#define QMLTIMER_H
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlTimerPrivate;
+class Q_DECLARATIVE_EXPORT QmlTimer : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlTimer)
+ Q_INTERFACES(QmlParserStatus)
+ Q_PROPERTY(int interval READ interval WRITE setInterval)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating)
+ Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart)
+
+public:
+ QmlTimer(QObject *parent=0);
+
+ void setInterval(int interval);
+ int interval() const;
+
+ bool isRunning() const;
+ void setRunning(bool running);
+
+ bool isRepeating() const;
+ void setRepeating(bool repeating);
+
+ bool triggeredOnStart() const;
+ void setTriggeredOnStart(bool triggeredOnStart);
+
+protected:
+ void classBegin();
+ void componentComplete();
+
+public Q_SLOTS:
+ void start();
+ void stop();
+ void restart();
+
+Q_SIGNALS:
+ void triggered();
+ void runningChanged();
+
+private:
+ void update();
+
+private Q_SLOTS:
+ void ticked();
+ void finished();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlTimer)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qmltransition.cpp b/src/declarative/util/qmltransition.cpp
new file mode 100644
index 0000000..215fc91
--- /dev/null
+++ b/src/declarative/util/qmltransition.cpp
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlstate_p.h"
+#include "qmlstategroup_p.h"
+#include "qmlstate_p_p.h"
+#include "qmlstateoperations_p.h"
+#include "qmlanimation_p.h"
+#include "qmlanimation_p_p.h"
+#include "qmltransitionmanager_p_p.h"
+
+#include <QParallelAnimationGroup>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Transition QmlTransition
+ \brief The Transition element defines animated transitions that occur on state changes.
+
+ \sa {qmlstates}{States}, {state-transitions}{Transitions}
+*/
+
+/*!
+ \internal
+ \class QmlTransition
+ \brief The QmlTransition class allows you to define animated transitions that occur on state changes.
+
+ \ingroup group_states
+*/
+
+//ParallelAnimationWrapperallows us to do a "callback" when the animation finishes, rather than connecting
+//and disconnecting signals and slots frequently
+class ParallelAnimationWrapper : public QParallelAnimationGroup
+{
+ Q_OBJECT
+public:
+ ParallelAnimationWrapper(QObject *parent = 0) : QParallelAnimationGroup(parent) {}
+ QmlTransitionPrivate *trans;
+protected:
+ virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+};
+
+class QmlTransitionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlTransition)
+public:
+ QmlTransitionPrivate() : fromState(QLatin1String("*")), toState(QLatin1String("*"))
+ , reversed(false), reversible(false), endState(0)
+ {
+ animations.parent = this;
+ }
+
+ QString fromState;
+ QString toState;
+ bool reversed;
+ bool reversible;
+ ParallelAnimationWrapper group;
+ QmlTransitionManager *endState;
+
+ void init()
+ {
+ group.trans = this;
+ }
+
+ void complete()
+ {
+ endState->complete();
+ }
+
+ class AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ public:
+ AnimationList() : parent(0) {}
+ virtual void append(QmlAbstractAnimation *a);
+ virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //###
+
+ QmlTransitionPrivate *parent;
+ };
+ AnimationList animations;
+};
+
+void QmlTransitionPrivate::AnimationList::append(QmlAbstractAnimation *a)
+{
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ parent->group.addAnimation(a->qtAnimation());
+}
+
+void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+{
+ QParallelAnimationGroup::updateState(newState, oldState);
+ if (newState == Stopped &&
+ ((direction() == QAbstractAnimation::Forward && currentLoopTime() == duration()) ||
+ (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0)))
+ {
+ trans->complete();
+ }
+}
+
+
+QML_DEFINE_TYPE(Qt,4,6,Transition,QmlTransition)
+QmlTransition::QmlTransition(QObject *parent)
+ : QObject(*(new QmlTransitionPrivate), parent)
+{
+ Q_D(QmlTransition);
+ d->init();
+}
+
+QmlTransition::~QmlTransition()
+{
+}
+
+void QmlTransition::stop()
+{
+ Q_D(QmlTransition);
+ d->group.stop();
+}
+
+void QmlTransition::setReversed(bool r)
+{
+ Q_D(QmlTransition);
+ d->reversed = r;
+}
+
+void QmlTransition::prepare(QmlStateOperation::ActionList &actions,
+ QList<QmlMetaProperty> &after,
+ QmlTransitionManager *endState)
+{
+ Q_D(QmlTransition);
+
+ qmlExecuteDeferred(this);
+
+ if (d->reversed) {
+ for (int ii = d->animations.count() - 1; ii >= 0; --ii) {
+ d->animations.at(ii)->transition(actions, after, QmlAbstractAnimation::Backward);
+ }
+ } else {
+ for (int ii = 0; ii < d->animations.count(); ++ii) {
+ d->animations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward);
+ }
+ }
+
+ d->endState = endState;
+ d->group.setDirection(d->reversed ? QAbstractAnimation::Backward : QAbstractAnimation::Forward);
+ d->group.start();
+}
+
+/*!
+ \qmlproperty string Transition::from
+ \qmlproperty string Transition::to
+ These properties are selectors indicating which state changes should trigger the transition.
+
+ from is used in conjunction with to to determine when a transition should
+ be applied. By default from and to are both "*" (any state). In the following example,
+ the transition is applied when changing from state1 to state2.
+ \code
+ Transition {
+ from: "state1"
+ to: "state2"
+ ...
+ }
+ \endcode
+*/
+QString QmlTransition::fromState() const
+{
+ Q_D(const QmlTransition);
+ return d->fromState;
+}
+
+void QmlTransition::setFromState(const QString &f)
+{
+ Q_D(QmlTransition);
+ d->fromState = f;
+}
+
+/*!
+ \qmlproperty bool Transition::reversible
+ This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
+
+ The default value is false.
+*/
+bool QmlTransition::reversible() const
+{
+ Q_D(const QmlTransition);
+ return d->reversible;
+}
+
+void QmlTransition::setReversible(bool r)
+{
+ Q_D(QmlTransition);
+ d->reversible = r;
+}
+
+QString QmlTransition::toState() const
+{
+ Q_D(const QmlTransition);
+ return d->toState;
+}
+
+void QmlTransition::setToState(const QString &t)
+{
+ Q_D(QmlTransition);
+ d->toState = t;
+}
+
+/*!
+ \qmlproperty list<Animation> Transition::animations
+ \default
+ This property holds a list of the animations to be run for this transition.
+
+ The top-level animations are run in parallel. To run them sequentially,
+ you can create a single SequentialAnimation which contains all the animations,
+ and assign that to animations the animations property.
+ \default
+*/
+QmlList<QmlAbstractAnimation *>* QmlTransition::animations()
+{
+ Q_D(QmlTransition);
+ return &d->animations;
+}
+
+QT_END_NAMESPACE
+
+#include <qmltransition.moc>
diff --git a/src/declarative/util/qmltransition_p.h b/src/declarative/util/qmltransition_p.h
new file mode 100644
index 0000000..c1a6f66
--- /dev/null
+++ b/src/declarative/util/qmltransition_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTRANSITION_H
+#define QMLTRANSITION_H
+
+#include "qmlstate_p.h"
+
+#include <qml.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractAnimation;
+class QmlTransitionPrivate;
+class QmlTransitionManager;
+class Q_DECLARATIVE_EXPORT QmlTransition : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlTransition)
+
+ Q_PROPERTY(QString from READ fromState WRITE setFromState)
+ Q_PROPERTY(QString to READ toState WRITE setToState)
+ Q_PROPERTY(bool reversible READ reversible WRITE setReversible)
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *>* animations READ animations)
+ Q_CLASSINFO("DefaultProperty", "animations")
+ Q_CLASSINFO("DeferredPropertyNames", "animations")
+
+public:
+ QmlTransition(QObject *parent=0);
+ ~QmlTransition();
+
+ QString fromState() const;
+ void setFromState(const QString &);
+
+ QString toState() const;
+ void setToState(const QString &);
+
+ bool reversible() const;
+ void setReversible(bool);
+
+ QmlList<QmlAbstractAnimation *>* animations();
+
+ void prepare(QmlStateOperation::ActionList &actions,
+ QList<QmlMetaProperty> &after,
+ QmlTransitionManager *end);
+
+ void setReversed(bool r);
+ void stop();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlTransition)
+
+QT_END_HEADER
+
+#endif // QMLTRANSITION_H
diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp
new file mode 100644
index 0000000..a3a16ca
--- /dev/null
+++ b/src/declarative/util/qmltransitionmanager.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltransitionmanager_p_p.h"
+
+#include "qmlstate_p_p.h"
+
+#include <qmlbinding.h>
+#include <qmlglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+class QmlTransitionManagerPrivate
+{
+public:
+ QmlTransitionManagerPrivate()
+ : state(0), transition(0) {}
+
+ void applyBindings();
+ typedef QList<QmlSimpleAction> SimpleActionList;
+ QmlState *state;
+ QmlTransition *transition;
+ QmlStateOperation::ActionList bindingsList;
+ SimpleActionList completeList;
+};
+
+QmlTransitionManager::QmlTransitionManager()
+: d(new QmlTransitionManagerPrivate)
+{
+}
+
+void QmlTransitionManager::setState(QmlState *s)
+{
+ d->state = s;
+}
+
+QmlTransitionManager::~QmlTransitionManager()
+{
+ delete d; d = 0;
+}
+
+void QmlTransitionManager::complete()
+{
+ d->applyBindings();
+
+ for (int ii = 0; ii < d->completeList.count(); ++ii) {
+ const QmlMetaProperty &prop = d->completeList.at(ii).property;
+ prop.write(d->completeList.at(ii).value);
+ }
+
+ d->completeList.clear();
+
+ if (d->state)
+ static_cast<QmlStatePrivate*>(QObjectPrivate::get(d->state))->complete();
+}
+
+void QmlTransitionManagerPrivate::applyBindings()
+{
+ foreach(const QmlAction &action, bindingsList) {
+ if (action.toBinding) {
+ action.property.setBinding(action.toBinding);
+ } else if (action.event) {
+ if (action.reverseEvent)
+ action.event->reverse();
+ else
+ action.event->execute();
+ }
+
+ }
+
+ bindingsList.clear();
+}
+
+void QmlTransitionManager::transition(const QList<QmlAction> &list,
+ QmlTransition *transition)
+{
+ cancel();
+
+ QmlStateOperation::ActionList applyList = list;
+ // Determine which actions are binding changes.
+ foreach(const QmlAction &action, applyList) {
+ if (action.toBinding)
+ d->bindingsList << action;
+ if (action.fromBinding)
+ action.property.setBinding(0); // Disable current binding
+ if (action.event && action.event->changesBindings()) { //### assume isReversable()?
+ d->bindingsList << action;
+ if (action.reverseEvent)
+ action.event->clearReverseBindings();
+ else
+ action.event->clearForwardBindings();
+ }
+ }
+
+ // Animated transitions need both the start and the end value for
+ // each property change. In the presence of bindings, the end values
+ // are non-trivial to calculate. As a "best effort" attempt, we first
+ // apply all the property and binding changes, then read all the actual
+ // final values, then roll back the changes and proceed as normal.
+ //
+ // This doesn't catch everything, and it might be a little fragile in
+ // some cases - but whatcha going to do?
+
+ if (!d->bindingsList.isEmpty()) {
+
+ //### do extra actions here?
+
+ // Apply all the property and binding changes
+ for (int ii = 0; ii < applyList.size(); ++ii) {
+ const QmlAction &action = applyList.at(ii);
+ if (action.toBinding) {
+ action.property.setBinding(action.toBinding, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ } else if (!action.event) {
+ action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ } else if (action.event->isReversable()) {
+ if (action.reverseEvent)
+ action.event->reverse();
+ else
+ action.event->execute();
+ applyList << action.event->extraActions();
+ }
+ }
+
+ // Read all the end values for binding changes
+ for (int ii = 0; ii < applyList.size(); ++ii) {
+ QmlAction *action = &applyList[ii];
+ if (action->event)
+ continue;
+ const QmlMetaProperty &prop = action->property;
+ if (action->toBinding || !action->toValue.isValid()) { //### is this always right (used for exta actions)
+ action->toValue = prop.read();
+ }
+ }
+
+ // Revert back to the original values
+ foreach(const QmlAction &action, applyList) {
+ if (action.event) {
+ if (action.event->isReversable()) {
+ if (action.reverseEvent) { //reverse the reverse
+ action.event->clearForwardBindings();
+ action.event->rewind();
+ action.event->clearReverseBindings();
+ } else {
+ action.event->clearReverseBindings();
+ action.event->rewind();
+ action.event->clearForwardBindings();
+ }
+ }
+ continue;
+ }
+
+ if (action.toBinding)
+ action.property.setBinding(0); // Make sure this is disabled during the transition
+
+ action.property.write(action.fromValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ }
+ }
+
+ if (transition) {
+ QList<QmlMetaProperty> touched;
+ d->transition = transition;
+ d->transition->prepare(applyList, touched, this);
+
+ // Modify the action list to remove actions handled in the transition
+ for (int ii = 0; ii < applyList.count(); ++ii) {
+ const QmlAction &action = applyList.at(ii);
+
+ if (action.event) {
+
+ if (action.actionDone) {
+ applyList.removeAt(ii);
+ --ii;
+ }
+
+ } else {
+
+ if (touched.contains(action.property)) {
+ if (action.toValue != action.fromValue)
+ d->completeList <<
+ QmlSimpleAction(action, QmlSimpleAction::EndState);
+
+ applyList.removeAt(ii);
+ --ii;
+ }
+
+ }
+ }
+ }
+
+ // Any actions remaining have not been handled by the transition and should
+ // be applied immediately. We skip applying bindings, as they are all
+ // applied at the end in applyBindings() to avoid any nastiness mid
+ // transition
+ foreach(const QmlAction &action, applyList) {
+ if (action.event && !action.event->changesBindings()) {
+ if (action.event->isReversable() && action.reverseEvent)
+ action.event->reverse();
+ else
+ action.event->execute();
+ } else if (!action.event && !action.toBinding) {
+ action.property.write(action.toValue);
+ }
+ }
+ if (stateChangeDebug()) {
+ foreach(const QmlAction &action, applyList) {
+ if (action.event)
+ qWarning() << " No transition for event:" << action.event->typeName();
+ else
+ qWarning() << " No transition for:" << action.property.object()
+ << action.property.name() << "From:" << action.fromValue
+ << "To:" << action.toValue;
+ }
+ }
+ if (!transition)
+ d->applyBindings();
+}
+
+void QmlTransitionManager::cancel()
+{
+ if (d->transition) {
+ // ### this could potentially trigger a complete in rare circumstances
+ d->transition->stop();
+ d->transition = 0;
+ }
+
+ for(int i = 0; i < d->bindingsList.count(); ++i) {
+ QmlAction action = d->bindingsList[i];
+ if (action.toBinding && action.deletableToBinding) {
+ action.property.setBinding(0);
+ action.toBinding->destroy();
+ action.toBinding = 0;
+ action.deletableToBinding = false;
+ } else if (action.event) {
+ //### what do we do here?
+ }
+
+ }
+ d->bindingsList.clear();
+ d->completeList.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmltransitionmanager_p_p.h b/src/declarative/util/qmltransitionmanager_p_p.h
new file mode 100644
index 0000000..cb4111c
--- /dev/null
+++ b/src/declarative/util/qmltransitionmanager_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTRANSITIONMANAGER_P_H
+#define QMLTRANSITIONMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmlstateoperations_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlStatePrivate;
+class QmlTransitionManagerPrivate;
+class QmlTransitionManager
+{
+public:
+ QmlTransitionManager();
+ ~QmlTransitionManager();
+
+ void transition(const QList<QmlAction> &, QmlTransition *transition);
+
+ void cancel();
+
+private:
+ Q_DISABLE_COPY(QmlTransitionManager);
+ QmlTransitionManagerPrivate *d;
+
+ void complete();
+ void setState(QmlState *);
+
+ friend class QmlState;
+ friend class QmlTransitionPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLTRANSITIONMANAGER_P_H
diff --git a/src/declarative/util/qmlview.cpp b/src/declarative/util/qmlview.cpp
new file mode 100644
index 0000000..690924f
--- /dev/null
+++ b/src/declarative/util/qmlview.cpp
@@ -0,0 +1,586 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlview.h"
+
+#include "qperformancelog_p_p.h"
+#include "qfxperf_p_p.h"
+
+#include <qml.h>
+#include <qmlgraphicsitem.h>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmldebug_p.h>
+#include <qmldebugservice_p.h>
+#include <qmlglobal_p.h>
+
+#include <qscriptvalueiterator.h>
+#include <qdebug.h>
+#include <qtimer.h>
+#include <qevent.h>
+#include <qdir.h>
+#include <qcoreapplication.h>
+#include <qfontdatabase.h>
+#include <qicon.h>
+#include <qurl.h>
+#include <qboxlayout.h>
+#include <qbasictimer.h>
+#include <QtCore/qabstractanimation.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE)
+
+class QmlViewDebugServer;
+class FrameBreakAnimation : public QAbstractAnimation
+{
+public:
+ FrameBreakAnimation(QmlViewDebugServer *s)
+ : QAbstractAnimation((QObject*)s), server(s)
+ {
+ start();
+ }
+
+ virtual int duration() const { return -1; }
+ virtual void updateCurrentTime(int msecs);
+
+private:
+ QmlViewDebugServer *server;
+};
+
+class QmlViewDebugServer : public QmlDebugService
+{
+public:
+ QmlViewDebugServer(QObject *parent = 0) : QmlDebugService(QLatin1String("CanvasFrameRate"), parent), breaks(0)
+ {
+ timer.start();
+ new FrameBreakAnimation(this);
+ }
+
+ void addTiming(int pe, int tbf)
+ {
+ if (!isEnabled())
+ return;
+
+ bool isFrameBreak = breaks > 1;
+ breaks = 0;
+ int e = timer.elapsed();
+ QByteArray data;
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << (int)pe << (int)tbf << (int)e
+ << (bool)isFrameBreak;
+ sendMessage(data);
+ }
+
+ void frameBreak() { ++breaks; }
+
+private:
+ QTime timer;
+ int breaks;
+};
+
+Q_GLOBAL_STATIC(QmlViewDebugServer, qfxViewDebugServer);
+
+void FrameBreakAnimation::updateCurrentTime(int msecs)
+{
+ Q_UNUSED(msecs);
+ server->frameBreak();
+}
+
+class QmlViewPrivate
+{
+public:
+ QmlViewPrivate(QmlView *w)
+ : q(w), root(0), component(0), resizable(false) {}
+
+ QmlView *q;
+ QmlGraphicsItem *root;
+
+ QUrl source;
+ QString qml;
+
+ QmlEngine engine;
+ QmlComponent *component;
+ QBasicTimer resizetimer;
+
+ QSize initialSize;
+ bool resizable;
+ QTime frameTimer;
+
+ void init();
+
+ QGraphicsScene scene;
+};
+
+/*!
+ \class QmlView
+ \brief The QmlView class provides a widget for displaying a Qt Declarative user interface.
+
+ QmlView currently provides a minimal interface for displaying QML
+ files, and connecting between QML and C++ Qt objects.
+
+ Typical usage:
+ \code
+ ...
+ QmlView *view = new QmlView(this);
+ vbox->addWidget(view);
+
+ QUrl url(fileName);
+ view->setUrl(url);
+ ...
+ view->execute();
+ ...
+ view->show();
+ \endcode
+
+ To receive errors related to loading and executing QML with QmlView,
+ you can connect to the errors() signal.
+*/
+
+/*!
+ \fn QmlView::QmlView(QWidget *parent)
+
+ Constructs a QmlView with the given \a parent.
+*/
+QmlView::QmlView(QWidget *parent)
+: QGraphicsView(parent), d(new QmlViewPrivate(this))
+{
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+}
+
+void QmlViewPrivate::init()
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ {
+ QmlPerfTimer<QmlPerf::FontDatabase> perf;
+ QFontDatabase database;
+ }
+#endif
+
+ q->setScene(&scene);
+
+ q->setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ q->setFrameStyle(0);
+
+ // These seem to give the best performance
+ q->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ q->viewport()->setFocusPolicy(Qt::NoFocus);
+
+ scene.setStickyFocus(true); //### needed for correct focus handling
+}
+
+/*!
+ The destructor clears the view's \l {QmlGraphicsItem} {items} and
+ deletes the internal representation.
+
+ \sa clearItems()
+ */
+QmlView::~QmlView()
+{
+ clearItems();
+ delete d; d = 0;
+}
+
+/*!
+ Sets the source to the \a url. The QML string is set to
+ empty.
+ */
+void QmlView::setUrl(const QUrl& url)
+{
+ d->source = url;
+ d->qml = QString();
+}
+
+/*!
+ Returns the source URL, if set.
+
+ \sa setUrl()
+ */
+QUrl QmlView::url() const
+{
+ return d->source;
+}
+
+/*!
+ Sets the source to the URL from the \a filename, and sets
+ the QML string to \a qml.
+ */
+void QmlView::setQml(const QString &qml, const QString &filename)
+{
+ d->source = QUrl::fromLocalFile(filename);
+ d->qml = qml;
+}
+
+/*!
+ Returns the QML string.
+ */
+QString QmlView::qml() const
+{
+ return d->qml;
+}
+
+/*!
+ Returns a pointer to the QmlEngine used for instantiating
+ QML Components.
+ */
+QmlEngine* QmlView::engine()
+{
+ return &d->engine;
+}
+
+/*!
+ This function returns the root of the context hierarchy. Each QML
+ component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are
+ arranged hierarchically and this hierarchy is managed by the
+ QmlEngine.
+ */
+QmlContext* QmlView::rootContext()
+{
+ return d->engine.rootContext();
+}
+
+/*!
+ Displays the Qt Declarative user interface.
+*/
+void QmlView::execute()
+{
+ if (d->qml.isEmpty()) {
+ d->component = new QmlComponent(&d->engine, d->source, this);
+ } else {
+ d->component = new QmlComponent(&d->engine, this);
+ d->component->setData(d->qml.toUtf8(), d->source);
+ }
+ connect (&d->engine, SIGNAL (quit ()), this, SIGNAL (quit ()));
+
+ if (!d->component->isLoading()) {
+ continueExecute();
+ } else {
+ connect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
+ }
+}
+
+
+/*!
+ \internal
+ */
+void QmlView::continueExecute()
+{
+ disconnect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
+
+ if (!d->component) {
+ qWarning() << "Error in loading" << d->source;
+ return;
+ }
+
+ if(d->component->isError()) {
+ QList<QmlError> errorList = d->component->errors();
+ foreach (const QmlError &error, errorList) {
+ qWarning() << error;
+ }
+ emit errors(errorList);
+
+ return;
+ }
+
+ QObject *obj = d->component->create();
+
+ if(d->component->isError()) {
+ QList<QmlError> errorList = d->component->errors();
+ foreach (const QmlError &error, errorList) {
+ qWarning() << error;
+ }
+ emit errors(errorList);
+
+ return;
+ }
+
+ if (obj) {
+ if (QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(obj)) {
+
+ d->scene.addItem(item);
+
+ QPerformanceLog::displayData();
+ QPerformanceLog::clear();
+ d->root = item;
+ connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged()));
+ connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged()));
+ if (d->initialSize.height() <= 0 && d->root->width() > 0)
+ d->initialSize.setWidth(d->root->width());
+ if (d->initialSize.height() <= 0 && d->root->height() > 0)
+ d->initialSize.setHeight(d->root->height());
+ resize(d->initialSize);
+
+ if (d->resizable) {
+ d->root->setWidth(width());
+ d->root->setHeight(height());
+ } else {
+ QSize sz(d->root->width(),d->root->height());
+ emit sceneResized(sz);
+ resize(sz);
+ }
+ updateGeometry();
+ emit initialSize(d->initialSize);
+ } else if (QWidget *wid = qobject_cast<QWidget *>(obj)) {
+ window()->setAttribute(Qt::WA_OpaquePaintEvent, false);
+ window()->setAttribute(Qt::WA_NoSystemBackground, false);
+ if (!layout()) {
+ setLayout(new QVBoxLayout);
+ layout()->setContentsMargins(0, 0, 0, 0);
+ } else if (layout()->count()) {
+ // Hide the QGraphicsView in GV mode.
+ QLayoutItem *item = layout()->itemAt(0);
+ if (item->widget())
+ item->widget()->hide();
+ }
+ layout()->addWidget(wid);
+ emit sceneResized(wid->size());
+ emit initialSize(wid->size());
+ }
+ }
+}
+
+/*! \fn void QmlView::sceneResized(QSize size)
+ This signal is emitted when the view is resized to \a size.
+ */
+
+/*! \fn void QmlView::initialSize(QSize size)
+ This signal is emitted when the initial \a size of the root item is known.
+ */
+
+/*! \fn void QmlView::errors(const QList<QmlError> &errors)
+ This signal is emitted when the qml loaded contains \a errors.
+ */
+
+/*!
+ \internal
+ */
+void QmlView::sizeChanged()
+{
+ // delay, so we catch both width and height changing.
+ d->resizetimer.start(0,this);
+}
+
+/*!
+ If the \l {QTimerEvent} {timer event} \a e is this
+ view's resize timer, sceneResized() is emitted.
+ */
+void QmlView::timerEvent(QTimerEvent* e)
+{
+ if (!e || e->timerId() == d->resizetimer.timerId()) {
+ if (d->root) {
+ QSize sz(d->root->width(),d->root->height());
+ emit sceneResized(sz);
+ //if (!d->resizable)
+ //resize(sz);
+ }
+ d->resizetimer.stop();
+ updateGeometry();
+ }
+}
+
+// modelled on QScrollArea::widgetResizable
+/*!
+ \property QmlView::contentResizable
+ \brief whether the view should resize the canvas contents
+
+ If this property is set to false (the default), the view
+ resizes with the root item in the QML.
+
+ If this property is set to true, the view will
+ automatically resize the root item.
+
+ Regardless of this property, the sizeHint of the view
+ is the initial size of the root item. Note though that
+ since QML may load dynamically, that size may change.
+
+ \sa initialSize()
+*/
+
+void QmlView::setContentResizable(bool on)
+{
+ if (d->resizable != on) {
+ d->resizable = on;
+ if (d->root) {
+ if (on) {
+ d->root->setWidth(width());
+ d->root->setHeight(height());
+ } else {
+ d->root->setWidth(d->initialSize.width());
+ d->root->setHeight(d->initialSize.height());
+ }
+ }
+ }
+}
+
+bool QmlView::contentResizable() const
+{
+ return d->resizable;
+}
+
+
+/*!
+ The size hint is the size of the root item.
+*/
+QSize QmlView::sizeHint() const
+{
+ if (d->root) {
+ if (d->initialSize.width() <= 0)
+ d->initialSize.setWidth(d->root->width());
+ if (d->initialSize.height() <= 0)
+ d->initialSize.setHeight(d->root->height());
+ }
+ return d->initialSize;
+}
+
+/*!
+ Creates a \l{QmlComponent} {component} from the \a qml
+ string, and returns it as an \l {QmlGraphicsItem} {item}. If the
+ \a parent item is provided, it becomes the new item's
+ parent. \a parent should be in this view's item hierarchy.
+ */
+QmlGraphicsItem* QmlView::addItem(const QString &qml, QmlGraphicsItem* parent)
+{
+ if (!d->root)
+ return 0;
+
+ QmlComponent component(&d->engine);
+ component.setData(qml.toUtf8(), QUrl());
+ if(d->component->isError()) {
+ QList<QmlError> errorList = d->component->errors();
+ foreach (const QmlError &error, errorList) {
+ qWarning() << error;
+ }
+ emit errors(errorList);
+
+ return 0;
+ }
+
+ QObject *obj = component.create();
+ if(d->component->isError()) {
+ QList<QmlError> errorList = d->component->errors();
+ foreach (const QmlError &error, errorList) {
+ qWarning() << error;
+ }
+ emit errors(errorList);
+
+ return 0;
+ }
+
+ if (obj){
+ QmlGraphicsItem *item = static_cast<QmlGraphicsItem *>(obj);
+ if (!parent)
+ parent = d->root;
+
+ item->setParentItem(parent);
+ return item;
+ }
+ return 0;
+}
+
+/*!
+ Deletes the view's \l {QmlGraphicsItem} {items} and clears the \l {QmlEngine}
+ {QML engine's} Component cache.
+ */
+void QmlView::reset()
+{
+ clearItems();
+ d->engine.clearComponentCache();
+ d->initialSize = QSize();
+}
+
+/*!
+ Deletes the view's \l {QmlGraphicsItem} {items}.
+ */
+void QmlView::clearItems()
+{
+ if (!d->root)
+ return;
+ delete d->root;
+ d->root = 0;
+}
+
+/*!
+ Returns the view's root \l {QmlGraphicsItem} {item}.
+ */
+QmlGraphicsItem *QmlView::root() const
+{
+ return d->root;
+}
+
+/*!
+ This function handles the \l {QResizeEvent} {resize event}
+ \a e.
+ */
+void QmlView::resizeEvent(QResizeEvent *e)
+{
+ if (d->resizable && d->root) {
+ d->root->setWidth(width());
+ d->root->setHeight(height());
+ }
+ if (d->root) {
+ setSceneRect(QRectF(0, 0, d->root->width(), d->root->height()));
+ } else {
+ setSceneRect(rect());
+ }
+ QGraphicsView::resizeEvent(e);
+}
+
+/*!
+ \reimp
+*/
+void QmlView::paintEvent(QPaintEvent *event)
+{
+ int time = 0;
+ if (frameRateDebug() || QmlViewDebugServer::isDebuggingEnabled())
+ time = d->frameTimer.restart();
+ QGraphicsView::paintEvent(event);
+ if (QmlViewDebugServer::isDebuggingEnabled())
+ qfxViewDebugServer()->addTiming(d->frameTimer.elapsed(), time);
+ if (frameRateDebug())
+ qDebug() << "paintEvent:" << d->frameTimer.elapsed() << "time since last frame:" << time;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlview.h b/src/declarative/util/qmlview.h
new file mode 100644
index 0000000..f4f58fd
--- /dev/null
+++ b/src/declarative/util/qmlview.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXVIEW_H
+#define QFXVIEW_H
+
+#include <QtCore/qdatetime.h>
+#include <QtGui/qgraphicssceneevent.h>
+#include <QtGui/qgraphicsview.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlGraphicsItem;
+class QmlEngine;
+class QmlContext;
+class QmlError;
+
+class QmlViewPrivate;
+class Q_DECLARATIVE_EXPORT QmlView : public QGraphicsView
+{
+ Q_OBJECT
+ Q_PROPERTY(bool contentResizable READ contentResizable WRITE setContentResizable)
+public:
+ explicit QmlView(QWidget *parent = 0);
+
+ virtual ~QmlView();
+
+ void setUrl(const QUrl&);
+ QUrl url() const;
+ void setQml(const QString &qml, const QString &filename=QString());
+ QString qml() const;
+ QmlEngine* engine();
+ QmlContext* rootContext();
+ virtual void execute();
+ virtual void reset();
+
+ virtual QmlGraphicsItem* addItem(const QString &qml, QmlGraphicsItem* parent=0);
+ virtual void clearItems();
+
+ virtual QmlGraphicsItem *root() const;
+
+ void setContentResizable(bool);
+ bool contentResizable() const;
+ QSize sizeHint() const;
+
+Q_SIGNALS:
+ void initialSize(QSize size);
+ void sceneResized(QSize size);
+ void errors(const QList<QmlError> &error);
+ void quit ();
+
+private Q_SLOTS:
+ void continueExecute();
+ void sizeChanged();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void paintEvent(QPaintEvent *event);
+ void timerEvent(QTimerEvent*);
+
+private:
+ friend class QmlViewPrivate;
+ QmlViewPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXVIEW_H
diff --git a/src/declarative/util/qmlxmllistmodel.cpp b/src/declarative/util/qmlxmllistmodel.cpp
new file mode 100644
index 0000000..d31fadf
--- /dev/null
+++ b/src/declarative/util/qmlxmllistmodel.cpp
@@ -0,0 +1,728 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlxmllistmodel_p.h"
+
+#include <qmlcontext.h>
+#include <qmlengine.h>
+
+#include <QDebug>
+#include <QApplication>
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QXmlQuery>
+#include <QXmlResultItems>
+#include <QXmlNodeModelIndex>
+#include <QBuffer>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,XmlRole,QmlXmlListModelRole)
+QML_DEFINE_TYPE(Qt,4,6,XmlListModel,QmlXmlListModel)
+
+/*!
+ \qmlclass XmlRole QmlXmlListModelRole
+ \brief The XmlRole element allows you to specify a role for an XmlListModel.
+*/
+
+/*!
+ \qmlproperty string XmlRole::name
+ The name for the role. This name is used to access the model data for this role from Qml.
+
+ \qml
+ XmlRole { name: "title"; query: "title/string()" }
+
+ ...
+
+ Component {
+ id: myDelegate
+ Text { text: title }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string XmlRole::query
+ The relative XPath query for this role. The query should not start with a '/' (i.e. it must be
+ relative).
+
+ \qml
+ XmlRole { name: "title"; query: "title/string()" }
+ \endqml
+*/
+
+class Q_DECLARATIVE_EXPORT QmlXmlListModelRole : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+
+public:
+ QmlXmlListModelRole() {}
+ ~QmlXmlListModelRole() {}
+
+ QString name() const { return m_name; }
+ void setName(const QString &name) { m_name = name; }
+
+ QString query() const { return m_query; }
+ void setQuery(const QString &query)
+ {
+ if (query.startsWith(QLatin1Char('/'))) {
+ qmlInfo(this) << tr("An XmlRole query must not start with '/'");
+ return;
+ }
+ m_query = query;
+ }
+
+ bool isValid() {
+ return !m_name.isEmpty() && !m_query.isEmpty();
+ }
+
+private:
+ QString m_name;
+ QString m_query;
+};
+
+QML_DECLARE_TYPE(QmlXmlListModelRole)
+
+class QmlXmlListModelPrivate;
+struct QmlXmlRoleList : public QmlConcreteList<QmlXmlListModelRole *>
+{
+ QmlXmlRoleList(QmlXmlListModelPrivate *p)
+ : model(p) {}
+ virtual void append(QmlXmlListModelRole *role);
+ virtual void clear();
+ virtual void removeAt(int i);
+ virtual void insert(int i, QmlXmlListModelRole *role);
+
+ QmlXmlListModelPrivate *model;
+};
+
+class QmlXmlQuery : public QThread
+{
+ Q_OBJECT
+public:
+ QmlXmlQuery(QObject *parent=0)
+ : QThread(parent), m_quit(false), m_restart(false), m_abort(false), m_queryId(0) {
+ }
+ ~QmlXmlQuery() {
+ m_mutex.lock();
+ m_quit = true;
+ m_condition.wakeOne();
+ m_mutex.unlock();
+
+ wait();
+ }
+
+ void abort() {
+ QMutexLocker locker(&m_mutex);
+ m_abort = true;
+ }
+
+ int doQuery(QString query, QString namespaces, QByteArray data, QmlXmlRoleList *roleObjects) {
+ QMutexLocker locker(&m_mutex);
+ m_modelData.clear();
+ m_size = 0;
+ m_data = data;
+ m_query = QLatin1String("doc($src)") + query;
+ m_namespaces = namespaces;
+ m_roleObjects = roleObjects;
+ if (!isRunning()) {
+ m_abort = false;
+ start();
+ } else {
+ m_restart = true;
+ m_condition.wakeOne();
+ }
+ m_queryId++;
+ return m_queryId;
+ }
+
+ QList<QList<QVariant> > modelData() {
+ QMutexLocker locker(&m_mutex);
+ return m_modelData;
+ }
+
+Q_SIGNALS:
+ void queryCompleted(int queryId, int size);
+
+protected:
+ void run() {
+ while (!m_quit) {
+ m_mutex.lock();
+ int queryId = m_queryId;
+ doQueryJob();
+ if (m_size > 0)
+ doSubQueryJob();
+ m_data.clear(); // no longer needed
+ m_mutex.unlock();
+
+ m_mutex.lock();
+ if (!m_abort && m_size > 0)
+ emit queryCompleted(queryId, m_size);
+ if (!m_restart)
+ m_condition.wait(&m_mutex);
+ m_abort = false;
+ m_restart = false;
+ m_mutex.unlock();
+ }
+ }
+
+private:
+ void doQueryJob();
+ void doSubQueryJob();
+
+private:
+ QMutex m_mutex;
+ QWaitCondition m_condition;
+ bool m_quit;
+ bool m_restart;
+ bool m_abort;
+ QByteArray m_data;
+ QString m_query;
+ QString m_namespaces;
+ QString m_prefix;
+ int m_size;
+ int m_queryId;
+ const QmlXmlRoleList *m_roleObjects;
+ QList<QList<QVariant> > m_modelData;
+};
+
+void QmlXmlQuery::doQueryJob()
+{
+ QString r;
+ QXmlQuery query;
+ QBuffer buffer(&m_data);
+ buffer.open(QIODevice::ReadOnly);
+ query.bindVariable(QLatin1String("src"), &buffer);
+ query.setQuery(m_namespaces + m_query);
+ query.evaluateTo(&r);
+
+ //qDebug() << r;
+
+ //always need a single root element
+ QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>";
+ QBuffer b(&xml);
+ b.open(QIODevice::ReadOnly);
+ //qDebug() << xml;
+
+ QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + m_namespaces;
+ QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
+ m_query.mid(m_query.lastIndexOf(QLatin1Char('/')));
+
+ //figure out how many items we are dealing with
+ int count = -1;
+ {
+ QXmlResultItems result;
+ QXmlQuery countquery;
+ countquery.bindVariable(QLatin1String("inputDocument"), &b);
+ countquery.setQuery(namespaces + QLatin1String("count(") + prefix + QLatin1Char(')'));
+ countquery.evaluateTo(&result);
+ QXmlItem item(result.next());
+ if (item.isAtomicValue())
+ count = item.toAtomicValue().toInt();
+ }
+ //qDebug() << count;
+
+ m_prefix = namespaces + prefix + QLatin1Char('/');
+ m_data = xml;
+ if (count > 0)
+ m_size = count;
+}
+
+void QmlXmlQuery::doSubQueryJob()
+{
+ m_modelData.clear();
+
+ QBuffer b(&m_data);
+ b.open(QIODevice::ReadOnly);
+
+ QXmlQuery subquery;
+ subquery.bindVariable(QLatin1String("inputDocument"), &b);
+
+ //### we might be able to condense even further (query for everything in one go)
+ for (int i = 0; i < m_roleObjects->size(); ++i) {
+ QmlXmlListModelRole *role = m_roleObjects->at(i);
+ if (!role->isValid()) {
+ QList<QVariant> resultList;
+ for (int j = 0; j < m_size; ++j)
+ resultList << QVariant();
+ m_modelData << resultList;
+ continue;
+ }
+ subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + role->query() + QLatin1String(" return if ($v) then ") + role->query() + QLatin1String(" else \"\")"));
+ QXmlResultItems output3;
+ subquery.evaluateTo(&output3);
+ QXmlItem item(output3.next());
+ QList<QVariant> resultList;
+ while (!item.isNull()) {
+ resultList << item.toAtomicValue(); //### we used to trim strings
+ item = output3.next();
+ }
+ //### should warn here if things have gone wrong.
+ while (resultList.count() < m_size)
+ resultList << QVariant();
+ m_modelData << resultList;
+ b.seek(0);
+ }
+
+ //this method is much slower, but works better for incremental loading
+ /*for (int j = 0; j < m_size; ++j) {
+ QList<QVariant> resultList;
+ for (int i = 0; i < m_roleObjects->size(); ++i) {
+ QmlXmlListModelRole *role = m_roleObjects->at(i);
+ subquery.setQuery(m_prefix.arg(j+1) + role->query());
+ if (role->isStringList()) {
+ QStringList data;
+ subquery.evaluateTo(&data);
+ resultList << QVariant(data);
+ //qDebug() << data;
+ } else {
+ QString s;
+ subquery.evaluateTo(&s);
+ if (role->isCData()) {
+ //un-escape
+ s.replace(QLatin1String("&lt;"), QLatin1String("<"));
+ s.replace(QLatin1String("&gt;"), QLatin1String(">"));
+ s.replace(QLatin1String("&amp;"), QLatin1String("&"));
+ }
+ resultList << s.trimmed();
+ //qDebug() << s;
+ }
+ b.seek(0);
+ }
+ m_modelData << resultList;
+ }*/
+}
+
+class QmlXmlListModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlXmlListModel)
+public:
+ QmlXmlListModelPrivate()
+ : isComponentComplete(true), size(-1), highestRole(Qt::UserRole)
+ , reply(0), status(QmlXmlListModel::Null), progress(0.0)
+ , queryId(-1), roleObjects(this) {}
+
+ bool isComponentComplete;
+ QUrl src;
+ QString xml;
+ QString query;
+ QString namespaces;
+ int size;
+ QList<int> roles;
+ QStringList roleNames;
+ int highestRole;
+ QNetworkReply *reply;
+ QmlXmlListModel::Status status;
+ qreal progress;
+ QmlXmlQuery qmlXmlQuery;
+ int queryId;
+ QmlXmlRoleList roleObjects;
+ QList<QList<QVariant> > data;
+};
+
+
+void QmlXmlRoleList::append(QmlXmlListModelRole *role)
+{
+ insert(size(), role);
+}
+
+//### clear, removeAt, and insert need to invalidate any cached data (in data table) as well
+// (and the model should emit the appropriate signals)
+void QmlXmlRoleList::clear()
+{
+ model->roles.clear();
+ model->roleNames.clear();
+ QmlConcreteList<QmlXmlListModelRole *>::clear();
+}
+
+void QmlXmlRoleList::removeAt(int i)
+{
+ model->roles.removeAt(i);
+ model->roleNames.removeAt(i);
+ QmlConcreteList<QmlXmlListModelRole *>::removeAt(i);
+}
+
+void QmlXmlRoleList::insert(int i, QmlXmlListModelRole *role)
+{
+ QmlConcreteList<QmlXmlListModelRole *>::insert(i, role);
+ if (model->roleNames.contains(role->name())) {
+ qmlInfo(role) << QObject::tr("\"%1\" duplicates a previous role name and will be disabled.").arg(role->name());
+ return;
+ }
+ model->roles.insert(i, model->highestRole);
+ model->roleNames.insert(i, role->name());
+ ++model->highestRole;
+}
+
+/*!
+ \class QmlXmlListModel
+ \internal
+*/
+
+/*!
+ \qmlclass XmlListModel QmlXmlListModel
+ \brief The XmlListModel element allows you to specify a model using XPath expressions.
+
+ XmlListModel allows you to construct a model from XML data that can then be used as a data source
+ for the view classes (ListView, PathView, GridView) and any other classes that interact with model
+ data (like Repeater).
+
+ The following is an example of a model containing news from a Yahoo RSS feed:
+ \qml
+ XmlListModel {
+ id: feedModel
+ source: "http://rss.news.yahoo.com/rss/oceania"
+ query: "/rss/channel/item"
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "link"; query: "link/string()" }
+ XmlRole { name: "description"; query: "description/string()" }
+ }
+ \endqml
+ \note The model is currently static, so the above is really just a snapshot of an RSS feed. To force a
+ reload of the entire model, you can call the reload function.
+*/
+
+QmlXmlListModel::QmlXmlListModel(QObject *parent)
+ : QListModelInterface(*(new QmlXmlListModelPrivate), parent)
+{
+ Q_D(QmlXmlListModel);
+ connect(&d->qmlXmlQuery, SIGNAL(queryCompleted(int,int)),
+ this, SLOT(queryCompleted(int,int)));
+}
+
+QmlXmlListModel::~QmlXmlListModel()
+{
+}
+
+/*!
+ \qmlproperty list<XmlRole> XmlListModel::roles
+
+ The roles to make available for this model.
+*/
+QmlList<QmlXmlListModelRole *> *QmlXmlListModel::roleObjects()
+{
+ Q_D(QmlXmlListModel);
+ return &d->roleObjects;
+}
+
+QHash<int,QVariant> QmlXmlListModel::data(int index, const QList<int> &roles) const
+{
+ Q_D(const QmlXmlListModel);
+ QHash<int, QVariant> rv;
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ int roleIndex = d->roles.indexOf(role);
+ rv.insert(role, roleIndex == -1 ? QVariant() : d->data.at(roleIndex).at(index));
+ }
+ return rv;
+}
+
+QVariant QmlXmlListModel::data(int index, int role) const
+{
+ Q_D(const QmlXmlListModel);
+ int roleIndex = d->roles.indexOf(role);
+ return (roleIndex == -1) ? QVariant() : d->data.at(roleIndex).at(index);
+}
+
+/*!
+ \qmlproperty int XmlListModel::count
+ The number of data entries in the model.
+*/
+int QmlXmlListModel::count() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->size;
+}
+
+QList<int> QmlXmlListModel::roles() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->roles;
+}
+
+QString QmlXmlListModel::toString(int role) const
+{
+ Q_D(const QmlXmlListModel);
+ int index = d->roles.indexOf(role);
+ if (index == -1)
+ return QString();
+ return d->roleNames.at(index);
+}
+
+/*!
+ \qmlproperty url XmlListModel::source
+ The location of the XML data source.
+
+ If both source and xml are set, xml will be used.
+*/
+QUrl QmlXmlListModel::source() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->src;
+}
+
+void QmlXmlListModel::setSource(const QUrl &src)
+{
+ Q_D(QmlXmlListModel);
+ if (d->src != src) {
+ d->src = src;
+ reload();
+ }
+}
+
+/*!
+ \qmlproperty string XmlListModel::xml
+ This property holds XML text set directly.
+
+ The text is assumed to be UTF-8 encoded.
+
+ If both source and xml are set, xml will be used.
+*/
+QString QmlXmlListModel::xml() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->xml;
+}
+
+void QmlXmlListModel::setXml(const QString &xml)
+{
+ Q_D(QmlXmlListModel);
+ d->xml = xml;
+ reload();
+}
+
+/*!
+ \qmlproperty url XmlListModel::query
+ An absolute XPath query representing the base query for the model items. The query should start with
+ a '/' or '//'.
+*/
+QString QmlXmlListModel::query() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->query;
+}
+
+void QmlXmlListModel::setQuery(const QString &query)
+{
+ Q_D(QmlXmlListModel);
+ if (!query.startsWith(QLatin1Char('/'))) {
+ qmlInfo(this) << tr("An XmlListModel query must start with '/' or \"//\"");
+ return;
+ }
+
+ if (d->query != query) {
+ d->query = query;
+ reload();
+ }
+}
+
+/*!
+ \qmlproperty string XmlListModel::namespaceDeclarations
+ A set of declarations for the namespaces used in the query.
+*/
+QString QmlXmlListModel::namespaceDeclarations() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->namespaces;
+}
+
+void QmlXmlListModel::setNamespaceDeclarations(const QString &declarations)
+{
+ Q_D(QmlXmlListModel);
+ if (d->namespaces != declarations) {
+ d->namespaces = declarations;
+ reload();
+ }
+}
+
+/*!
+ \qmlproperty enum XmlListModel::status
+
+ This property holds the status of data source loading. It can be one of:
+ \list
+ \o Null - no data source has been set
+ \o Ready - nthe data source has been loaded
+ \o Loading - the data source is currently being loaded
+ \o Error - an error occurred while loading the data source
+ \endlist
+
+ \sa progress
+
+*/
+QmlXmlListModel::Status QmlXmlListModel::status() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->status;
+}
+
+/*!
+ \qmlproperty real XmlListModel::progress
+
+ This property holds the progress of data source loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+qreal QmlXmlListModel::progress() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->progress;
+}
+
+void QmlXmlListModel::classBegin()
+{
+ Q_D(QmlXmlListModel);
+ d->isComponentComplete = false;
+}
+
+void QmlXmlListModel::componentComplete()
+{
+ Q_D(QmlXmlListModel);
+ d->isComponentComplete = true;
+ reload();
+}
+
+/*!
+ \qmlmethod XmlListModel::reload()
+
+ Reloads the model. All the existing model data will be removed, and the model
+ will be rebuilt from scratch.
+*/
+void QmlXmlListModel::reload()
+{
+ Q_D(QmlXmlListModel);
+
+ if (!d->isComponentComplete)
+ return;
+
+ d->qmlXmlQuery.abort();
+ d->queryId = -1;
+
+ //clear existing data
+ int count = d->size;
+ d->size = 0;
+ d->data.clear();
+ if (count > 0)
+ emit itemsRemoved(0, count);
+
+ if (d->src.isEmpty() && d->xml.isEmpty())
+ return;
+
+ if (d->reply) {
+ d->reply->abort();
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+
+ if (!d->xml.isEmpty()) {
+ d->queryId = d->qmlXmlQuery.doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects);
+ d->progress = 1.0;
+ d->status = Ready;
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+ return;
+ }
+
+ d->progress = 0.0;
+ d->status = Loading;
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+
+ QNetworkRequest req(d->src);
+ d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished()));
+ QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+}
+
+void QmlXmlListModel::requestFinished()
+{
+ Q_D(QmlXmlListModel);
+ if (d->reply->error() != QNetworkReply::NoError) {
+ disconnect(d->reply, 0, this, 0);
+ d->reply->deleteLater();
+ d->reply = 0;
+ d->status = Error;
+ } else {
+ d->status = Ready;
+ QByteArray data = d->reply->readAll();
+ d->queryId = d->qmlXmlQuery.doQuery(d->query, d->namespaces, data, &d->roleObjects);
+ disconnect(d->reply, 0, this, 0);
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+}
+
+void QmlXmlListModel::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QmlXmlListModel);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
+
+void QmlXmlListModel::queryCompleted(int id, int size)
+{
+ Q_D(QmlXmlListModel);
+ if (id != d->queryId)
+ return;
+ d->size = size;
+ if (size > 0) {
+ d->data = d->qmlXmlQuery.modelData();
+ emit itemsInserted(0, d->size);
+ emit countChanged();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include <qmlxmllistmodel.moc>
diff --git a/src/declarative/util/qmlxmllistmodel_p.h b/src/declarative/util/qmlxmllistmodel_p.h
new file mode 100644
index 0000000..e4b8cab
--- /dev/null
+++ b/src/declarative/util/qmlxmllistmodel_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLXMLLISTMODEL_H
+#define QMLXMLLISTMODEL_H
+
+#include <qml.h>
+#include <qmlinfo.h>
+
+#include "../3rdparty/qlistmodelinterface_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlContext;
+
+class QmlXmlListModelRole;
+
+class QmlXmlListModelPrivate;
+class Q_DECLARATIVE_EXPORT QmlXmlListModel : public QListModelInterface, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource)
+ Q_PROPERTY(QString xml READ xml WRITE setXml)
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(QString namespaceDeclarations READ namespaceDeclarations WRITE setNamespaceDeclarations)
+ Q_PROPERTY(QmlList<QmlXmlListModelRole *> *roles READ roleObjects)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_CLASSINFO("DefaultProperty", "roles")
+
+public:
+ QmlXmlListModel(QObject *parent = 0);
+ ~QmlXmlListModel();
+
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual QVariant data(int index, int role) const;
+ virtual int count() const;
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+
+ QmlList<QmlXmlListModelRole *> *roleObjects();
+
+ QUrl source() const;
+ void setSource(const QUrl&);
+
+ QString xml() const;
+ void setXml(const QString&);
+
+ QString query() const;
+ void setQuery(const QString&);
+
+ QString namespaceDeclarations() const;
+ void setNamespaceDeclarations(const QString&);
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ virtual void classBegin();
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void statusChanged(Status);
+ void progressChanged(qreal progress);
+ void countChanged();
+
+public Q_SLOTS:
+ // ### need to use/expose Expiry to guess when to call this?
+ // ### property to auto-call this on reasonable Expiry?
+ // ### LastModified/Age also useful to guess.
+ // ### Probably also applies to other network-requesting types.
+ void reload();
+
+private Q_SLOTS:
+ void requestFinished();
+ void requestProgress(qint64,qint64);
+ void queryCompleted(int,int);
+
+private:
+ Q_DECLARE_PRIVATE(QmlXmlListModel)
+ Q_DISABLE_COPY(QmlXmlListModel)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlXmlListModel)
+
+QT_END_HEADER
+
+#endif // QMLXMLLISTMODEL_H
diff --git a/src/declarative/util/qnumberformat.cpp b/src/declarative/util/qnumberformat.cpp
new file mode 100644
index 0000000..fd44db1
--- /dev/null
+++ b/src/declarative/util/qnumberformat.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnumberformat_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_NOCREATE_TYPE(QNumberFormat)
+
+QNumberFormat::QNumberFormat(QObject *parent) : QObject(parent), _number(0), _type(Decimal),
+ _groupingSize(0)
+{
+ _locale = QLocale::system();
+ _groupingSeparator = _locale.groupSeparator();
+ _decimalSeparator = _locale.decimalPoint();
+ _currencySymbol = QLatin1Char('$');
+}
+
+QNumberFormat::~QNumberFormat()
+{
+
+}
+
+void QNumberFormat::updateText()
+{
+ QTime t;
+ t.start();
+ static int totalTime;
+
+ handleFormat();
+
+ totalTime += t.elapsed();
+ emit textChanged();
+}
+
+void QNumberFormat::handleFormat()
+{
+ // ### is extremely messy
+ if (_format.isEmpty()) {
+ _text = QString::number(_number, 'f', -1);
+ return;
+ }
+
+ QString inputString;
+
+ // ### possible to use the following parsed data in the future
+
+ int remainingLength = _format.size();
+ int currentIndex = _format.size()-1;
+
+ int maxDigits = 0;
+ int minDigits = 0;
+ int decimalLength = 0;
+
+ while (remainingLength > 0) {
+ switch(_format.at(currentIndex).unicode()) {
+ case ',':
+ if (decimalLength && !_groupingSize)
+ setGroupingSize(maxDigits - decimalLength);
+ else if (!_groupingSize)
+ setGroupingSize(maxDigits);
+ break;
+ case '.':
+ if (!decimalLength)
+ decimalLength = maxDigits;
+ break;
+ case '0':
+ minDigits++;
+ case '#':
+ maxDigits++;
+ break;
+ default:
+ break;
+ }
+ currentIndex--;
+ remainingLength--;
+ }
+
+ // round given the decimal length/precision
+ inputString = QString::number(_number, 'f', decimalLength);
+
+ QStringList parts = inputString.split(QLatin1Char('.'));
+ QStringList formatParts = _format.split(QLatin1Char('.'));
+
+ if (formatParts.size() > 2 || parts.size() > 2 )
+ return;
+
+ QString formatInt = formatParts.at(0);
+
+ QString formatDec;
+ if (formatParts.size() == 2)
+ formatDec = formatParts.at(1);
+
+ QString integer = parts.at(0);
+
+ QString decimal;
+ if (parts.size() == 2)
+ decimal = parts.at(1);
+
+ QString outputDecimal = formatDecimal(formatDec, decimal);
+ QString outputInteger = formatInteger(formatInt, integer);
+
+ // insert separators
+ if (_groupingSize) {
+ unsigned int count = 0;
+ for (int i = outputInteger.size()-1; i > 0; i--) {
+ if (outputInteger.at(i).digitValue() >= 0) {
+ if (count == _groupingSize - 1) {
+ count = 0;
+ outputInteger.insert(i, _groupingSeparator);
+ }
+ else
+ count++;
+ }
+ }
+ }
+ if (!outputDecimal.isEmpty())
+ _text = outputInteger + _decimalSeparator + outputDecimal;
+ else
+ _text = outputInteger;
+}
+
+QString QNumberFormat::formatInteger(const QString &formatInt, const QString &integer)
+{
+ if (formatInt.isEmpty() || integer.isEmpty())
+ return QString();
+
+ QString outputInteger;
+ int formatIndex = formatInt.size()-1;
+
+ //easier for carry?
+ for (int index= integer.size()-1; index >= 0; index--) {
+ if (formatIndex < 0) {
+ outputInteger.push_front(integer.at(index));
+ }
+ else {
+ switch(formatInt.at(formatIndex).unicode()) {
+ case '0':
+ if (index > integer.size()-1) {
+ outputInteger.push_front(QLatin1Char('0'));
+ break;
+ }
+ case '#':
+ outputInteger.push_front(integer.at(index));
+ break;
+ case ',':
+ index++;
+ break;
+ default:
+ outputInteger.push_front(formatInt.at(formatIndex));
+ index++;
+ break;
+ }
+ formatIndex--;
+ }
+ }
+ while (formatIndex >= 0) {
+ if (formatInt.at(formatIndex).unicode() != '#' && formatInt.at(formatIndex).unicode() != ',')
+ outputInteger.push_front(formatInt.at(formatIndex));
+ formatIndex--;
+ }
+ return outputInteger;
+}
+
+QString QNumberFormat::formatDecimal(const QString &formatDec, const QString &decimal)
+{
+ QString outputDecimal;
+
+ // up to max 6 decimal places
+ for (int index=formatDec.size()-1; index >= 0; index--) {
+ switch(formatDec.at(index).unicode()) {
+ case '0':
+ outputDecimal.push_front(decimal.at(index));
+ break;
+ case '#':
+ if (decimal.at(index) != QLatin1Char('0') || outputDecimal.size() > 0)
+ outputDecimal.push_front(decimal.at(index));
+ break;
+ default:
+ outputDecimal.push_front(formatDec.at(index));
+ break;
+ }
+ }
+ return outputDecimal;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qnumberformat_p.h b/src/declarative/util/qnumberformat_p.h
new file mode 100644
index 0000000..c73ef8a
--- /dev/null
+++ b/src/declarative/util/qnumberformat_p.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NUMBERFORMAT_H
+#define NUMBERFORMAT_H
+
+#include <qml.h>
+
+#include <QtCore/QLocale>
+#include <QtCore/QTime>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+// TODO
+// be able to set Locale, instead of default system for dynamic formatting
+// add currency support
+// add additional syntax, extend to format scientific, percentiles, significant digits etc
+
+
+class QNumberFormat : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(NumberType)
+public:
+ QNumberFormat(QObject *parent=0);
+ ~QNumberFormat();
+
+ enum NumberType {
+ Percent,
+ Scientific,
+ Currency,
+ Decimal
+ };
+
+ //external property, only visible
+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
+
+ //mutatable properties to modify the output (text)
+ Q_PROPERTY(qreal number READ number WRITE setNumber)
+ Q_PROPERTY(QString format READ format WRITE setFormat)
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale)
+
+ //Format specific settings
+ Q_PROPERTY(unsigned short groupingSeparator READ groupingSeparator WRITE setGroupingSeparator)
+ Q_PROPERTY(unsigned short decimalSeperator READ decimalSeparator WRITE setDecimalSeparator)
+ Q_PROPERTY(unsigned int groupingSize READ groupingSize WRITE setGroupingSize)
+ Q_PROPERTY(unsigned short currencySymbol READ currencySymbol WRITE setCurrencySymbol)
+
+
+ QString text() const { return _text; }
+
+ qreal number() const { return _number; }
+ void setNumber(qreal n) {
+ if (_number == n)
+ return;
+ _number = n;
+ updateText();
+ }
+
+ QString format() const { return _format; }
+ void setFormat(const QString &format) {
+ if (format.isEmpty())
+ _format = QString::null;
+ else if (_format == format)
+ return;
+
+ _format = format;
+ updateText();
+ }
+
+ QLocale locale() const { return _locale; }
+ void setLocale(const QLocale &locale) { _locale = locale; updateText(); }
+
+ //Do we deal with unicode standard? or create our own
+ // ### since this is the backend for the number conversions, we will use the unicode
+ // the front-end will handle the QChar/QString -> short int
+
+ unsigned short groupingSeparator() { return _groupingSeparator.unicode(); }
+ void setGroupingSeparator(unsigned short unicodeSymbol)
+ {
+ _groupingSeparator = QChar(unicodeSymbol);
+ }
+
+ unsigned short decimalSeparator() { return _decimalSeparator.unicode(); }
+ void setDecimalSeparator(unsigned short unicodeSymbol)
+ {
+ _decimalSeparator = QChar(unicodeSymbol);
+ }
+
+ unsigned short currencySymbol() { return _currencySymbol.unicode(); }
+ void setCurrencySymbol(unsigned short unicodeSymbol)
+ {
+ _currencySymbol = QChar(unicodeSymbol);
+ }
+
+ unsigned int groupingSize() { return _groupingSize; }
+ void setGroupingSize(unsigned int size)
+ {
+ _groupingSize = size;
+ }
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ void updateText();
+ void handleFormat();
+ QString formatInteger(const QString &formatInt, const QString &integer);
+ QString formatDecimal(const QString &formatDec, const QString &decimal);
+
+ qreal _number;
+ NumberType _type;
+ QChar _groupingSeparator;
+ QChar _decimalSeparator;
+ QChar _currencySymbol;
+ unsigned int _groupingSize;
+
+ QLocale _locale;
+ QString _format;
+
+ // only hooked member at the moment
+ QString _text;
+
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QNumberFormat)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qperformancelog.cpp b/src/declarative/util/qperformancelog.cpp
new file mode 100644
index 0000000..2f91dfb
--- /dev/null
+++ b/src/declarative/util/qperformancelog.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qperformancelog_p_p.h"
+
+#include <QHash>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+
+struct QPerformanceLogData
+{
+ struct Log
+ {
+ Log()
+ : logDescription(0), maxId(-1) {}
+
+ QHash<int, const char *> descriptions;
+ const char *logDescription;
+ int maxId;
+ };
+
+ typedef QHash<QPerformanceLog::LogData *, Log> Logs;
+ Logs logs;
+};
+Q_GLOBAL_STATIC(QPerformanceLogData, performanceLogData);
+
+QPerformanceLog::LogData::LogData(const char *desc)
+: sumTime(0), data(0)
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ QPerformanceLogData::Log log;
+ log.logDescription = desc;
+ logData->logs.insert(this, log);
+
+ timer.start();
+}
+
+QPerformanceLog::LogMetric::LogMetric(LogData *l, int id, const char *desc)
+{
+ if (id < 0)
+ qFatal("QPerformanceLog: Invalid log id %d ('%s')", id, desc);
+
+ QPerformanceLogData *logData = performanceLogData();
+
+ QPerformanceLogData::Logs::Iterator logIter = logData->logs.find(l);
+ if (logIter == logData->logs.end())
+ qFatal("QPerformanceLog: Unable to locate log for metric '%s'", desc);
+ QPerformanceLogData::Log &log = *logIter;
+ if (log.descriptions.contains(id))
+ qFatal("QPerformanceLog: Duplicate log metric %d ('%s')", id, desc);
+ log.descriptions.insert(id, desc);
+
+ if (log.maxId < id) {
+ log.maxId = id;
+ if (l->data) delete [] l->data;
+ l->data = new unsigned int[2 * (log.maxId + 1)];
+ ::memset(l->data, 0, 2 * (log.maxId + 1) * sizeof(unsigned int));
+ }
+}
+
+static void QPerformanceLog_clear(QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl)
+{
+ ::memset(l->data, 0, 2 * (pl->maxId + 1) * sizeof(unsigned int));
+}
+
+static void QPerformanceLog_displayData(const QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl)
+{
+ qWarning() << pl->logDescription << "performance data";
+ unsigned int total = 0;
+ for (QHash<int, const char *>::ConstIterator iter = pl->descriptions.begin();
+ iter != pl->descriptions.end();
+ ++iter) {
+
+ int id = iter.key();
+ unsigned int ms = l->data[id * 2];
+ total += ms;
+ unsigned int inst = l->data[id * 2 + 1];
+ float pi = float(ms) / float(inst);
+ qWarning().nospace() << " " << *iter << ": " << ms << " ms over "
+ << inst << " instances (" << pi << " ms/instance)";
+ }
+ qWarning().nospace() << " TOTAL: " << total;
+}
+
+void QPerformanceLog::displayData()
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ for (QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin();
+ iter != logData->logs.end();
+ ++iter) {
+ QPerformanceLog_displayData(iter.key(), &(*iter));
+ }
+}
+
+void QPerformanceLog::clear()
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ for (QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin();
+ iter != logData->logs.end();
+ ++iter) {
+ QPerformanceLog_clear(iter.key(), &(*iter));
+ }
+}
+
+void QPerformanceLog::displayData(LogData *l)
+{
+ QPerformanceLogData *logData = performanceLogData();
+ QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l);
+ if (iter == logData->logs.end())
+ qFatal("QPerformanceLog: Internal corruption - unable to locate log");
+
+ QPerformanceLog_displayData(iter.key(), &(*iter));
+}
+
+void QPerformanceLog::clear(LogData *l)
+{
+ QPerformanceLogData *logData = performanceLogData();
+ QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l);
+ if (iter == logData->logs.end())
+ qFatal("QPerformanceLog: Internal corruption - unable to locate log");
+
+ QPerformanceLog_clear(iter.key(), &(*iter));
+}
+
+#else // Q_ENABLE_PERFORMANCE_LOG
+
+void QPerformanceLog::displayData()
+{
+}
+
+void QPerformanceLog::clear()
+{
+}
+
+#endif // Q_ENABLE_PERFORMANCE_LOG
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qperformancelog_p_p.h b/src/declarative/util/qperformancelog_p_p.h
new file mode 100644
index 0000000..e7a3b5e
--- /dev/null
+++ b/src/declarative/util/qperformancelog_p_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPERFORMANCELOG_H
+#define QPERFORMANCELOG_H
+
+#include <QtCore/qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QPerformanceLog
+{
+ Q_DECLARATIVE_EXPORT void displayData();
+ Q_DECLARATIVE_EXPORT void clear();
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ struct LogData {
+ LogData(const char *);
+ QTime timer;
+ int sumTime;
+ unsigned int *data;
+ };
+
+ struct LogMetric {
+ LogMetric(LogData *, int, const char *);
+ };
+
+ // Internal
+ void displayData(LogData *);
+ void clear(LogData *);
+#endif
+}
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+
+#define Q_DECLARE_PERFORMANCE_METRIC(name) \
+ enum { name = ValueChoice<0, ValueTracker<0, __LINE__>::value, __LINE__>::value }; \
+ template<int L> \
+ struct ValueTracker<name, L> \
+ { \
+ enum { value = name }; \
+ }; \
+ extern QPerformanceLog::LogMetric metric ## name;
+
+#define Q_DECLARE_PERFORMANCE_LOG(name) \
+ namespace name { \
+ extern QPerformanceLog::LogData log; \
+ inline void displayData() { QPerformanceLog::displayData(&log); } \
+ inline void clear() { QPerformanceLog::clear(&log); } \
+ } \
+ template<int N> \
+ class name ## Timer { \
+ public: \
+ name ## Timer() { \
+ lastSum = name::log.sumTime + name::log.timer.restart(); \
+ name::log.sumTime = 0; \
+ } \
+ ~ name ## Timer() { \
+ name::log.data[2 * N] += name::log.sumTime + name::log.timer.restart(); \
+ ++name::log.data[2 * N + 1]; \
+ name::log.sumTime = lastSum; \
+ } \
+ private: \
+ int lastSum; \
+ }; \
+ namespace name { \
+ template<int N, int L> \
+ struct ValueTracker \
+ { \
+ enum { value = -1 }; \
+ }; \
+ template<int DefNextValue, int NextValue, int L> \
+ struct ValueChoice \
+ { \
+ enum { value = ValueChoice<DefNextValue + 1, ValueTracker<DefNextValue + 1, L>::value, L>::value }; \
+ }; \
+ template<int DefNextValue, int L> \
+ struct ValueChoice<DefNextValue, -1, L> \
+ { \
+ enum { value = DefNextValue }; \
+ }; \
+ } \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_LOG(name, desc) \
+ QPerformanceLog::LogData name::log(desc); \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_METRIC(name, desc) \
+ QPerformanceLog::LogMetric metrix ## name(&log, name, desc);
+
+#else // Q_ENABLE_PERFORMANCE_LOG
+
+#define Q_DECLARE_PERFORMANCE_METRIC(name)
+#define Q_DECLARE_PERFORMANCE_LOG(name) namespace name
+#define Q_DEFINE_PERFORMANCE_LOG(name, desc) namespace name
+#define Q_DEFINE_PERFORMANCE_METRIC(name, desc)
+
+#endif // Q_ENABLE_PERFORMANCE_LOG
+
+QT_END_NAMESPACE
+
+#endif // QPERFORMANCELOG_H
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
new file mode 100644
index 0000000..b6a5c90
--- /dev/null
+++ b/src/declarative/util/util.pri
@@ -0,0 +1,72 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qmlview.cpp \
+ $$PWD/qfxperf.cpp \
+ $$PWD/qperformancelog.cpp \
+ $$PWD/qmlconnection.cpp \
+ $$PWD/qmlpackage.cpp \
+ $$PWD/qmlanimation.cpp \
+ $$PWD/qmlsystempalette.cpp \
+ $$PWD/qmlspringfollow.cpp \
+ $$PWD/qmleasefollow.cpp \
+ $$PWD/qmlstate.cpp\
+ $$PWD/qmltransitionmanager.cpp \
+ $$PWD/qmlstateoperations.cpp \
+ $$PWD/qmlpropertychanges.cpp \
+ $$PWD/qmlstategroup.cpp \
+ $$PWD/qmltransition.cpp \
+ $$PWD/qmllistmodel.cpp\
+ $$PWD/qmllistaccessor.cpp \
+ $$PWD/qmlopenmetaobject.cpp \
+ $$PWD/qmltimeline.cpp \
+ $$PWD/qmltimer.cpp \
+ $$PWD/qmlbind.cpp \
+ $$PWD/qmlpropertymap.cpp \
+ $$PWD/qmlpixmapcache.cpp \
+ $$PWD/qnumberformat.cpp \
+ $$PWD/qmlnumberformatter.cpp \
+ $$PWD/qmldatetimeformatter.cpp \
+ $$PWD/qmlbehavior.cpp \
+ $$PWD/qmlfontloader.cpp \
+ $$PWD/qmlstyledtext.cpp
+
+HEADERS += \
+ $$PWD/qmlview.h \
+ $$PWD/qfxperf_p_p.h \
+ $$PWD/qperformancelog_p_p.h \
+ $$PWD/qmlconnection_p.h \
+ $$PWD/qmlpackage_p.h \
+ $$PWD/qmlanimation_p.h \
+ $$PWD/qmlanimation_p_p.h \
+ $$PWD/qmlsystempalette_p.h \
+ $$PWD/qmlspringfollow_p.h \
+ $$PWD/qmleasefollow_p.h \
+ $$PWD/qmlstate_p.h\
+ $$PWD/qmlstateoperations_p.h \
+ $$PWD/qmlpropertychanges_p.h \
+ $$PWD/qmlstate_p_p.h\
+ $$PWD/qmltransitionmanager_p_p.h \
+ $$PWD/qmlstategroup_p.h \
+ $$PWD/qmltransition_p.h \
+ $$PWD/qmllistmodel_p.h\
+ $$PWD/qmllistaccessor_p.h \
+ $$PWD/qmlopenmetaobject_p.h \
+ $$PWD/qmlnullablevalue_p_p.h \
+ $$PWD/qmltimeline_p_p.h \
+ $$PWD/qmltimer_p.h \
+ $$PWD/qmlbind_p.h \
+ $$PWD/qmlpropertymap.h \
+ $$PWD/qmlpixmapcache_p.h \
+ $$PWD/qnumberformat_p.h \
+ $$PWD/qmlnumberformatter_p.h \
+ $$PWD/qmldatetimeformatter_p.h \
+ $$PWD/qmlbehavior_p.h \
+ $$PWD/qmlfontloader_p.h \
+ $$PWD/qmlstyledtext_p.h
+
+contains(QT_CONFIG, xmlpatterns) {
+ QT+=xmlpatterns
+ SOURCES += $$PWD/qmlxmllistmodel.cpp
+ HEADERS += $$PWD/qmlxmllistmodel_p.h
+}
diff --git a/src/declarative/widgets/graphicslayouts.cpp b/src/declarative/widgets/graphicslayouts.cpp
new file mode 100644
index 0000000..065040f
--- /dev/null
+++ b/src/declarative/widgets/graphicslayouts.cpp
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicslayouts_p.h"
+
+#include <QtGui/qgraphicswidget.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_INTERFACE(QGraphicsLayoutItem)
+QML_DEFINE_INTERFACE(QGraphicsLayout)
+
+QML_DEFINE_TYPE(Qt,4,6,QGraphicsLinearLayoutStretchItem,QGraphicsLinearLayoutStretchItemObject)
+QML_DEFINE_TYPE(Qt,4,6,QGraphicsLinearLayout,QGraphicsLinearLayoutObject)
+QML_DEFINE_TYPE(Qt,4,6,QGraphicsGridLayout,QGraphicsGridLayoutObject)
+
+class LinearLayoutAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int stretchFactor READ stretchFactor WRITE setStretchFactor NOTIFY stretchChanged)
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged)
+public:
+ LinearLayoutAttached(QObject *parent)
+ : QObject(parent), _stretch(1), _alignment(Qt::AlignCenter)
+ {
+ }
+
+ int stretchFactor() const { return _stretch; }
+ void setStretchFactor(int f)
+ {
+ if (_stretch == f)
+ return;
+
+ _stretch = f;
+ emit stretchChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _stretch);
+ }
+
+ Qt::Alignment alignment() const { return _alignment; }
+ void setAlignment(Qt::Alignment a)
+ {
+ if (_alignment == a)
+ return;
+
+ _alignment = a;
+ emit alignmentChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _alignment);
+ }
+
+Q_SIGNALS:
+ void stretchChanged(QGraphicsLayoutItem*,int);
+ void alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ int _stretch;
+ Qt::Alignment _alignment;
+};
+
+
+QGraphicsLinearLayoutStretchItemObject::QGraphicsLinearLayoutStretchItemObject(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QSizeF QGraphicsLinearLayoutStretchItemObject::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ return QSizeF();
+}
+
+
+QGraphicsLinearLayoutObject::QGraphicsLinearLayoutObject(QObject *parent)
+: QObject(parent), _children(this)
+{
+}
+
+QGraphicsLinearLayoutObject::~QGraphicsLinearLayoutObject()
+{
+}
+
+void QGraphicsLinearLayoutObject::insertLayoutItem(int index, QGraphicsLayoutItem *item)
+{
+ insertItem(index, item);
+
+ //connect attached properties
+ if (LinearLayoutAttached *obj = attachedProperties.value(item)) {
+ setStretchFactor(item, obj->stretchFactor());
+ setAlignment(item, obj->alignment());
+ QObject::connect(obj, SIGNAL(stretchChanged(QGraphicsLayoutItem*,int)),
+ this, SLOT(updateStretch(QGraphicsLayoutItem*,int)));
+ QObject::connect(obj, SIGNAL(alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment)),
+ this, SLOT(updateAlignment(QGraphicsLayoutItem*,Qt::Alignment)));
+ //### need to disconnect when widget is removed?
+ }
+}
+
+//### is there a better way to do this?
+void QGraphicsLinearLayoutObject::clearChildren()
+{
+ for (int i = 0; i < count(); ++i)
+ removeAt(i);
+}
+
+void QGraphicsLinearLayoutObject::updateStretch(QGraphicsLayoutItem *item, int stretch)
+{
+ QGraphicsLinearLayout::setStretchFactor(item, stretch);
+}
+
+void QGraphicsLinearLayoutObject::updateAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment)
+{
+ QGraphicsLinearLayout::setAlignment(item, alignment);
+}
+
+QHash<QGraphicsLayoutItem*, LinearLayoutAttached*> QGraphicsLinearLayoutObject::attachedProperties;
+LinearLayoutAttached *QGraphicsLinearLayoutObject::qmlAttachedProperties(QObject *obj)
+{
+ // ### This is not allowed - you must attach to any object
+ if (!qobject_cast<QGraphicsLayoutItem*>(obj))
+ return 0;
+ LinearLayoutAttached *rv = new LinearLayoutAttached(obj);
+ attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv);
+ return rv;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// QGraphicsGridLayout-related classes
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+class GridLayoutAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int row READ row WRITE setRow)
+ Q_PROPERTY(int column READ column WRITE setColumn)
+ Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan)
+ Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan)
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment)
+public:
+ GridLayoutAttached(QObject *parent)
+ : QObject(parent), _row(-1), _column(-1), _rowspan(1), _colspan(1), _alignment(-1)
+ {
+ }
+
+ int row() const { return _row; }
+ void setRow(int r)
+ {
+ if (_row == r)
+ return;
+
+ _row = r;
+ //emit rowChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _row);
+ }
+
+ int column() const { return _column; }
+ void setColumn(int c)
+ {
+ if (_column == c)
+ return;
+
+ _column = c;
+ //emit columnChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _column);
+ }
+
+ int rowSpan() const { return _rowspan; }
+ void setRowSpan(int rs)
+ {
+ if (_rowspan == rs)
+ return;
+
+ _rowspan = rs;
+ //emit rowSpanChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _rowSpan);
+ }
+
+ int columnSpan() const { return _colspan; }
+ void setColumnSpan(int cs)
+ {
+ if (_colspan == cs)
+ return;
+
+ _colspan = cs;
+ //emit columnSpanChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _columnSpan);
+ }
+
+ Qt::Alignment alignment() const { return _alignment; }
+ void setAlignment(Qt::Alignment a)
+ {
+ if (_alignment == a)
+ return;
+
+ _alignment = a;
+ //emit alignmentChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _alignment);
+ }
+
+Q_SIGNALS:
+ //void rowChanged(QGraphicsLayoutItem*,int);
+ //void columnSpanChanged(QGraphicsLayoutItem*,int);
+ //void rowSpanChanged(QGraphicsLayoutItem*,int);
+ //void columnChanged(QGraphicsLayoutItem*,int);
+ //void alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ int _row;
+ int _column;
+ int _rowspan;
+ int _colspan;
+ Qt::Alignment _alignment;
+};
+
+
+QGraphicsGridLayoutObject::QGraphicsGridLayoutObject(QObject *parent)
+: QObject(parent), _children(this)
+{
+}
+
+QGraphicsGridLayoutObject::~QGraphicsGridLayoutObject()
+{
+}
+
+void QGraphicsGridLayoutObject::addWidget(QGraphicsWidget *wid)
+{
+ //use attached properties
+ if (QObject *obj = attachedProperties.value(qobject_cast<QGraphicsLayoutItem*>(wid))) {
+ int row = static_cast<GridLayoutAttached *>(obj)->row();
+ int column = static_cast<GridLayoutAttached *>(obj)->column();
+ int rowSpan = static_cast<GridLayoutAttached *>(obj)->rowSpan();
+ int columnSpan = static_cast<GridLayoutAttached *>(obj)->columnSpan();
+ if (row == -1 || column == -1) {
+ qWarning() << "Must set row and column for an item in a grid layout";
+ return;
+ }
+ addItem(wid, row, column, rowSpan, columnSpan);
+ }
+}
+
+void QGraphicsGridLayoutObject::addLayoutItem(QGraphicsLayoutItem *item)
+{
+ //use attached properties
+ if (GridLayoutAttached *obj = attachedProperties.value(item)) {
+ int row = obj->row();
+ int column = obj->column();
+ int rowSpan = obj->rowSpan();
+ int columnSpan = obj->columnSpan();
+ Qt::Alignment alignment = obj->alignment();
+ if (row == -1 || column == -1) {
+ qWarning() << "Must set row and column for an item in a grid layout";
+ return;
+ }
+ addItem(item, row, column, rowSpan, columnSpan);
+ if (alignment != -1)
+ setAlignment(item,alignment);
+ }
+}
+
+//### is there a better way to do this?
+void QGraphicsGridLayoutObject::clearChildren()
+{
+ for (int i = 0; i < count(); ++i)
+ removeAt(i);
+}
+
+qreal QGraphicsGridLayoutObject::spacing() const
+{
+ if (verticalSpacing() == horizontalSpacing())
+ return verticalSpacing();
+ return -1; //###
+}
+
+QHash<QGraphicsLayoutItem*, GridLayoutAttached*> QGraphicsGridLayoutObject::attachedProperties;
+GridLayoutAttached *QGraphicsGridLayoutObject::qmlAttachedProperties(QObject *obj)
+{
+ // ### This is not allowed - you must attach to any object
+ if (!qobject_cast<QGraphicsLayoutItem*>(obj))
+ return 0;
+ GridLayoutAttached *rv = new GridLayoutAttached(obj);
+ attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv);
+ return rv;
+}
+
+QT_END_NAMESPACE
+
+#include <graphicslayouts.moc>
diff --git a/src/declarative/widgets/graphicslayouts_p.h b/src/declarative/widgets/graphicslayouts_p.h
new file mode 100644
index 0000000..34e2556
--- /dev/null
+++ b/src/declarative/widgets/graphicslayouts_p.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHICSLAYOUTS_H
+#define GRAPHICSLAYOUTS_H
+
+#include "graphicswidgets_p.h"
+
+#include <QtGui/QGraphicsLinearLayout>
+#include <QtGui/QGraphicsGridLayout>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QGraphicsLinearLayoutStretchItemObject : public QObject, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+public:
+ QGraphicsLinearLayoutStretchItemObject(QObject *parent = 0);
+
+ virtual QSizeF sizeHint(Qt::SizeHint, const QSizeF &) const;
+};
+
+class LinearLayoutAttached;
+class QGraphicsLinearLayoutObject : public QObject, public QGraphicsLinearLayout
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayout QGraphicsLayoutItem)
+
+ Q_PROPERTY(QmlList<QGraphicsLayoutItem *> *children READ children)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsLinearLayoutObject(QObject * = 0);
+ ~QGraphicsLinearLayoutObject();
+
+ QmlList<QGraphicsLayoutItem *> *children() { return &_children; }
+
+ static LinearLayoutAttached *qmlAttachedProperties(QObject *);
+
+private Q_SLOTS:
+ void updateStretch(QGraphicsLayoutItem*,int);
+ void updateAlignment(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ friend class LinearLayoutAttached;
+ void clearChildren();
+ void insertLayoutItem(int, QGraphicsLayoutItem *);
+ static QHash<QGraphicsLayoutItem*, LinearLayoutAttached*> attachedProperties;
+
+ class ChildList : public QmlList<QGraphicsLayoutItem *>
+ {
+ public:
+ ChildList(QGraphicsLinearLayoutObject *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsLayoutItem *item)
+ {
+ insert(-1, item);
+ }
+ virtual void clear() { obj->clearChildren(); }
+ virtual int count() const { return obj->count(); }
+ virtual void removeAt(int i) { obj->removeAt(i); }
+ virtual QGraphicsLayoutItem *at(int i) const { return obj->itemAt(i); }
+ virtual void insert(int i, QGraphicsLayoutItem *item) { obj->insertLayoutItem(i, item); }
+
+ private:
+ QGraphicsLinearLayoutObject *obj;
+ };
+
+ ChildList _children;
+};
+
+class GridLayoutAttached;
+class QGraphicsGridLayoutObject : public QObject, public QGraphicsGridLayout
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayout QGraphicsLayoutItem)
+
+ Q_PROPERTY(QmlList<QGraphicsLayoutItem *> *children READ children)
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing)
+ Q_PROPERTY(qreal verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
+ Q_PROPERTY(qreal horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsGridLayoutObject(QObject * = 0);
+ ~QGraphicsGridLayoutObject();
+
+ QmlList<QGraphicsLayoutItem *> *children() { return &_children; }
+
+ qreal spacing() const;
+
+ static GridLayoutAttached *qmlAttachedProperties(QObject *);
+
+private:
+ friend class GraphicsLayoutAttached;
+ void addWidget(QGraphicsWidget *);
+ void clearChildren();
+ void addLayoutItem(QGraphicsLayoutItem *);
+ static QHash<QGraphicsLayoutItem*, GridLayoutAttached*> attachedProperties;
+
+ class ChildList : public QmlList<QGraphicsLayoutItem *>
+ {
+ public:
+ ChildList(QGraphicsGridLayoutObject *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsLayoutItem *o)
+ {
+ obj->addLayoutItem(o);
+ }
+ virtual void clear() { obj->clearChildren(); }
+ virtual int count() const { return obj->count(); }
+ virtual void removeAt(int i) { obj->removeAt(i); }
+ virtual QGraphicsLayoutItem *at(int i) const { return obj->itemAt(i); }
+ //### GridLayout doesn't have an insert, so for now we treat it as an append.
+ // this is obviously potenitally dangerous -- perhaps should be a concrete
+ // list with no relation to layout index, etc at all.
+ virtual void insert(int, QGraphicsLayoutItem *item) { append(item); }
+
+ private:
+ QGraphicsGridLayoutObject *obj;
+ };
+
+ ChildList _children;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_INTERFACE(QGraphicsLayoutItem)
+QML_DECLARE_INTERFACE(QGraphicsLayout)
+QML_DECLARE_TYPE(QGraphicsLinearLayoutStretchItemObject)
+QML_DECLARE_TYPE(QGraphicsLinearLayoutObject)
+QML_DECLARE_TYPEINFO(QGraphicsLinearLayoutObject, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QGraphicsGridLayoutObject)
+QML_DECLARE_TYPEINFO(QGraphicsGridLayoutObject, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // GRAPHICSLAYOUTS_H
diff --git a/src/declarative/widgets/graphicswidgets.cpp b/src/declarative/widgets/graphicswidgets.cpp
new file mode 100644
index 0000000..4c13865
--- /dev/null
+++ b/src/declarative/widgets/graphicswidgets.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicswidgets_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsViewDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QGraphicsScene *scene READ scene WRITE setScene)
+ Q_CLASSINFO("DefaultProperty", "scene")
+public:
+ QGraphicsViewDeclarativeUI(QObject *other) : QObject(other) {}
+
+ QGraphicsScene *scene() const { return static_cast<QGraphicsView *>(parent())->scene(); }
+ void setScene(QGraphicsScene *scene)
+ {
+ static_cast<QGraphicsView *>(parent())->setScene(scene);
+ }
+};
+
+class QGraphicsSceneDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QObject *> *children READ children)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsSceneDeclarativeUI(QObject *other) : QObject(other), _children(other) {}
+
+ QmlList<QObject *> *children() { return &_children; }
+
+private:
+ class Children : public QmlConcreteList<QObject *>
+ {
+ public:
+ Children(QObject *scene) : q(scene) {}
+ virtual void append(QObject *o)
+ {
+ insert(-1, o);
+ }
+ virtual void clear()
+ {
+ for (int i = 0; i < count(); ++i)
+ if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(at(i)))
+ static_cast<QGraphicsScene *>(q)->removeItem(go);
+ QmlConcreteList<QObject *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(at(i)))
+ static_cast<QGraphicsScene *>(q)->removeItem(go);
+ QmlConcreteList<QObject *>::removeAt(i);
+ }
+ virtual void insert(int i, QObject *o)
+ {
+ QmlConcreteList<QObject *>::insert(i, o);
+ if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(o))
+ static_cast<QGraphicsScene *>(q)->addItem(go);
+ //else if (QWidget *w = qobject_cast<QWidget *>(o))
+ // static_cast<QGraphicsScene *>(q)->addWidget(w);
+ }
+ private:
+ QObject *q;
+ };
+ Children _children;
+};
+
+class QGraphicsWidgetDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QObject *> *data READ data)
+ Q_PROPERTY(QmlList<QGraphicsItem *> *children READ children)
+ Q_PROPERTY(QGraphicsLayout *layout READ layout WRITE setLayout)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsWidgetDeclarativeUI(QObject *other) : QObject(other), _widgets(this) {}
+
+ QmlList<QObject *> *data() { return &_data; }
+
+ QmlList<QGraphicsItem *> *children() { return &_widgets; }
+
+ QGraphicsLayout *layout() const { return static_cast<QGraphicsWidget *>(parent())->layout(); }
+ void setLayout(QGraphicsLayout *lo)
+ {
+ static_cast<QGraphicsWidget *>(parent())->setLayout(lo);
+ }
+
+private:
+ friend class WidgetList;
+ void setItemParent(QGraphicsItem *wid)
+ {
+ wid->setParentItem(static_cast<QGraphicsWidget *>(parent()));
+ }
+
+ class WidgetList : public QmlConcreteList<QGraphicsItem *>
+ {
+ public:
+ WidgetList(QGraphicsWidgetDeclarativeUI *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsItem *w) { QmlConcreteList<QGraphicsItem *>::append(w); obj->setItemParent(w); }
+ virtual void clear() { QmlConcreteList<QGraphicsItem *>::clear(); } //###
+ virtual void removeAt(int i) { QmlConcreteList<QGraphicsItem *>::removeAt(i); } //###
+ virtual void insert(int i, QGraphicsItem *item) { QmlConcreteList<QGraphicsItem *>::insert(i, item); obj->setItemParent(item); }
+
+ private:
+ QGraphicsWidgetDeclarativeUI *obj;
+ };
+ WidgetList _widgets;
+ QmlConcreteList<QObject *> _data;
+};
+
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QGraphicsView,QGraphicsView,QGraphicsViewDeclarativeUI)
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QGraphicsScene,QGraphicsScene,QGraphicsSceneDeclarativeUI)
+QML_DEFINE_EXTENDED_TYPE(Qt,4,6,QGraphicsWidget,QGraphicsWidget,QGraphicsWidgetDeclarativeUI)
+
+QML_DEFINE_INTERFACE(QGraphicsItem)
+
+QT_END_NAMESPACE
+
+#include <graphicswidgets.moc>
diff --git a/src/declarative/widgets/graphicswidgets_p.h b/src/declarative/widgets/graphicswidgets_p.h
new file mode 100644
index 0000000..0de5c89
--- /dev/null
+++ b/src/declarative/widgets/graphicswidgets_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHICSWIDGETS_H
+#define GRAPHICSWIDGETS_H
+
+#include <qml.h>
+
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QGraphicsView>
+#include <QtGui/QGraphicsWidget>
+#include <QtGui/QGraphicsItem>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QGraphicsView)
+QML_DECLARE_TYPE_HASMETATYPE(QGraphicsScene)
+QML_DECLARE_TYPE(QGraphicsWidget)
+QML_DECLARE_TYPE(QGraphicsObject)
+QML_DECLARE_INTERFACE_HASMETATYPE(QGraphicsItem)
+
+QT_END_HEADER
+
+#endif // GRAPHICSWIDGETS_H
diff --git a/src/declarative/widgets/widgets.pri b/src/declarative/widgets/widgets.pri
new file mode 100644
index 0000000..4cae3ff
--- /dev/null
+++ b/src/declarative/widgets/widgets.pri
@@ -0,0 +1,9 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/graphicswidgets.cpp \
+ $$PWD/graphicslayouts.cpp
+
+HEADERS += \
+ $$PWD/graphicswidgets_p.h \
+ $$PWD/graphicslayouts_p.h
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index 9ff2ad8..fb0dba4 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -648,13 +648,14 @@ void QDialog::contextMenuEvent(QContextMenuEvent *e)
while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))
w = w->isWindow() ? 0 : w->parentWidget();
if (w) {
- QMenu p(this);
- QAction *wt = p.addAction(tr("What's This?"));
- if (p.exec(e->globalPos()) == wt) {
+ QWeakPointer<QMenu> p = new QMenu(this);
+ QAction *wt = p.data()->addAction(tr("What's This?"));
+ if (p.data()->exec(e->globalPos()) == wt) {
QHelpEvent e(QEvent::WhatsThis, w->rect().center(),
w->mapToGlobal(w->rect().center()));
QApplication::sendEvent(w, &e);
}
+ delete p.data();
}
#endif
}
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 21650bb..089e04a 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -229,11 +229,10 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
\value ReadOnly Indicates that the model is readonly.
\value HideNameFilterDetails Indicates if the is hidden or not.
- This value is obsolete and does nothing since Qt 4.5:
\value DontUseSheet In previous versions of Qt, the static
functions would create a sheet by default if the static function
- was given a parent. This is no longer supported in Qt 4.5, The
+ was given a parent. This is no longer supported and does nothing in Qt 4.5, The
static functions will always be an application modal dialog. If
you want to use sheets, use QFileDialog::open() instead.
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 0e1837b..ba0a560 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -51,6 +51,9 @@
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
+#ifdef Q_OS_WIN32
+#include <QtCore/QVarLengthArray>
+#endif
QT_BEGIN_NAMESPACE
@@ -278,53 +281,38 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QM
return indexNode;
}
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
static QString qt_GetLongPathName(const QString &strShortPath)
{
- QString longPath;
- int i = 0;
- if (strShortPath == QLatin1String(".")
- || (strShortPath.startsWith(QLatin1String("//")))
- || (strShortPath.startsWith(QLatin1String("\\\\")))) // unc
+ if (strShortPath.isEmpty()
+ || strShortPath == QLatin1String(".") || strShortPath == QLatin1String(".."))
return strShortPath;
- QString::const_iterator it = strShortPath.constBegin();
- QString::const_iterator constEnd = strShortPath.constEnd();
- do {
- bool isSep = (*it == QLatin1Char('\\') || *it == QLatin1Char('/'));
- if (isSep || it == constEnd) {
- QString section = (it == constEnd ? strShortPath : strShortPath.left(i));
- // FindFirstFile does not handle volumes ("C:"), so we have to catch that ourselves.
- if (section.endsWith(QLatin1Char(':'))) {
- longPath.append(section.toUpper());
- } else {
- HANDLE h;
-#ifndef Q_OS_WINCE
- //We add the extend length prefix to handle long path
- QString longSection = QLatin1String("\\\\?\\")+QDir::toNativeSeparators(section);
-#else
- QString longSection = QDir::toNativeSeparators(section);
-#endif
- 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;
- }
- }
- if (it != constEnd)
- longPath.append(*it);
- else
- break;
- }
- ++it;
- if (isSep && it == constEnd) // break out if the last character is a separator
- break;
- ++i;
- } while (true);
- return longPath;
+ if (strShortPath.length() == 2 && strShortPath.endsWith(QLatin1Char(':')))
+ return strShortPath.toUpper();
+ const QString absPath = QDir(strShortPath).absolutePath();
+ if (absPath.startsWith(QLatin1String("//"))
+ || absPath.startsWith(QLatin1String("\\\\"))) // unc
+ return QDir::fromNativeSeparators(absPath);
+ if (absPath.startsWith(QLatin1Char('/')))
+ return QString();
+ const QString inputString = QLatin1String("\\\\?\\") + QDir::toNativeSeparators(absPath);
+ QVarLengthArray<TCHAR, MAX_PATH> buffer(MAX_PATH);
+ DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ if (result > DWORD(buffer.size())) {
+ buffer.resize(result);
+ result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ }
+ if (result > 4) {
+ QString longPath = QString::fromWCharArray(buffer.data() + 4); // ignoring prefix
+ longPath[0] = longPath.at(0).toUpper(); // capital drive letters
+ return QDir::fromNativeSeparators(longPath);
+ } else {
+ return QDir::fromNativeSeparators(strShortPath);
+ }
}
#endif
@@ -342,7 +330,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// Construct the nodes up to the new root path if they need to be built
QString absolutePath;
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
QString longPath = qt_GetLongPathName(path);
#else
QString longPath = path;
@@ -1357,7 +1345,11 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
{
Q_D(QFileSystemModel);
#ifdef Q_OS_WIN
- QString longNewPath = QDir::fromNativeSeparators(qt_GetLongPathName(newPath));
+#ifdef Q_OS_WIN32
+ QString longNewPath = qt_GetLongPathName(newPath);
+#else
+ QString longNewPath = QDir::fromNativeSeparators(newPath);
+#endif
#else
QString longNewPath = newPath;
#endif
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index d1b2e3f..ed437ff 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -92,8 +92,8 @@ public:
{
#ifndef QT_NO_CONTEXTMENU
QMenu *menu = createStandardContextMenu();
- menu->exec(e->globalPos());
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(e->globalPos());
#else
Q_UNUSED(e);
#endif
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index ed36f87..63b0ec7 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -319,7 +319,7 @@
QGraphicsItem::keyPressEvent() and QGraphicsItem::keyReleaseEvent().
\value ItemClipsToShape The item clips to its own shape. The item cannot
- draw or receive mouse, tablet, drag and drop or hover events outside ts
+ draw or receive mouse, tablet, drag and drop or hover events outside its
shape. It is disabled by default. This behavior is enforced by
QGraphicsView::drawItems() or QGraphicsScene::drawItems(). This flag was
introduced in Qt 4.3.
@@ -668,6 +668,7 @@
#include <QtCore/qtimer.h>
#include <QtCore/qvariant.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qnumeric.h>
#include <QtGui/qapplication.h>
#include <QtGui/qbitmap.h>
#include <QtGui/qpainter.h>
@@ -1392,7 +1393,8 @@ QGraphicsItem::~QGraphicsItem()
}
delete d_ptr->transformData;
- qt_dataStore()->data.remove(this);
+ if (QGraphicsItemCustomDataStore *dataStore = qt_dataStore())
+ dataStore->data.remove(this);
}
/*!
@@ -2569,6 +2571,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
if (newOpacity == d_ptr->opacity)
return;
+ bool wasFullyTransparent = d_ptr->isOpacityNull();
d_ptr->opacity = newOpacity;
// Notify change.
@@ -2584,7 +2587,9 @@ void QGraphicsItem::setOpacity(qreal opacity)
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
/*force=*/false,
- /*ignoreOpacity=*/true);
+ /*ignoreOpacity=*/d_ptr->isOpacityNull());
+ if (wasFullyTransparent)
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
}
if (d_ptr->isObject)
@@ -3438,6 +3443,9 @@ void QGraphicsItem::setX(qreal x)
if (d_ptr->inDestructor)
return;
+ if (qIsNaN(x))
+ return;
+
d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
}
@@ -3462,6 +3470,9 @@ void QGraphicsItem::setY(qreal y)
if (d_ptr->inDestructor)
return;
+ if (qIsNaN(y))
+ return;
+
d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
}
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 5ad6cd5..b3ca3b5 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -358,14 +358,20 @@ public:
return o;
}
+ inline bool isOpacityNull() const
+ { return (opacity < qreal(0.001)); }
+
+ static inline bool isOpacityNull(qreal opacity)
+ { return (opacity < qreal(0.001)); }
+
inline bool isFullyTransparent() const
{
- if (opacity < 0.001)
+ if (isOpacityNull())
return true;
if (!parent)
return false;
- return calcEffectiveOpacity() < 0.001;
+ return isOpacityNull(calcEffectiveOpacity());
}
inline qreal effectiveOpacity() const {
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 478669e..9a36d46 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -251,6 +251,7 @@
#endif
#include <private/qgraphicseffect_p.h>
#include <private/qgesturemanager_p.h>
+#include <private/qpathclipper_p.h>
// #define GESTURE_DEBUG
#ifndef GESTURE_DEBUG
@@ -372,7 +373,10 @@ void QGraphicsScenePrivate::_q_emitUpdated()
}
}
} else {
- updateAll = false;
+ if (views.isEmpty()) {
+ updateAll = false;
+ return;
+ }
for (int i = 0; i < views.size(); ++i)
views.at(i)->d_func()->processPendingUpdates();
// It's important that we update all views before we dispatch, hence two for-loops.
@@ -4605,6 +4609,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const
if (!unpolishedItems.isEmpty())
_q_polishItems();
+ updateAll = false;
QRectF exposedSceneRect;
if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
@@ -4632,7 +4637,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
return; // Item has neither contents nor children!(?)
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
return;
@@ -4752,7 +4757,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
qreal opacity, const QTransform *effectTransform,
bool wasDirtyParentSceneTransform, bool drawItem)
{
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
const bool itemHasChildren = !item->d_ptr->children.isEmpty();
@@ -4767,7 +4772,12 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
painter->setWorldTransform(*transformPtr * *effectTransform);
else
painter->setWorldTransform(*transformPtr);
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ QRectF clipRect;
+ const QPainterPath clipPath(item->shape());
+ if (QPathClipper::pathToRect(clipPath, &clipRect))
+ painter->setClipRect(clipRect, Qt::IntersectClip);
+ else
+ painter->setClipPath(clipPath, Qt::IntersectClip);
}
// Draw children behind
@@ -4803,8 +4813,14 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
painter->setWorldTransform(*transformPtr);
}
- if (itemClipsToShape)
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ if (itemClipsToShape) {
+ QRectF clipRect;
+ const QPainterPath clipPath(item->shape());
+ if (QPathClipper::pathToRect(clipPath, &clipRect))
+ painter->setClipRect(clipRect, Qt::IntersectClip);
+ else
+ painter->setClipPath(clipPath, Qt::IntersectClip);
+ }
painter->setOpacity(opacity);
if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
@@ -4982,7 +4998,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
}
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
+ const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
+ && QGraphicsItemPrivate::isOpacityNull(opacity);
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
resetDirtyItem(item, /*recursive=*/itemHasChildren);
return;
@@ -5155,6 +5172,7 @@ void QGraphicsScene::drawItems(QPainter *painter,
if (!d->unpolishedItems.isEmpty())
d->_q_polishItems();
+ d->updateAll = false;
QTransform viewTransform = painter->worldTransform();
Q_UNUSED(options);
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
index 043c4eb..707c71f 100644
--- a/src/gui/graphicsview/qgraphicssceneindex.cpp
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -279,7 +279,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
return;
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
const bool itemHasChildren = !item->d_ptr->children.isEmpty();
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
return;
@@ -554,7 +554,7 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &
/*!
\fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const
-
+
This pure virtual function all items in the index and sort them using
\a order.
*/
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 451f183..96b9373 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -2748,7 +2748,6 @@ bool QGraphicsView::viewportEvent(QEvent *event)
}
}
}
- d->scene->d_func()->updateAll = false;
}
break;
case QEvent::TouchBegin:
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index ac1d303..bf6eb8d 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -104,6 +104,15 @@ QT_BEGIN_NAMESPACE
static QBasicAtomicInt serialNumCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
+static void qt_cleanup_icon_cache();
+typedef QCache<QString, QIcon> IconCache;
+Q_GLOBAL_STATIC_WITH_INITIALIZER(IconCache, qtIconCache, qAddPostRoutine(qt_cleanup_icon_cache))
+
+static void qt_cleanup_icon_cache()
+{
+ qtIconCache()->clear();
+}
+
QIconPrivate::QIconPrivate()
: engine(0), ref(1),
serialNum(serialNumCounter.fetchAndAddRelaxed(1)),
@@ -963,15 +972,13 @@ QString QIcon::themeName()
*/
QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
{
- static QCache <QString, QIcon> iconCache;
-
QIcon icon;
- if (iconCache.contains(name)) {
- icon = *iconCache.object(name);
+ if (qtIconCache()->contains(name)) {
+ icon = *qtIconCache()->object(name);
} else {
QIcon *cachedIcon = new QIcon(new QIconLoaderEngine(name));
- iconCache.insert(name, cachedIcon);
+ qtIconCache()->insert(name, cachedIcon);
icon = *cachedIcon;
}
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
index 61d538f..ace4bb6 100644
--- a/src/gui/image/qimagepixmapcleanuphooks.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -62,12 +62,12 @@ QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance()
return qt_image_and_pixmap_cleanup_hooks();
}
-void QImagePixmapCleanupHooks::addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.append(hook);
}
-void QImagePixmapCleanupHooks::addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.append(hook);
}
@@ -78,12 +78,12 @@ void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook)
imageHooks.append(hook);
}
-void QImagePixmapCleanupHooks::removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.removeAll(hook);
}
-void QImagePixmapCleanupHooks::removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.removeAll(hook);
}
@@ -93,24 +93,24 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
imageHooks.removeAll(hook);
}
-void QImagePixmapCleanupHooks::executePixmapModificationHooks(QPixmap* pm)
+void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
for (int i = 0; i < h->pixmapModificationHooks.count(); ++i)
- h->pixmapModificationHooks[i](pm);
+ h->pixmapModificationHooks[i](pmd);
if (qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(pm->cacheKey());
+ qt_pixmap_cleanup_hook_64(pmd->cacheKey());
}
-void QImagePixmapCleanupHooks::executePixmapDestructionHooks(QPixmap* pm)
+void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i)
- h->pixmapDestructionHooks[i](pm);
+ h->pixmapDestructionHooks[i](pmd);
if (qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(pm->cacheKey());
+ qt_pixmap_cleanup_hook_64(pmd->cacheKey());
}
void QImagePixmapCleanupHooks::executeImageHooks(qint64 key)
diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h
index 7176044..88dd3a6 100644
--- a/src/gui/image/qimagepixmapcleanuphooks_p.h
+++ b/src/gui/image/qimagepixmapcleanuphooks_p.h
@@ -58,7 +58,8 @@
QT_BEGIN_NAMESPACE
typedef void (*_qt_image_cleanup_hook_64)(qint64);
-typedef void (*_qt_pixmap_cleanup_hook_pm)(QPixmap*);
+typedef void (*_qt_pixmap_cleanup_hook_pmd)(QPixmapData*);
+
class QImagePixmapCleanupHooks;
@@ -71,27 +72,27 @@ public:
static void enableCleanupHooks(const QPixmap &pixmap);
static void enableCleanupHooks(QPixmapData *pixmapData);
- // Gets called when a pixmap is about to be modified:
- void addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm);
+ // Gets called when a pixmap data is about to be modified:
+ void addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
- // Gets called when a pixmap is about to be destroyed:
- void addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm);
+ // Gets called when a pixmap data is about to be destroyed:
+ void addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
// Gets called when an image is about to be modified or destroyed:
void addImageHook(_qt_image_cleanup_hook_64);
- void removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm);
- void removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm);
+ void removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
+ void removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
void removeImageHook(_qt_image_cleanup_hook_64);
- static void executePixmapModificationHooks(QPixmap*);
- static void executePixmapDestructionHooks(QPixmap*);
+ static void executePixmapDataModificationHooks(QPixmapData*);
+ static void executePixmapDataDestructionHooks(QPixmapData*);
static void executeImageHooks(qint64 key);
private:
QList<_qt_image_cleanup_hook_64> imageHooks;
- QList<_qt_pixmap_cleanup_hook_pm> pixmapModificationHooks;
- QList<_qt_pixmap_cleanup_hook_pm> pixmapDestructionHooks;
+ QList<_qt_pixmap_cleanup_hook_pmd> pixmapModificationHooks;
+ QList<_qt_pixmap_cleanup_hook_pmd> pixmapDestructionHooks;
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index c9e015c..9320cfc 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -263,25 +263,37 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
device->seek(pos);
}
- if (!handler && !testFormat.isEmpty() && autoDetectImageFormat && !ignoresFormatAndExtension) {
+ if (!handler && !testFormat.isEmpty() && !ignoresFormatAndExtension) {
// check if any plugin supports the format (they are not allowed to
// read from the device yet).
const qint64 pos = device ? device->pos() : 0;
- for (int i = 0; i < keys.size(); ++i) {
- if (i != suffixPluginIndex) {
- QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(keys.at(i)));
- if (plugin && plugin->capabilities(device, testFormat) & QImageIOPlugin::CanRead) {
+
+ if (autoDetectImageFormat) {
+ for (int i = 0; i < keys.size(); ++i) {
+ if (i != suffixPluginIndex) {
+ QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(keys.at(i)));
+ if (plugin && plugin->capabilities(device, testFormat) & QImageIOPlugin::CanRead) {
#ifdef QIMAGEREADER_DEBUG
- qDebug() << "QImageReader::createReadHandler: the" << keys.at(i) << "plugin can read this format";
+ qDebug() << "QImageReader::createReadHandler: the" << keys.at(i) << "plugin can read this format";
#endif
- handler = plugin->create(device, testFormat);
- break;
+ handler = plugin->create(device, testFormat);
+ break;
+ }
}
}
+ } else {
+ QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(QLatin1String(testFormat)));
+ if (plugin && plugin->capabilities(device, testFormat) & QImageIOPlugin::CanRead) {
+#ifdef QIMAGEREADER_DEBUG
+ qDebug() << "QImageReader::createReadHandler: the" << testFormat << "plugin can read this format";
+#endif
+ handler = plugin->create(device, testFormat);
+ }
}
if (device && !device->isSequential())
device->seek(pos);
}
+
#endif // QT_NO_LIBRARY
// if we don't have a handler yet, check if we have built-in support for
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index e51d858..7cafbd0 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -320,8 +320,6 @@ QPixmap::QPixmap(const char * const xpm[])
QPixmap::~QPixmap()
{
Q_ASSERT(!data || data->ref >= 1); // Catch if ref-counting changes again
- if (data && data->is_cached && data->ref == 1) // ref will be decrememnted after destructor returns
- QImagePixmapCleanupHooks::executePixmapDestructionHooks(this);
}
/*!
@@ -1025,12 +1023,8 @@ qint64 QPixmap::cacheKey() const
if (isNull())
return 0;
- int classKey = data->classId();
- if (classKey >= 1024)
- classKey = -(classKey >> 10);
- return ((((qint64) classKey) << 56)
- | (((qint64) data->serialNumber()) << 32)
- | ((qint64) (data->detach_no)));
+ Q_ASSERT(data);
+ return data->cacheKey();
}
static void sendResizeEvents(QWidget *target)
@@ -1963,7 +1957,7 @@ void QPixmap::detach()
}
if (data->is_cached && data->ref == 1)
- QImagePixmapCleanupHooks::executePixmapModificationHooks(this);
+ QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data());
#if defined(Q_WS_MAC)
QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 0e66e09..b976376 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -68,6 +68,7 @@
#include "qx11info_x11.h"
#include <private/qdrawhelper_p.h>
#include <private/qimage_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
#include <stdlib.h>
@@ -1141,7 +1142,7 @@ void QX11PixmapData::fromImage(const QImage &img,
}
}
-void QX11PixmapData::bitmapFromImage(const QImage &image)
+Qt::HANDLE QX11PixmapData::createBitmapFromImage(const QImage &image)
{
QImage img = image.convertToFormat(QImage::Format_MonoLSB);
const QRgb c0 = QColor(Qt::black).rgb();
@@ -1154,10 +1155,8 @@ void QX11PixmapData::bitmapFromImage(const QImage &image)
char *bits;
uchar *tmp_bits;
- w = img.width();
- h = img.height();
- d = 1;
- is_null = (w <= 0 || h <= 0);
+ int w = img.width();
+ int h = img.height();
int bpl = (w + 7) / 8;
int ibpl = img.bytesPerLine();
if (bpl != ibpl) {
@@ -1176,18 +1175,26 @@ void QX11PixmapData::bitmapFromImage(const QImage &image)
bits = (char *)img.bits();
tmp_bits = 0;
}
- hd = (Qt::HANDLE)XCreateBitmapFromData(xinfo.display(),
- RootWindow(xinfo.display(), xinfo.screen()),
+ Qt::HANDLE hd = (Qt::HANDLE)XCreateBitmapFromData(X11->display,
+ QX11Info::appRootWindow(),
bits, w, h);
+ if (tmp_bits) // Avoid purify complaint
+ delete [] tmp_bits;
+ return hd;
+}
+void QX11PixmapData::bitmapFromImage(const QImage &image)
+{
+ w = image.width();
+ h = image.height();
+ d = 1;
+ is_null = (w <= 0 || h <= 0);
+ hd = createBitmapFromImage(image);
#ifndef QT_NO_XRENDER
if (X11->use_xrender)
picture = XRenderCreatePicture(X11->display, hd,
XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
#endif // QT_NO_XRENDER
-
- if (tmp_bits) // Avoid purify complaint
- delete [] tmp_bits;
}
void QX11PixmapData::fill(const QColor &fillColor)
@@ -1228,6 +1235,12 @@ void QX11PixmapData::fill(const QColor &fillColor)
QX11PixmapData::~QX11PixmapData()
{
+ // Cleanup hooks have to be called before the handles are freed
+ if (is_cached) {
+ QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
+ is_cached = false;
+ }
+
release();
}
@@ -1236,8 +1249,13 @@ void QX11PixmapData::release()
delete pengine;
pengine = 0;
- if (!X11)
+ if (!X11) {
+#ifndef QT_NO_DEBUG
+ qWarning("~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication"
+ " object, otherwise the native pixmap object will be leaked.");
+#endif
return;
+ }
if (x11_mask) {
#ifndef QT_NO_XRENDER
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 20fb654..0c0a9bd 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -92,6 +92,8 @@ public:
Qt::HANDLE handle() const { return hd; }
Qt::HANDLE x11ConvertToDefaultDepth();
+ static Qt::HANDLE createBitmapFromImage(const QImage &image);
+
protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index 65032da..ea4fe6b 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -45,6 +45,7 @@
#include <QtGui/qimagereader.h>
#include <private/qgraphicssystem_p.h>
#include <private/qapplication_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
QT_BEGIN_NAMESPACE
@@ -80,6 +81,16 @@ QPixmapData::QPixmapData(PixelType pixelType, int objectId)
QPixmapData::~QPixmapData()
{
+ // Sometimes the pixmap cleanup hooks will be called from derrived classes, which will
+ // then set is_cached to false. For example, on X11 QtOpenGL needs to delete the GLXPixmap
+ // or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted,
+ // otherwise some drivers will leak the GL surface. In this case, QX11PixmapData will
+ // call the cleanup hooks itself before deleting the native pixmap and set is_cached to
+ // false.
+ if (is_cached) {
+ QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
+ is_cached = false;
+ }
}
QPixmapData *QPixmapData::createCompatiblePixmapData() const
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 1125515..827fa18 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -117,6 +117,14 @@ public:
inline int colorCount() const { return metric(QPaintDevice::PdmNumColors); }
inline int depth() const { return d; }
inline bool isNull() const { return is_null; }
+ inline qint64 cacheKey() const {
+ int classKey = id;
+ if (classKey >= 1024)
+ classKey = -(classKey >> 10);
+ return ((((qint64) classKey) << 56)
+ | (((qint64) ser_no) << 32)
+ | ((qint64) detach_no));
+ }
#if defined(Q_OS_SYMBIAN)
virtual void* toNativeType(NativeType type);
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp
index 37a6a18..2792e45 100644
--- a/src/gui/image/qpixmapfilter.cpp
+++ b/src/gui/image/qpixmapfilter.cpp
@@ -422,6 +422,9 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q
if(d->kernelWidth<=0 || d->kernelHeight <= 0)
return;
+ if (src.isNull())
+ return;
+
QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ?
static_cast<QPaintEngineEx *>(painter->paintEngine())->pixmapFilter(type(), this) : 0;
QPixmapConvolutionFilter *convolutionFilter = static_cast<QPixmapConvolutionFilter*>(filter);
@@ -710,7 +713,8 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
radius *= qreal(0.5);
Q_ASSERT(img.format() == QImage::Format_ARGB32_Premultiplied
- || img.format() == QImage::Format_RGB32);
+ || img.format() == QImage::Format_RGB32
+ || img.format() == QImage::Format_Indexed8);
// choose the alpha such that pixels at radius distance from a fully
// saturated pixel will have an alpha component of no greater than
@@ -902,6 +906,9 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap
if (!painter->isActive())
return;
+ if (src.isNull())
+ return;
+
QRectF srcRect = rect;
if (srcRect.isNull())
srcRect = src.rect();
@@ -1082,6 +1089,10 @@ void QPixmapColorizeFilter::setStrength(qreal strength)
void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
{
Q_D(const QPixmapColorizeFilter);
+
+ if (src.isNull())
+ return;
+
QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ?
static_cast<QPaintEngineEx *>(painter->paintEngine())->pixmapFilter(type(), this) : 0;
QPixmapColorizeFilter *colorizeFilter = static_cast<QPixmapColorizeFilter*>(filter);
@@ -1312,6 +1323,10 @@ void QPixmapDropShadowFilter::draw(QPainter *p,
const QRectF &src) const
{
Q_D(const QPixmapDropShadowFilter);
+
+ if (px.isNull())
+ return;
+
QPixmapFilter *filter = p->paintEngine() && p->paintEngine()->isExtended() ?
static_cast<QPaintEngineEx *>(p->paintEngine())->pixmapFilter(type(), this) : 0;
QPixmapDropShadowFilter *dropShadowFilter = static_cast<QPixmapDropShadowFilter*>(filter);
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index d5406cb..dd31834 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -50,8 +50,13 @@
#include <qvariant.h>
#include <qvector.h>
+#ifdef QT_USE_BUNDLED_LIBPNG
+#include <../../3rdparty/libpng/png.h>
+#include <../../3rdparty/libpng/pngconf.h>
+#else
#include <png.h>
#include <pngconf.h>
+#endif
#ifdef Q_OS_WINCE
#define CALLBACK_CALL_TYPE __cdecl
@@ -162,11 +167,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
png_uint_32 height;
int bit_depth;
int color_type;
+ png_bytep trans_alpha = 0;
+ png_color_16p trans_color_p = 0;
+ int num_trans;
+ png_colorp palette = 0;
+ int num_palette;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
png_set_invert_mono(png_ptr);
png_read_update_info(png_ptr, info_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
@@ -207,20 +217,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
int c = i*255/(ncols-1);
image.setColor(i, qRgba(c,c,c,0xff));
}
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- const int g = info_ptr->trans_values.gray;
-#else
- const int g = info_ptr->trans_color.gray;
-#endif
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
+ const int g = trans_color_p->gray;
if (g < ncols) {
image.setColor(g, 0);
}
}
}
} else if (color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
if (bit_depth != 1)
@@ -233,29 +239,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
if (image.isNull())
return;
}
- image.setColorCount(info_ptr->num_palette);
+ png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
+ image.setColorCount(num_palette);
int i = 0;
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- while (i < info_ptr->num_trans) {
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
+ while (i < num_trans) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- info_ptr->trans[i]
-#else
- info_ptr->trans_alpha[i]
-#endif
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
+ trans_alpha[i]
)
);
i++;
}
}
- while (i < info_ptr->num_palette) {
+ while (i < num_palette) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
0xff
)
);
@@ -531,33 +534,36 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
QImage::Format format = QImage::Format_Invalid;
png_uint_32 width, height;
int bit_depth, color_type;
- if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
+ png_colorp palette;
+ int num_palette;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
+ if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
format = QImage::Format_Mono;
- } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
format = QImage::Format_ARGB32;
} else {
format = QImage::Format_Indexed8;
}
- } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ } else if (color_type == PNG_COLOR_TYPE_PALETTE
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
- if (info_ptr->bit_depth != 1)
+ if (bit_depth != 1)
png_set_packing(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
} else {
// 32-bit
- if (info_ptr->bit_depth == 16)
+ if (bit_depth == 16)
png_set_strip_16(png_ptr);
format = QImage::Format_ARGB32;
// Only add filler if no alpha, or we can get 5 channel data.
- if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if (!(color_type & PNG_COLOR_MASK_ALPHA)
&& !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
// We want 4 bytes, but it isn't an alpha channel
format = QImage::Format_RGB32;
@@ -648,7 +654,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
text_ptr[i].text = qstrdup(value.constData());
text_ptr[i].text_length = 0;
text_ptr[i].itxt_length = value.size();
- text_ptr[i].lang = "UTF-8";
+ text_ptr[i].lang = const_cast<char*>("UTF-8");
text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
#endif
++i;
@@ -735,64 +741,51 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_set_compression_level(png_ptr, quality);
}
- if (gamma != 0.0) {
- png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
- }
-
png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
- info_ptr->channels =
- (image.depth() == 32)
- ? (image.format() == QImage::Format_RGB32 ? 3 : 4)
- : 1;
-
png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
image.depth() == 1 ? 1 : 8 /* per channel */,
image.depth() == 32
? image.format() == QImage::Format_RGB32
? PNG_COLOR_TYPE_RGB
: PNG_COLOR_TYPE_RGB_ALPHA
- : PNG_COLOR_TYPE_PALETTE, 0, 0, 0);
+ : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels
+ if (gamma != 0.0) {
+ png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
+ }
- //png_set_sBIT(png_ptr, info_ptr, 8);
- info_ptr->sig_bit.red = 8;
- info_ptr->sig_bit.green = 8;
- info_ptr->sig_bit.blue = 8;
+ png_color_8 sig_bit;
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
if (image.format() == QImage::Format_MonoLSB)
png_set_packswap(png_ptr);
- png_colorp palette = 0;
- png_bytep copy_trans = 0;
if (image.colorCount()) {
// Paletted
- int num_palette = image.colorCount();
- palette = new png_color[num_palette];
- png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
- int* trans = new int[num_palette];
+ int num_palette = qMin(256, image.colorCount());
+ png_color palette[256];
+ png_byte trans[256];
int num_trans = 0;
for (int i=0; i<num_palette; i++) {
- QRgb rgb=image.color(i);
- info_ptr->palette[i].red = qRed(rgb);
- info_ptr->palette[i].green = qGreen(rgb);
- info_ptr->palette[i].blue = qBlue(rgb);
- trans[i] = rgb >> 24;
+ QRgb rgba=image.color(i);
+ palette[i].red = qRed(rgba);
+ palette[i].green = qGreen(rgba);
+ palette[i].blue = qBlue(rgba);
+ trans[i] = qAlpha(rgba);
if (trans[i] < 255) {
num_trans = i+1;
}
}
+ png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
+
if (num_trans) {
- copy_trans = new png_byte[num_trans];
- for (int i=0; i<num_trans; i++)
- copy_trans[i] = trans[i];
- png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0);
+ png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
}
- delete [] trans;
- }
-
- if (image.format() != QImage::Format_RGB32) {
- info_ptr->sig_bit.alpha = 8;
}
// Swap ARGB to RGBA (normal PNG format) before saving on
@@ -868,11 +861,6 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_write_end(png_ptr, info_ptr);
frames_written++;
- if (palette)
- delete [] palette;
- if (copy_trans)
- delete [] copy_trans;
-
png_destroy_write_struct(&png_ptr, &info_ptr);
return true;
@@ -958,7 +946,8 @@ QVariant QPngHandler::option(ImageOption option) const
else if (option == Description)
return d->description;
else if (option == Size)
- return QSize(d->info_ptr->width, d->info_ptr->height);
+ return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
+ png_get_image_height(d->png_ptr, d->info_ptr));
else if (option == ImageFormat)
return d->readImageFormat();
return 0;
diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h
index f5034fc..d5243c3 100644
--- a/src/gui/inputmethod/qcoefepinputcontext_p.h
+++ b/src/gui/inputmethod/qcoefepinputcontext_p.h
@@ -96,7 +96,7 @@ protected:
void timerEvent(QTimerEvent *timerEvent);
private:
- void commitCurrentString(bool triggeredBySymbian);
+ void commitCurrentString(bool cancelFepTransaction);
void updateHints(bool mustUpdateInputCapabilities);
void applyHints(Qt::InputMethodHints hints);
void applyFormat(QList<QInputMethodEvent::Attribute> *attributes);
@@ -127,7 +127,7 @@ public:
private:
void DoCommitFepInlineEditL();
MCoeFepAwareTextEditor_Extension1* Extension1(TBool& aSetToTrue);
- void ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType);
+ void ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType);
// From MCoeFepAwareTextEditor_Extension1
public:
@@ -151,7 +151,6 @@ private:
int m_inlinePosition;
MFepInlineTextFormatRetriever *m_formatRetriever;
MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler;
- int m_longPress;
int m_cursorPos;
QBasicTimer m_tempPreeditStringTimeout;
bool m_hasTempPreeditString;
diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
index e5ab300..2b91711 100644
--- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
@@ -71,7 +71,6 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent)
m_inlinePosition(0),
m_formatRetriever(0),
m_pointerHandler(0),
- m_longPress(0),
m_cursorPos(0),
m_hasTempPreeditString(false)
{
@@ -101,7 +100,7 @@ QCoeFepInputContext::~QCoeFepInputContext()
void QCoeFepInputContext::reset()
{
- commitCurrentString(false);
+ commitCurrentString(true);
}
void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType)
@@ -126,7 +125,7 @@ void QCoeFepInputContext::update()
void QCoeFepInputContext::setFocusWidget(QWidget *w)
{
- commitCurrentString(false);
+ commitCurrentString(true);
QInputContext::setFocusWidget(w);
@@ -219,7 +218,7 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event)
break;
case Qt::Key_Select:
if (!m_preeditString.isEmpty()) {
- commitCurrentString(false);
+ commitCurrentString(true);
return true;
}
break;
@@ -231,10 +230,11 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event)
&& focusWidget()->inputMethodHints() & Qt::ImhHiddenText
&& !keyEvent->text().isEmpty()) {
// Send some temporary preedit text in order to make text visible for a moment.
+ m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
m_preeditString = keyEvent->text();
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent imEvent(m_preeditString, attributes);
- QApplication::sendEvent(focusWidget(), &imEvent);
+ sendEvent(imEvent);
m_tempPreeditStringTimeout.start(1000, this);
m_hasTempPreeditString = true;
update();
@@ -293,7 +293,7 @@ void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event)
Q_ASSERT(focusWidget());
if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) {
- commitCurrentString(false);
+ commitCurrentString(true);
int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
QList<QInputMethodEvent::Attribute> attributes;
@@ -739,31 +739,33 @@ void QCoeFepInputContext::GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLin
void QCoeFepInputContext::DoCommitFepInlineEditL()
{
- commitCurrentString(true);
+ commitCurrentString(false);
}
-void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian)
+void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction)
{
+ int longPress = 0;
+
if (m_preeditString.size() == 0) {
QWidget *w = focusWidget();
- if (triggeredBySymbian && w) {
+ if (!cancelFepTransaction && w) {
// We must replace the last character only if the input box has already accepted one
if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos)
- m_longPress = 1;
+ longPress = 1;
}
return;
}
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(m_preeditString, 0-m_longPress, m_longPress);
+ event.setCommitString(m_preeditString, 0-longPress, longPress);
m_preeditString.clear();
sendEvent(event);
m_hasTempPreeditString = false;
- m_longPress = 0;
+ longPress = 0;
- if (!triggeredBySymbian) {
+ if (cancelFepTransaction) {
CCoeFep* fep = CCoeEnv::Static()->Fep();
if (fep)
fep->CancelTransaction();
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index 19b1e8c..b2def39 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -2160,7 +2160,7 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
} else {
if (flowPositions.isEmpty())
return;
- const int max = flowPositions.count() - 1;
+ const int max = scrollValueMap.count() - 1;
if (vertical && flow() == QListView::TopToBottom && dy != 0) {
int currentValue = qBound(0, verticalValue, max);
int previousValue = qBound(0, currentValue + dy, max);
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index 4b7d949..8ddd051 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -715,6 +715,10 @@ QActionGroup *QAction::actionGroup() const
it is displayed to the left of the menu text. There is no default
icon.
+ On Symbian the icons which are passed to softkeys, i.e. to actions with
+ softkey role, need to have pixmap alpha channel correctly set otherwise
+ drawing artifacts will appear when softkey is pressed down.
+
If a null icon (QIcon::isNull() is passed into this function,
the icon of the action is cleared.
*/
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index b9ea540..336be91 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -182,6 +182,15 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T
gestureManager = 0;
gestureWidget = 0;
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ move_cursor = 0;
+ copy_cursor = 0;
+ link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ ignore_cursor = 0;
+#endif
+
if (!self)
self = this;
}
@@ -1032,6 +1041,15 @@ QApplication::~QApplication()
qt_clipboard = 0;
#endif
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ delete d->move_cursor; d->move_cursor = 0;
+ delete d->copy_cursor; d->copy_cursor = 0;
+ delete d->link_cursor; d->link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ delete d->ignore_cursor; d->ignore_cursor = 0;
+#endif
+
delete QWidgetPrivate::mapper;
QWidgetPrivate::mapper = 0;
@@ -5246,10 +5264,20 @@ QInputContext *QApplication::inputContext() const
qic = QInputContextFactory::create(QLatin1String("xim"), that);
that->d_func()->inputContext = qic;
}
-#elif defined(Q_WS_S60)
+#elif defined(Q_OS_SYMBIAN)
if (!d->inputContext) {
QApplication *that = const_cast<QApplication *>(this);
- that->d_func()->inputContext = QInputContextFactory::create(QString::fromLatin1("coefep"), that);
+ const QStringList keys = QInputContextFactory::keys();
+ // Try hbim and coefep first, then try others.
+ if (keys.contains("hbim")) {
+ that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("hbim"), that);
+ } else if (keys.contains("coefep")) {
+ that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("coefep"), that);
+ } else {
+ for (int c = 0; c < keys.size() && !d->inputContext; ++c) {
+ that->d_func()->inputContext = QInputContextFactory::create(keys[c], that);
+ }
+ }
}
#endif
return d->inputContext;
@@ -5689,6 +5717,228 @@ QGestureManager* QGestureManager::instance()
return qAppPriv->gestureManager;
}
+// These pixmaps approximate the images in the Windows User Interface Guidelines.
+
+// XPM
+
+static const char * const move_xpm[] = {
+"11 20 3 1",
+". c None",
+#if defined(Q_WS_WIN)
+"a c #000000",
+"X c #FFFFFF", // Windows cursor is traditionally white
+#else
+"a c #FFFFFF",
+"X c #000000", // X11 cursor is traditionally black
+#endif
+"aa.........",
+"aXa........",
+"aXXa.......",
+"aXXXa......",
+"aXXXXa.....",
+"aXXXXXa....",
+"aXXXXXXa...",
+"aXXXXXXXa..",
+"aXXXXXXXXa.",
+"aXXXXXXXXXa",
+"aXXXXXXaaaa",
+"aXXXaXXa...",
+"aXXaaXXa...",
+"aXa..aXXa..",
+"aa...aXXa..",
+"a.....aXXa.",
+"......aXXa.",
+".......aXXa",
+".......aXXa",
+"........aa."};
+
+#ifdef Q_WS_WIN
+/* XPM */
+static const char * const ignore_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa.....XXXX.....",
+".......aXXa..XXaaaaXX...",
+".......aXXa.XaaaaaaaaX..",
+"........aa.XaaaXXXXaaaX.",
+"...........XaaaaX..XaaX.",
+"..........XaaXaaaX..XaaX",
+"..........XaaXXaaaX.XaaX",
+"..........XaaX.XaaaXXaaX",
+"..........XaaX..XaaaXaaX",
+"...........XaaX..XaaaaX.",
+"...........XaaaXXXXaaaX.",
+"............XaaaaaaaaX..",
+".............XXaaaaXX...",
+"...............XXXX....."};
+#endif
+
+/* XPM */
+static const char * const copy_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXaaaaaXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+/* XPM */
+static const char * const link_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXaaaaXXa",
+".............aXXXXaaaXXa",
+".............aXXXaaaaXXa",
+".............aXXaaaXaXXa",
+".............aXXaaXXXXXa",
+".............aXXaXXXXXXa",
+".............aXXXaXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
+{
+ if (!move_cursor) {
+ move_cursor = new QPixmap((const char **)move_xpm);
+ copy_cursor = new QPixmap((const char **)copy_xpm);
+ link_cursor = new QPixmap((const char **)link_xpm);
+#ifdef Q_WS_WIN
+ ignore_cursor = new QPixmap((const char **)ignore_xpm);
+#endif
+ }
+
+ switch (cshape) {
+ case Qt::DragMoveCursor:
+ return *move_cursor;
+ case Qt::DragCopyCursor:
+ return *copy_cursor;
+ case Qt::DragLinkCursor:
+ return *link_cursor;
+#ifdef Q_WS_WIN
+ case Qt::ForbiddenCursor:
+ return *ignore_cursor;
+#endif
+ default:
+ break;
+ }
+ return QPixmap();
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index 3fba833..25c98c5 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -2168,6 +2168,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
}
if (wheel_deltaX || wheel_deltaY) {
+#ifndef QT_NO_WHEELEVENT
if (wheel_deltaX) {
QWheelEvent qwe(plocal, p, wheel_deltaX, buttons, modifiers, Qt::Horizontal);
QApplication::sendSpontaneousEvent(widget, &qwe);
@@ -2190,6 +2191,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
handled_event = false;
}
}
+#endif // QT_NO_WHEELEVENT
} else {
#ifdef QMAC_SPEAK_TO_ME
const int speak_keys = Qt::AltModifier | Qt::ShiftModifier;
@@ -2764,6 +2766,7 @@ int QApplication::keyboardInputInterval()
return QApplicationPrivate::keyboard_input_time;
}
+#ifndef QT_NO_WHEELEVENT
void QApplication::setWheelScrollLines(int n)
{
QApplicationPrivate::wheel_scroll_lines = n;
@@ -2773,6 +2776,7 @@ int QApplication::wheelScrollLines()
{
return QApplicationPrivate::wheel_scroll_lines;
}
+#endif
void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
{
@@ -2935,9 +2939,11 @@ bool QApplicationPrivate::qt_mac_apply_settings()
QApplication::cursorFlashTime()).toInt();
QApplication::setCursorFlashTime(num);
+#ifndef QT_NO_WHEELEVENT
num = settings.value(QLatin1String("wheelScrollLines"),
QApplication::wheelScrollLines()).toInt();
QApplication::setWheelScrollLines(num);
+#endif
QString colorspec = settings.value(QLatin1String("colorSpec"),
QVariant(QLatin1String("default"))).toString();
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 59565d4..e0a6103 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -427,7 +427,9 @@ public:
static int cursor_flash_time;
static int mouse_double_click_time;
static int keyboard_input_time;
+#ifndef QT_NO_WHEELEVENT
static int wheel_scroll_lines;
+#endif
static bool animate_ui;
static bool animate_menu;
@@ -518,6 +520,13 @@ public:
QGestureManager *gestureManager;
QWidget *gestureWidget;
+ QPixmap *move_cursor;
+ QPixmap *copy_cursor;
+ QPixmap *link_cursor;
+#if defined(Q_WS_WIN)
+ QPixmap *ignore_cursor;
+#endif
+ QPixmap getPixmapCursor(Qt::CursorShape cshape);
QMap<int, QWeakPointer<QWidget> > widgetForTouchPointId;
QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints;
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 20b8030..3e2e6f6 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -809,12 +809,15 @@ TCoeInputCapabilities QSymbianControl::InputCapabilities() const
void QSymbianControl::Draw(const TRect& controlRect) const
{
// Set flag to avoid calling DrawNow in window surface
- QWExtra *extra = qwidget->d_func()->extraData();
- if (extra && !extra->inExpose) {
- extra->inExpose = true;
+ QWidget *window = qwidget->window();
+ Q_ASSERT(window);
+ QTLWExtra *topExtra = window->d_func()->maybeTopData();
+ Q_ASSERT(topExtra);
+ if (!topExtra->inExpose) {
+ topExtra->inExpose = true;
QRect exposeRect = qt_TRect2QRect(controlRect);
qwidget->d_func()->syncBackingStore(exposeRect);
- extra->inExpose = false;
+ topExtra->inExpose = false;
}
QWindowSurface *surface = qwidget->windowSurface();
@@ -924,8 +927,8 @@ void QSymbianControl::PositionChanged()
cr.moveTopLeft(newPos);
qwidget->data->crect = cr;
QTLWExtra *top = qwidget->d_func()->maybeTopData();
- if (top)
- top->normalGeometry = cr;
+ if (top && (qwidget->windowState() & (~Qt::WindowActive)) == Qt::WindowNoState)
+ top->normalGeometry.moveTopLeft(newPos);
if (qwidget->isVisible()) {
QMoveEvent e(newPos, oldPos);
qt_sendSpontaneousEvent(qwidget, &e);
@@ -960,15 +963,14 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
qwidget->d_func()->setWindowIcon_sys(true);
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
#ifdef Q_WS_S60
- // If widget is fullscreen, hide status pane and button container
- // otherwise show them.
+ // If widget is fullscreen/minimized, hide status pane and button container otherwise show them.
CEikStatusPane* statusPane = S60->statusPane();
CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
- bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
- if (statusPane && (bool)statusPane->IsVisible() == isFullscreen)
- statusPane->MakeVisible(!isFullscreen);
- if (buttonGroup && (bool)buttonGroup->IsVisible() == isFullscreen)
- buttonGroup->MakeVisible(!isFullscreen);
+ TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
+ if (statusPane)
+ statusPane->MakeVisible(visible);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(visible);
#endif
} else if (QApplication::activeWindow() == qwidget->window()) {
if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) {
@@ -1647,6 +1649,9 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent
if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) {
delete w->d_func()->topData()->backingStore;
w->d_func()->topData()->backingStore = 0;
+ // In order to ensure that any resources used by the window surface
+ // are immediately freed, we flush the WSERV command buffer.
+ S60->wsSession().Flush();
} else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
&& !w->d_func()->maybeBackingStore()) {
w->d_func()->topData()->backingStore = new QWidgetBackingStore(w);
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 3355272..0a4869b 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -928,7 +928,11 @@ const QString qt_reg_winclass(QWidget *w) // register window class
uint style;
bool icon;
QString cname;
- if (flags & Qt::MSWindowsOwnDC) {
+ if (qt_widget_private(w)->isGLWidget) {
+ cname = QLatin1String("QGLWidget");
+ style = CS_DBLCLKS;
+ icon = true;
+ } else if (flags & Qt::MSWindowsOwnDC) {
cname = QLatin1String("QWidgetOwnDC");
style = CS_DBLCLKS;
#ifndef Q_WS_WINCE
@@ -1021,7 +1025,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
}
wc.hCursor = 0;
#ifndef Q_WS_WINCE
- wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
+ wc.hbrBackground = qt_widget_private(w)->isGLWidget ? 0 : (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
#else
wc.hbrBackground = 0;
#endif
@@ -3616,13 +3620,19 @@ bool QETWidget::translatePaintEvent(const MSG &msg)
return true;
setAttribute(Qt::WA_PendingUpdate, false);
- const QRegion dirtyInBackingStore(qt_dirtyRegion(this));
- // Make sure the invalidated region contains the region we're about to repaint.
- // BeginPaint will set the clip to the invalidated region and it is impossible
- // to enlarge it afterwards (only shrink it). Using GetDCEx is not suffient
- // as it may return an invalid context (especially on Windows Vista).
- if (!dirtyInBackingStore.isEmpty())
- InvalidateRgn(internalWinId(), dirtyInBackingStore.handle(), false);
+
+ if (d_func()->isGLWidget) {
+ if (d_func()->usesDoubleBufferedGLContext)
+ InvalidateRect(internalWinId(), 0, false);
+ } else {
+ const QRegion dirtyInBackingStore(qt_dirtyRegion(this));
+ // Make sure the invalidated region contains the region we're about to repaint.
+ // BeginPaint will set the clip to the invalidated region and it is impossible
+ // to enlarge it afterwards (only shrink it). Using GetDCEx is not suffient
+ // as it may return an invalid context (especially on Windows Vista).
+ if (!dirtyInBackingStore.isEmpty())
+ InvalidateRgn(internalWinId(), dirtyInBackingStore.handle(), false);
+ }
PAINTSTRUCT ps;
d_func()->hd = BeginPaint(internalWinId(), &ps);
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 667db39..34865b5 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -949,10 +949,12 @@ bool QApplicationPrivate::x11_apply_settings()
QApplication::cursorFlashTime()).toInt();
QApplication::setCursorFlashTime(num);
+#ifndef QT_NO_WHEELEVENT
num =
settings.value(QLatin1String("wheelScrollLines"),
QApplication::wheelScrollLines()).toInt();
QApplication::setWheelScrollLines(num);
+#endif
QString colorspec = settings.value(QLatin1String("colorSpec"),
QVariant(QLatin1String("default"))).toString();
@@ -4406,8 +4408,10 @@ bool QETWidget::translateWheelEvent(int global_x, int global_y, int delta,
QWidget* popup = qApp->activePopupWidget();
if (popup && window() != popup)
popup->close();
+#ifndef QT_NO_WHEELEVENT
QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
if (QApplication::sendSpontaneousEvent(widget, &e))
+#endif
return true;
}
@@ -4418,8 +4422,10 @@ bool QETWidget::translateWheelEvent(int global_x, int global_y, int delta,
QWidget* popup = qApp->activePopupWidget();
if (popup && widget != popup)
popup->hide();
+#ifndef QT_NO_WHEELEVENT
QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
if (QApplication::sendSpontaneousEvent(widget, &e))
+#endif
return true;
}
return false;
@@ -5318,6 +5324,7 @@ int QApplication::keyboardInputInterval()
return QApplicationPrivate::keyboard_input_time;
}
+#ifndef QT_NO_WHEELEVENT
void QApplication::setWheelScrollLines(int n)
{
QApplicationPrivate::wheel_scroll_lines = n;
@@ -5327,6 +5334,7 @@ int QApplication::wheelScrollLines()
{
return QApplicationPrivate::wheel_scroll_lines;
}
+#endif
void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
{
diff --git a/src/gui/kernel/qclipboard_mac.cpp b/src/gui/kernel/qclipboard_mac.cpp
index f3a971d..49a6cc8 100644
--- a/src/gui/kernel/qclipboard_mac.cpp
+++ b/src/gui/kernel/qclipboard_mac.cpp
@@ -388,6 +388,18 @@ QMacPasteboard::setMimeData(QMimeData *mime_src)
clear_helper();
QStringList formats = mime_src->formats();
+#ifdef QT_MAC_USE_COCOA
+ // QMimeData sub classes reimplementing the formats() might not expose the
+ // temporary "application/x-qt-mime-type-name" mimetype. So check the existence
+ // of this mime type while doing drag and drop.
+ QString dummyMimeType(QLatin1String("application/x-qt-mime-type-name"));
+ if (!formats.contains(dummyMimeType)) {
+ QByteArray dummyType = mime_src->data(dummyMimeType);
+ if (!dummyType.isEmpty()) {
+ formats.append(dummyMimeType);
+ }
+ }
+#endif
for(int f = 0; f < formats.size(); ++f) {
QString mimeType = formats.at(f);
for (QList<QMacPasteboardMime *>::Iterator it = availableConverters.begin(); it != availableConverters.end(); ++it) {
diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm
index 3012093..0b48efd 100644
--- a/src/gui/kernel/qcocoapanel_mac.mm
+++ b/src/gui/kernel/qcocoapanel_mac.mm
@@ -47,6 +47,9 @@
#import <private/qcocoaview_mac_p.h>
#import <private/qcocoawindowcustomthemeframe_mac_p.h>
#import <private/qcocoaapplication_mac_p.h>
+#include <private/qapplication_p.h>
+#include <private/qbackingstore_p.h>
+
#include <QtGui/QWidget>
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
index d8bbcd4..a1d2c61 100644
--- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
+++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
@@ -51,6 +51,9 @@
NSPanel, while QCocoaWindow needs to inherit NSWindow rather than NSPanel).
****************************************************************************/
+// WARNING: Don't include any header files from within this file. Put them
+// directly into qcocoawindow_mac_p.h and qcocoapanel_mac_p.h
+
QT_BEGIN_NAMESPACE
extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
@@ -205,7 +208,7 @@ QT_END_NAMESPACE
qt_button_down = widget;
handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton);
// Don't call super here. This prevents us from getting the mouseUp event,
- // which we need to send even if the mouseDown event was not accepted.
+ // which we need to send even if the mouseDown event was not accepted.
// (this is standard Qt behavior.)
break;
case NSRightMouseDown:
@@ -303,9 +306,9 @@ QT_END_NAMESPACE
{
// The user dragged something into the window. Send a draggingEntered message
// to the QWidget under the mouse. As the drag moves over the window, and over
- // different widgets, we will handle enter and leave events from within
+ // different widgets, we will handle enter and leave events from within
// draggingUpdated below. The reason why we handle this ourselves rather than
- // subscribing for drag events directly in QCocoaView is that calling
+ // subscribing for drag events directly in QCocoaView is that calling
// registerForDraggedTypes on the views will severly degrade initialization time
// for an application that uses a lot of drag subscribing widgets.
@@ -369,3 +372,18 @@ QT_END_NAMESPACE
return dropResult;
}
+- (void)displayIfNeeded
+{
+
+ QWidget *qwidget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
+ if (qwidget == 0) {
+ [super displayIfNeeded];
+ return;
+ }
+
+ if (QApplicationPrivate::graphicsSystem() != 0) {
+ if (QWidgetBackingStore *bs = qt_widget_private(qwidget)->maybeBackingStore())
+ bs->sync(qwidget, qwidget->rect());
+ }
+ [super displayIfNeeded];
+}
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 8c5d166..873fb7e 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -474,10 +474,11 @@ extern "C" {
- (void)drawRect:(NSRect)aRect
{
if (QApplicationPrivate::graphicsSystem() != 0) {
- if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore())
- bs->markDirty(qwidget->rect(), qwidget);
- qwidgetprivate->syncBackingStore(qwidget->rect());
- return;
+ if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) {
+ // Drawing is handled on the window level
+ // See qcocoasharedwindowmethods_mac_p.
+ return;
+ }
}
CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
qwidgetprivate->hd = cg;
@@ -785,6 +786,7 @@ extern "C" {
deltaZ = qBound(-120, int([theEvent deltaZ] * 10000), 120);
}
+#ifndef QT_NO_WHEELEVENT
if (deltaX != 0) {
QWheelEvent qwe(qlocal, qglobal, deltaX, buttons, keyMods, Qt::Horizontal);
qt_sendSpontaneousEvent(widgetToGetMouse, &qwe);
@@ -825,6 +827,8 @@ extern "C" {
wheelOK = qwe2.isAccepted();
}
}
+#endif //QT_NO_WHEELEVENT
+
if (!wheelOK) {
return [super scrollWheel:theEvent];
}
@@ -1361,7 +1365,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
// setup the data
QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacPasteboardMime::MIME_DND);
- dragPrivate()->data->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray());
+ dragPrivate()->data->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy"));
dragBoard.setMimeData(dragPrivate()->data);
// create the image
diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h
index 403a1a5..21f82df 100644
--- a/src/gui/kernel/qcocoawindow_mac_p.h
+++ b/src/gui/kernel/qcocoawindow_mac_p.h
@@ -53,6 +53,9 @@
#ifdef QT_MAC_USE_COCOA
#include "qmacdefines_mac.h"
#import <Cocoa/Cocoa.h>
+#include <private/qapplication_p.h>
+#include <private/qbackingstore_p.h>
+
enum { QtMacCustomizeWindow = 1 << 21 }; // This will one day be run over by
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 0f0470c..f38e4f5 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -141,6 +141,12 @@ QT_BEGIN_NAMESPACE
\o Qt::WhatsThisCursor \o \c whats_this
\o \inlineimage cursor-closedhand.png
\o Qt::ClosedHandCursor \o \c closedhand
+ \row \o
+ \o Qt::DragMoveCursor \o \c dnd-move or \c move
+ \o
+ \o Qt::DragCopyCursor \o \c dnd-copy or \c copy
+ \row \o
+ \o Qt::DragLinkCursor \o \c dnd-link or \c link
\endtable
\sa QWidget, {fowler}{GUI Design Handbook: Cursors}
diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm
index 48bb9cc..cfebf60 100644
--- a/src/gui/kernel/qcursor_mac.mm
+++ b/src/gui/kernel/qcursor_mac.mm
@@ -424,6 +424,18 @@ void QCursorData::update()
type = QCursorData::TYPE_ThemeCursor;
curs.cp.nscursor = [NSCursor closedHandCursor];
break;
+ case Qt::DragCopyCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor dragCopyCursor];
+ break;
+ case Qt::DragMoveCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor arrowCursor];
+ break;
+ case Qt::DragLinkCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor dragLinkCursor];
+ break;
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
case Qt::SizeVerCursor:
@@ -519,6 +531,18 @@ void QCursorData::update()
type = QCursorData::TYPE_ThemeCursor;
curs.tc.curs = kThemeClosedHandCursor;
break;
+ case Qt::DragMoveCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeArrowCursor;
+ break;
+ case Qt::DragCopyCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeCopyArrowCursor;
+ break;
+ case Qt::DragLinkCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeAliasArrowCursor;
+ break;
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
case Qt::SizeVerCursor:
diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp
index 6f651d4..ae1c004 100644
--- a/src/gui/kernel/qcursor_win.cpp
+++ b/src/gui/kernel/qcursor_win.cpp
@@ -47,6 +47,7 @@
#include <qimage.h>
#include <qt_windows.h>
+#include <private/qapplication_p.h>
QT_BEGIN_NAMESPACE
@@ -470,6 +471,12 @@ void QCursorData::update()
#endif
return;
}
+ case Qt::DragCopyCursor:
+ case Qt::DragMoveCursor:
+ case Qt::DragLinkCursor: {
+ QPixmap pixmap = QApplicationPrivate::instance()->getPixmapCursor(cshape);
+ hcurs = create32BitCursor(pixmap, hx, hy);
+ }
default:
qWarning("QCursor::update: Invalid cursor shape %d", cshape);
return;
diff --git a/src/gui/kernel/qcursor_x11.cpp b/src/gui/kernel/qcursor_x11.cpp
index 3e83363..4e871a6 100644
--- a/src/gui/kernel/qcursor_x11.cpp
+++ b/src/gui/kernel/qcursor_x11.cpp
@@ -39,9 +39,11 @@
**
****************************************************************************/
+#include <qdebug.h>
#include <qdatastream.h>
#include <private/qcursor_p.h>
#include <private/qt_x11_p.h>
+#include <private/qapplication_p.h>
#include <qbitmap.h>
#include <qcursor.h>
#include <X11/cursorfont.h>
@@ -57,6 +59,7 @@
#endif // QT_NO_XFIXES
#include "qx11info_x11.h"
+#include <private/qpixmap_x11_p.h>
QT_BEGIN_NAMESPACE
@@ -262,12 +265,31 @@ void QCursorData::update()
"whats_this",
"left_ptr_watch",
"openhand",
- "closedhand"
+ "closedhand",
+ "copy",
+ "move",
+ "link"
};
#ifndef QT_NO_XCURSOR
- if (X11->ptrXcursorLibraryLoadCursor)
- hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ if (X11->ptrXcursorLibraryLoadCursor) {
+ // special case for non-standard dnd-* cursors
+ switch (cshape) {
+ case Qt::DragCopyCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
+ break;
+ case Qt::DragMoveCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
+ break;
+ case Qt::DragLinkCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
+ break;
+ default:
+ break;
+ }
+ if (!hcurs)
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ }
if (hcurs)
return;
#endif // QT_NO_XCURSOR
@@ -504,6 +526,19 @@ void QCursorData::update()
pm = XCreateBitmapFromData(dpy, rootwin, open ? openhand_bits : closedhand_bits, 16, 16);
pmm = XCreateBitmapFromData(dpy, rootwin, open ? openhandm_bits : closedhandm_bits, 16, 16);
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
+ } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor
+ || cshape == Qt::DragLinkCursor) {
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ QImage image = QApplicationPrivate::instance()->getPixmapCursor(cshape).toImage();
+ pm = QX11PixmapData::createBitmapFromImage(image);
+ pmm = QX11PixmapData::createBitmapFromImage(image.createAlphaMask().convertToFormat(QImage::Format_MonoLSB));
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
}
if (hcurs)
@@ -577,6 +612,15 @@ void QCursorData::update()
case Qt::BusyCursor:
sh = XC_watch;
break;
+ case Qt::DragCopyCursor:
+ sh = XC_tcross;
+ break;
+ case Qt::DragLinkCursor:
+ sh = XC_center_ptr;
+ break;
+ case Qt::DragMoveCursor:
+ sh = XC_top_left_arrow;
+ break;
#endif /* QT_USE_APPROXIMATE_CURSORS */
default:
qWarning("QCursor::update: Invalid cursor shape %d", cshape);
diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp
index 77745ea..84e3c5d 100644
--- a/src/gui/kernel/qdesktopwidget_s60.cpp
+++ b/src/gui/kernel/qdesktopwidget_s60.cpp
@@ -88,24 +88,20 @@ QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
void QDesktopWidgetPrivate::init(QDesktopWidget *that)
{
- int screenCount=0;
+// int screenCount=0;
- if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone)
- QDesktopWidgetPrivate::screenCount = screenCount;
- else
- QDesktopWidgetPrivate::screenCount = 0;
+ // ### TODO: Implement proper multi-display support
+ QDesktopWidgetPrivate::screenCount = 1;
+// if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone)
+// QDesktopWidgetPrivate::screenCount = screenCount;
+// else
+// QDesktopWidgetPrivate::screenCount = 0;
rects = new QVector<QRect>();
workrects = new QVector<QRect>();
rects->resize(QDesktopWidgetPrivate::screenCount);
workrects->resize(QDesktopWidgetPrivate::screenCount);
-
- // ### TODO: Implement proper multi-display support
- rects->resize(1);
- rects->replace(0, that->rect());
- workrects->resize(1);
- workrects->replace(0, that->rect());
}
void QDesktopWidgetPrivate::cleanup()
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index 21438a8..2b3a3d0 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -60,204 +60,12 @@
#include "qdebug.h"
#include <ctype.h>
+#include <private/qapplication_p.h>
+
#ifndef QT_NO_DRAGANDDROP
QT_BEGIN_NAMESPACE
-// These pixmaps approximate the images in the Windows User Interface Guidelines.
-
-// XPM
-
-static const char * const move_xpm[] = {
-"11 20 3 1",
-". c None",
-#if defined(Q_WS_WIN)
-"a c #000000",
-"X c #FFFFFF", // Windows cursor is traditionally white
-#else
-"a c #FFFFFF",
-"X c #000000", // X11 cursor is traditionally black
-#endif
-"aa.........",
-"aXa........",
-"aXXa.......",
-"aXXXa......",
-"aXXXXa.....",
-"aXXXXXa....",
-"aXXXXXXa...",
-"aXXXXXXXa..",
-"aXXXXXXXXa.",
-"aXXXXXXXXXa",
-"aXXXXXXaaaa",
-"aXXXaXXa...",
-"aXXaaXXa...",
-"aXa..aXXa..",
-"aa...aXXa..",
-"a.....aXXa.",
-"......aXXa.",
-".......aXXa",
-".......aXXa",
-"........aa."};
-
-#ifdef Q_WS_WIN
-/* XPM */
-static const char * const ignore_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa.....XXXX.....",
-".......aXXa..XXaaaaXX...",
-".......aXXa.XaaaaaaaaX..",
-"........aa.XaaaXXXXaaaX.",
-"...........XaaaaX..XaaX.",
-"..........XaaXaaaX..XaaX",
-"..........XaaXXaaaX.XaaX",
-"..........XaaX.XaaaXXaaX",
-"..........XaaX..XaaaXaaX",
-"...........XaaX..XaaaaX.",
-"...........XaaaXXXXaaaX.",
-"............XaaaaaaaaX..",
-".............XXaaaaXX...",
-"...............XXXX....."};
-#endif
-
-/* XPM */
-static const char * const copy_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-#if defined(Q_WS_WIN) // Windows cursor is traditionally white
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa..............",
-".......aXXa.............",
-".......aXXa.............",
-"........aa...aaaaaaaaaaa",
-#else
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-#endif
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXaaaaaXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
-/* XPM */
-static const char * const link_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-#if defined(Q_WS_WIN) // Windows cursor is traditionally white
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa..............",
-".......aXXa.............",
-".......aXXa.............",
-"........aa...aaaaaaaaaaa",
-#else
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-#endif
-".............aXXXXXXXXXa",
-".............aXXXaaaaXXa",
-".............aXXXXaaaXXa",
-".............aXXXaaaaXXa",
-".............aXXaaaXaXXa",
-".............aXXaaXXXXXa",
-".............aXXaXXXXXXa",
-".............aXXXaXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
#ifndef QT_NO_DRAGANDDROP
//#define QDND_DEBUG
@@ -326,22 +134,9 @@ QDragManager::QDragManager()
{
Q_ASSERT(!instance);
-#ifdef Q_WS_WIN
- n_cursor = 4;
-#else
- n_cursor = 3;
-#endif
-
#ifdef Q_WS_QWS
currentActionForOverrideCursor = Qt::IgnoreAction;
#endif
- pm_cursor = new QPixmap[n_cursor];
- pm_cursor[0] = QPixmap((const char **)move_xpm);
- pm_cursor[1] = QPixmap((const char **)copy_xpm);
- pm_cursor[2] = QPixmap((const char **)link_xpm);
-#ifdef Q_WS_WIN
- pm_cursor[3] = QPixmap((const char **)ignore_xpm);
-#endif
object = 0;
beingCancelled = false;
restoreCursor = false;
@@ -362,7 +157,6 @@ QDragManager::~QDragManager()
QApplication::restoreOverrideCursor();
#endif
instance = 0;
- delete [] pm_cursor;
delete dropData;
}
@@ -379,14 +173,14 @@ QPixmap QDragManager::dragCursor(Qt::DropAction action) const
if (d && d->customCursors.contains(action))
return d->customCursors[action];
else if (action == Qt::MoveAction)
- return pm_cursor[0];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragMoveCursor);
else if (action == Qt::CopyAction)
- return pm_cursor[1];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragCopyCursor);
else if (action == Qt::LinkAction)
- return pm_cursor[2];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragLinkCursor);
#ifdef Q_WS_WIN
else if (action == Qt::IgnoreAction)
- return pm_cursor[3];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::ForbiddenCursor);
#endif
return QPixmap();
}
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index d70b983..033e6a6 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -261,8 +261,6 @@ public:
#endif
private:
- QPixmap *pm_cursor;
- int n_cursor;
#ifdef Q_WS_QWS
Qt::DropAction currentActionForOverrideCursor;
#endif
diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp
index 33968bd..9591b9a 100644
--- a/src/gui/kernel/qdnd_x11.cpp
+++ b/src/gui/kernel/qdnd_x11.cpp
@@ -1340,9 +1340,9 @@ void QDragManager::updateCursor()
if (!noDropCursor) {
#ifndef QT_NO_CURSOR
noDropCursor = new QCursor(Qt::ForbiddenCursor);
- moveCursor = new QCursor(dragCursor(Qt::MoveAction), 0,0);
- copyCursor = new QCursor(dragCursor(Qt::CopyAction), 0,0);
- linkCursor = new QCursor(dragCursor(Qt::LinkAction), 0,0);
+ moveCursor = new QCursor(Qt::DragMoveCursor);
+ copyCursor = new QCursor(Qt::DragCopyCursor);
+ linkCursor = new QCursor(Qt::DragLinkCursor);
#endif
}
diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp
index 70574e7..4e6c847 100644
--- a/src/gui/kernel/qkeymapper_x11.cpp
+++ b/src/gui/kernel/qkeymapper_x11.cpp
@@ -360,6 +360,13 @@ QList<int> QKeyMapperPrivate::possibleKeysXKB(QKeyEvent *event)
if (code && code < 0xfffe)
code = QChar(code).toUpper().unicode();
+
+ if (code == Qt::Key_Tab && (baseModifiers & Qt::ShiftModifier)) {
+ // map shift+tab to shift+backtab
+ code = Qt::Key_Backtab;
+ text = QString();
+ }
+
if (code == baseCode)
continue;
@@ -448,6 +455,13 @@ QList<int> QKeyMapperPrivate::possibleKeysCore(QKeyEvent *event)
if (code && code < 0xfffe)
code = QChar(code).toUpper().unicode();
+
+ if (code == Qt::Key_Tab && (baseModifiers & Qt::ShiftModifier)) {
+ // map shift+tab to shift+backtab
+ code = Qt::Key_Backtab;
+ text = QString();
+ }
+
if (code == baseCode)
continue;
diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp
index 67ed8b0..8ac1e31 100644
--- a/src/gui/kernel/qsoftkeymanager_s60.cpp
+++ b/src/gui/kernel/qsoftkeymanager_s60.cpp
@@ -49,7 +49,7 @@
#include "private/qsoftkeymanager_p.h"
#include "private/qsoftkeymanager_s60_p.h"
#include "private/qobject_p.h"
-//#include <eiksoftkeyimage.h>
+#include <eiksoftkeyimage.h>
#include <eikcmbut.h>
#ifndef QT_NO_SOFTKEYMANAGER
@@ -64,17 +64,20 @@ QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60()
{
cachedCbaIconSize[0] = QSize(0,0);
cachedCbaIconSize[1] = QSize(0,0);
- skipNextUpdate = false;
+ cachedCbaIconSize[2] = QSize(0,0);
+ cachedCbaIconSize[3] = QSize(0,0);
}
bool QSoftKeyManagerPrivateS60::skipCbaUpdate()
{
- // lets not update softkeys if
+ // Lets not update softkeys if
// 1. We don't have application panes, i.e. cba
- // 2. S60 native dialog or menu is shown
- if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) ||
- CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || skipNextUpdate) {
- skipNextUpdate = false;
+ // 2. Our CBA is not active, i.e. S60 native dialog or menu with custom CBA is shown
+ // Note: Cannot use IsDisplayingMenuOrDialog since CBA update can be triggered before
+ // menu/dialog CBA is actually displayed i.e. it is being costructed.
+ CEikButtonGroupContainer *appUiCba = S60->buttonGroupContainer();
+ CEikButtonGroupContainer *currentCba = CEikButtonGroupContainer::Current();
+ if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) || appUiCba != currentCba) {
return true;
}
return false;
@@ -149,6 +152,39 @@ void QSoftKeyManagerPrivateS60::setNativeSoftkey(CEikButtonGroupContainer &cba,
QT_TRAP_THROWING(cba.SetCommandL(position, command, text));
}
+QPoint QSoftKeyManagerPrivateS60::softkeyIconPosition(int position, QSize sourceSize, QSize targetSize)
+{
+ QPoint iconPosition(0,0);
+ switch( AknLayoutUtils::CbaLocation() )
+ {
+ case AknLayoutUtils::EAknCbaLocationBottom:
+ // RSK must be moved to right, LSK in on correct position by default
+ if (position == RSK_POSITION)
+ iconPosition.setX(targetSize.width() - sourceSize.width());
+ break;
+ case AknLayoutUtils::EAknCbaLocationRight:
+ case AknLayoutUtils::EAknCbaLocationLeft:
+ // Already in correct position
+ default:
+ break;
+ }
+
+ // Align horizontally to center
+ iconPosition.setY((targetSize.height() - sourceSize.height()) >> 1);
+ return iconPosition;
+}
+
+QPixmap QSoftKeyManagerPrivateS60::prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize)
+{
+ QPixmap target(targetSize);
+ target.fill(Qt::transparent);
+ QPainter p;
+ p.begin(&target);
+ p.drawPixmap(softkeyIconPosition(position, src.size(), targetSize), src);
+ p.end();
+ return target;
+}
+
bool QSoftKeyManagerPrivateS60::isOrientationLandscape()
{
// Hard to believe that there is no public API in S60 to
@@ -158,15 +194,11 @@ bool QSoftKeyManagerPrivateS60::isOrientationLandscape()
QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int position)
{
- Q_UNUSED(cba);
- Q_UNUSED(position);
- // Will be implemented when EikSoftkeyImage usage license wise is OK
-/*
- const int index = isOrientationLandscape() ? 0 : 1;
+ int index = position;
+ index += isOrientationLandscape() ? 0 : 1;
if(cachedCbaIconSize[index].isNull()) {
// Only way I figured out to get CBA icon size without RnD SDK, was
- // Only way I figured out to get CBA icon size without RnD SDK, was
// to set some dummy icon to CBA first and then ask CBA button CCoeControl::Size()
// The returned value is cached to avoid unnecessary icon setting every time.
const bool left = (position == LSK_POSITION);
@@ -178,38 +210,46 @@ QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int
setNativeSoftkey(*cba, position, command, KNullDesC());
cachedCbaIconSize[index] = qt_TSize2QSize(cba->ControlOrNull(command)->Size());
EikSoftkeyImage::SetLabel(cba, left);
+
+ if(cachedCbaIconSize[index] == QSize(138,72)) {
+ // Hack for S60 5.0 (5800) landscape orientation, which return wrong icon size
+ cachedCbaIconSize[index] = QSize(60,60);
+ }
}
}
return cachedCbaIconSize[index];
-*/
- return QSize();
}
bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba,
QAction &action, int position)
{
bool ret = false;
- Q_UNUSED(cba);
- Q_UNUSED(action);
- Q_UNUSED(position);
- // Will be implemented when EikSoftkeyImage usage license wise is OK
- /*
const bool left = (position == LSK_POSITION);
if(position == LSK_POSITION || position == RSK_POSITION) {
QIcon icon = action.icon();
if (!icon.isNull()) {
- QPixmap pm = icon.pixmap(cbaIconSize(cba, position));
- pm = pm.scaled(cbaIconSize(cba, position));
- QBitmap mask = pm.mask();
- if (mask.isNull()) {
- mask = QBitmap(pm.size());
- mask.fill(Qt::color1);
+ // Get size of CBA icon area based on button position and orientation
+ QSize requiredIconSize = cbaIconSize(cba, position);
+ // Get pixmap out of icon based on preferred size, the aspect ratio is kept
+ QPixmap pmWihtAspectRatio = icon.pixmap(requiredIconSize);
+ // Native softkeys require that pixmap size is exactly the same as requiredIconSize
+ // prepareSoftkeyPixmap creates a new pixmap with requiredIconSize and blits the 'pmWihtAspectRatio'
+ // to correct location of it
+ QPixmap softkeyPixmap = prepareSoftkeyPixmap(pmWihtAspectRatio, position, requiredIconSize);
+
+ QPixmap softkeyAlpha = softkeyPixmap.alphaChannel();
+ // Alpha channel in 5.1 and older devices need to be inverted
+ // TODO: Switch to use toSymbianCFbsBitmap with invert when available
+ if(QSysInfo::s60Version() <= QSysInfo::SV_S60_5_1) {
+ QImage alphaImage = softkeyAlpha.toImage();
+ alphaImage.invertPixels();
+ softkeyAlpha = QPixmap::fromImage(alphaImage);
}
- CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap();
- CFbsBitmap* nMask = mask.toSymbianCFbsBitmap();
+ CFbsBitmap* nBitmap = softkeyPixmap.toSymbianCFbsBitmap();
+ CFbsBitmap* nMask = softkeyAlpha.toSymbianCFbsBitmap();
CEikImage* myimage = new (ELeave) CEikImage;
myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transfered
@@ -221,7 +261,6 @@ bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba,
EikSoftkeyImage::SetLabel(cba, left);
}
}
- */
return ret;
}
@@ -272,6 +311,7 @@ bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba)
if (windowType != Qt::Dialog && windowType != Qt::Popup) {
QString text(QSoftKeyManager::tr("Exit"));
TPtrC nativeText = qt_QString2TPtrC(text);
+ EikSoftkeyImage::SetLabel(&cba, false);
setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText);
return true;
}
@@ -303,7 +343,6 @@ void QSoftKeyManagerPrivateS60::setSoftkeys(CEikButtonGroupContainer &cba)
void QSoftKeyManagerPrivateS60::updateSoftKeys_sys()
{
- //bool status = CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog();
if (skipCbaUpdate())
return;
@@ -346,9 +385,6 @@ bool QSoftKeyManagerPrivateS60::handleCommand(int command)
}
qt_symbian_next_menu_from_action(actionContainer);
QT_TRAP_THROWING(S60->menuBar()->TryDisplayMenuBarL());
- // TODO: hack remove, it can happen that IsDisplayingMenuOrDialog return false
- // in updateSoftKeys_sys, and we will override menu CBA with our own
- skipNextUpdate = true;
} else {
Q_ASSERT(action->softKeyRole() != QAction::NoSoftKey);
QWidget *actionParent = action->parentWidget();
diff --git a/src/gui/kernel/qsoftkeymanager_s60_p.h b/src/gui/kernel/qsoftkeymanager_s60_p.h
index 46e3596..823a2db 100644
--- a/src/gui/kernel/qsoftkeymanager_s60_p.h
+++ b/src/gui/kernel/qsoftkeymanager_s60_p.h
@@ -84,6 +84,8 @@ private:
QAction *highestPrioritySoftkey(QAction::SoftKeyRole role);
static bool actionPriorityMoreThan(const QAction* item1, const QAction* item2);
void setNativeSoftkey(CEikButtonGroupContainer &cba, TInt position, TInt command, const TDesC& text);
+ QPoint softkeyIconPosition(int position, QSize sourceSize, QSize targetSize);
+ QPixmap prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize);
bool isOrientationLandscape();
QSize cbaIconSize(CEikButtonGroupContainer *cba, int position);
bool setSoftkeyImage(CEikButtonGroupContainer *cba, QAction &action, int position);
@@ -95,8 +97,7 @@ private:
private:
QHash<int, QAction*> realSoftKeyActions;
- QSize cachedCbaIconSize[2];
- bool skipNextUpdate;
+ QSize cachedCbaIconSize[4];
};
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index 377e5a0..4e51cf4 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -1162,7 +1162,7 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget)
CGrafPtr port = GetWindowPort(qt_mac_window_for(widget));
QDBeginCGContext(port, &context);
#else
- CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort];
+ CGContextRef context = reinterpret_cast<CGContextRef>([[qt_mac_window_for(widget) graphicsContext] graphicsPort]);
#endif
return context;
}
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index e678220..d433048 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -192,6 +192,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
, inDirtyList(0)
, isScrolled(0)
, isMoved(0)
+ , isGLWidget(0)
, usesDoubleBufferedGLContext(0)
#if defined(Q_WS_X11)
, picture(0)
@@ -200,7 +201,6 @@ QWidgetPrivate::QWidgetPrivate(int version)
, nativeGesturePanEnabled(0)
#elif defined(Q_WS_MAC)
, needWindowChange(0)
- , isGLWidget(0)
, window_event(0)
, qd_hd(0)
#endif
@@ -1439,6 +1439,18 @@ QWidget::~QWidget()
}
#endif
+#ifdef Q_OS_SYMBIAN
+ if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) {
+ // Okay, we are about to destroy the top-level window that owns
+ // the backing store. Make sure we delete the backing store right away
+ // before the window handle is invalid. This is important because
+ // the backing store will delete its window surface, which may or may
+ // not have a reference to this widget that will be used later to
+ // notify the window it no longer has a surface.
+ delete d->extra->topextra->backingStore;
+ d->extra->topextra->backingStore = 0;
+ }
+#endif
if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
bs->removeDirtyWidget(this);
if (testAttribute(Qt::WA_StaticContents))
@@ -1660,7 +1672,13 @@ void QWidgetPrivate::syncBackingStore()
repaint_sys(dirty);
dirty = QRegion();
} else if (QWidgetBackingStore *bs = maybeBackingStore()) {
+#ifdef QT_MAC_USE_COCOA
+ Q_UNUSED(bs);
+ void qt_mac_set_needs_display(QWidget *, QRegion);
+ qt_mac_set_needs_display(q_func(), QRegion());
+#else
bs->sync();
+#endif
}
}
@@ -1668,8 +1686,15 @@ void QWidgetPrivate::syncBackingStore(const QRegion &region)
{
if (paintOnScreen())
repaint_sys(region);
- else if (QWidgetBackingStore *bs = maybeBackingStore())
+ else if (QWidgetBackingStore *bs = maybeBackingStore()) {
+#ifdef QT_MAC_USE_COCOA
+ Q_UNUSED(bs);
+ void qt_mac_set_needs_display(QWidget *, QRegion);
+ qt_mac_set_needs_display(q_func(), region);
+#else
bs->sync(q_func(), region);
+#endif
+ }
}
void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
@@ -6422,6 +6447,8 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
first = fp;
}
+ if (fp == second)
+ return;
if (QWidget *sp = second->focusProxy())
second = sp;
@@ -7573,23 +7600,21 @@ bool QWidgetPrivate::close_helper(CloseMode mode)
if (isMain)
QApplication::quit();
#endif
- // Attempt to close the application only if this widget has the
- // WA_QuitOnClose flag set set and has a non-visible parent
- quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible() || parentWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
+ quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
if (quitOnClose) {
- // If there is no non-withdrawn primary window left (except
- // the ones without QuitOnClose or with WA_DontShowOnScreen),
- // we emit the lastWindowClosed signal
+ /* if there is no non-withdrawn primary window left (except
+ the ones without QuitOnClose), we emit the lastWindowClosed
+ signal */
QWidgetList list = QApplication::topLevelWidgets();
bool lastWindowClosed = true;
for (int i = 0; i < list.size(); ++i) {
QWidget *w = list.at(i);
- if ((w->isVisible() && !w->testAttribute(Qt::WA_DontShowOnScreen))
- && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose)) {
- lastWindowClosed = false;
- break;
- }
+ if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
+ continue;
+ lastWindowClosed = false;
+ break;
}
if (lastWindowClosed)
QApplicationPrivate::emitLastWindowClosed();
@@ -8252,7 +8277,7 @@ bool QWidget::event(QEvent *event)
}
#ifdef QT_SOFTKEYS_ENABLED
- if (isWindow() && isActiveWindow())
+ if (isWindow())
QSoftKeyManager::updateSoftKeys();
#endif
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index 878b776..a5633d3 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -565,6 +565,25 @@ inline static void qt_mac_set_window_group_to_popup(OSWindowRef window)
}
#endif
+#ifdef QT_MAC_USE_COCOA
+void qt_mac_set_needs_display(QWidget *widget, QRegion region)
+{
+ NSView *theNSView = qt_mac_nativeview_for(widget);
+ if (region.isEmpty()) {
+ [theNSView setNeedsDisplay:YES];
+ return;
+ }
+
+ QVector<QRect> rects = region.rects();
+ for (int i = 0; i<rects.count(); ++i) {
+ const QRect &rect = rects.at(i);
+ NSRect nsrect = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
+ [theNSView setNeedsDisplayInRect:nsrect];
+ }
+
+}
+#endif
+
inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRect &rect)
{
if (!widget)
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index ff8f276..75b4c12 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -174,6 +174,8 @@ struct QTLWExtra {
#ifndef QT_NO_QWS_MANAGER
QWSManager *qwsManager;
#endif
+#elif defined(Q_OS_SYMBIAN)
+ uint inExpose : 1; // Prevents drawing recursion
#endif
};
@@ -230,7 +232,6 @@ struct QWExtra {
#endif
#elif defined(Q_OS_SYMBIAN) // <----------------------------------------------------- Symbian
uint activated : 1; // RWindowBase::Activated has been called
- uint inExpose : 1; // Prevents drawing recursion
/**
* Defines the behaviour of QSymbianControl::Draw.
@@ -685,6 +686,7 @@ public:
uint inDirtyList : 1;
uint isScrolled : 1;
uint isMoved : 1;
+ uint isGLWidget : 1;
uint usesDoubleBufferedGLContext : 1;
// *************************** Platform specific ************************************
@@ -716,7 +718,6 @@ public:
#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
// This is new stuff
uint needWindowChange : 1;
- uint isGLWidget : 1;
// Each wiget keeps a list of all its child and grandchild OpenGL widgets.
// This list is used to update the gl context whenever a parent and a granparent
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index 00f2213..ebd289c 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -878,6 +878,7 @@ void QWidgetPrivate::registerDropSite(bool /* on */)
void QWidgetPrivate::createTLSysExtra()
{
extra->topextra->backingStore = 0;
+ extra->topextra->inExpose = 0;
}
void QWidgetPrivate::deleteTLSysExtra()
@@ -891,7 +892,6 @@ void QWidgetPrivate::createSysExtra()
extra->activated = 0;
extra->nativePaintMode = QWExtra::Default;
extra->receiveNativePaintEvents = 0;
- extra->inExpose = 0;
}
void QWidgetPrivate::deleteSysExtra()
@@ -1046,96 +1046,48 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
return;
if (isWindow()) {
-#ifdef Q_WS_S60
- // Change window decoration visibility if switching to or from fullsccreen
- // In addition decoration visibility is changed when the initial has been
- // WindowNoState.
- // The window decoration visibility has to be changed before doing actual
- // window state change since in that order the availableGeometry will return
- // directly the right size and we will avoid unnecessarty redraws
- if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen) ||
- oldstate == Qt::WindowNoState) {
- CEikStatusPane* statusPane = S60->statusPane();
- CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
- if (newstate & Qt::WindowFullScreen) {
- if (statusPane)
- statusPane->MakeVisible(false);
- if (buttonGroup)
- buttonGroup->MakeVisible(false);
- } else {
- if (statusPane)
- statusPane->MakeVisible(true);
- if (buttonGroup)
- buttonGroup->MakeVisible(true);
- }
+ QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId());
+ if (window && newstate & Qt::WindowMinimized) {
+ window->setFocusSafely(false);
+ window->MakeVisible(false);
+ } else if (window && oldstate & Qt::WindowMinimized) {
+ window->setFocusSafely(true);
+ window->MakeVisible(true);
}
+
+#ifdef Q_WS_S60
+ // Hide window decoration when switching to fullsccreen / minimized otherwise show decoration.
+ // The window decoration visibility has to be changed before doing actual window state
+ // change since in that order the availableGeometry will return directly the right size and
+ // we will avoid unnecessarty redraws
+ CEikStatusPane* statusPane = S60->statusPane();
+ CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+ TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized));
+ if (statusPane)
+ statusPane->MakeVisible(visible);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(visible);
#endif // Q_WS_S60
createWinId();
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
- QTLWExtra *top = d->topData();
-
// Ensure the initial size is valid, since we store it as normalGeometry below.
if (!testAttribute(Qt::WA_Resized) && !isVisible())
adjustSize();
- if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
- if ((newstate & Qt::WindowMaximized)) {
- const QRect normalGeometry = geometry();
+ QTLWExtra *top = d->topData();
+ const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry;
- const QRect r = top->normalGeometry;
- setGeometry(qApp->desktop()->availableGeometry(this));
- top->normalGeometry = r;
+ if (newstate & Qt::WindowFullScreen)
+ setGeometry(qApp->desktop()->screenGeometry(this));
+ else if (newstate & Qt::WindowMaximized)
+ setGeometry(qApp->desktop()->availableGeometry(this));
+ else
+ setGeometry(normalGeometry);
- if (top->normalGeometry.width() < 0)
- top->normalGeometry = normalGeometry;
- } else {
- // restore original geometry
- setGeometry(top->normalGeometry);
- }
- }
- if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
- if (newstate & Qt::WindowFullScreen) {
- const QRect normalGeometry = geometry();
- const QRect r = top->normalGeometry;
- setGeometry(qApp->desktop()->screenGeometry(this));
-
- top->normalGeometry = r;
- if (top->normalGeometry.width() < 0)
- top->normalGeometry = normalGeometry;
- } else {
- if (newstate & Qt::WindowMaximized) {
- const QRect r = top->normalGeometry;
- setGeometry(qApp->desktop()->availableGeometry(this));
- top->normalGeometry = r;
- } else {
- setGeometry(top->normalGeometry);
- }
- }
- }
- if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
- if (newstate & Qt::WindowMinimized) {
- if (isVisible()) {
- QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId());
- if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
- id->setFocusSafely(false);
- id->MakeVisible(false);
- }
- } else {
- if (isVisible()) {
- QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId());
- id->MakeVisible(true);
- if (!id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
- id->setFocusSafely(true);
- }
- const QRect normalGeometry = geometry();
- const QRect r = top->normalGeometry;
- top->normalGeometry = r;
- if (top->normalGeometry.width() < 0)
- top->normalGeometry = normalGeometry;
- }
- }
+ //restore normal geometry
+ top->normalGeometry = normalGeometry;
}
data->window_state = newstate;
@@ -1195,6 +1147,10 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
if (destroyWindow) {
delete id;
+ // At this point the backing store should already be destroyed
+ // so we flush the command buffer to ensure that the freeing of
+ // those resources and deleting the window can happen "atomically"
+ S60->wsSession().Flush();
}
}
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 6a36293..8cab387 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -1156,7 +1156,10 @@ void QWidgetPrivate::show_sys()
data.window_state |= Qt::WindowMinimized;
if (IsZoomed(q->internalWinId()))
data.window_state |= Qt::WindowMaximized;
- if (q->windowType() == Qt::Popup)
+ // This is to resolve the problem where popups are opened from the
+ // system tray and not being implicitly activated
+ if (q->windowType() == Qt::Popup &&
+ (!q->parentWidget() || !q->parentWidget()->isActiveWindow()))
q->activateWindow();
}
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 4684bc1..10fb009 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -346,11 +346,6 @@ Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
qt_x11_enforce_cursor(w, false);
}
-static Bool checkForConfigureAndExpose(Display *, XEvent *e, XPointer)
-{
- return e->type == ConfigureNotify || e->type == Expose;
-}
-
Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
{
if (!w || (!w->isWindow() && !w->internalWinId()))
@@ -363,38 +358,60 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
if (!w->testAttribute(Qt::WA_WState_Created))
return;
- if (!(w->windowFlags() & Qt::X11BypassWindowManagerHint)) {
- // if the window is not override-redirect, then the window manager
- // will reparent us to the frame decoration window.
- while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ReparentNotify, &ev)) {
- if (t.elapsed() > maximumWaitTime)
- return;
- qApp->syncX(); // non-busy wait
- }
- }
+ WId winid = w->internalWinId();
- while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev)) {
- if (t.elapsed() > maximumWaitTime)
- return;
- qApp->syncX(); // non-busy wait
- }
+ // first deliver events that are already in the local queue
+ QApplication::sendPostedEvents();
- qApp->x11ProcessEvent(&ev);
+ // the normal sequence is:
+ // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
+ // with X11BypassWindowManagerHint:
+ // ConfigureNotify ... MapNotify ... Expose
- // ok, seems like the window manager successfully reparented us, we'll wait
- // for the first paint event to arrive, while handling ConfigureNotify in
- // the arrival order
- while(1)
- {
- if (XCheckIfEvent(X11->display, &ev, checkForConfigureAndExpose, 0)) {
+ enum State {
+ Initial, Reparented, Mapped
+ } state = Initial;
+
+ do {
+ if (XEventsQueued(X11->display, QueuedAlready)) {
+ XNextEvent(X11->display, &ev);
qApp->x11ProcessEvent(&ev);
- if (ev.type == Expose)
- return;
+
+ if (w->windowFlags() & Qt::X11BypassWindowManagerHint) {
+ switch (state) {
+ case Initial:
+ case Reparented:
+ if (ev.type == MapNotify && ev.xany.window == winid)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose && ev.xany.window == winid)
+ return;
+ break;
+ }
+ } else {
+ switch (state) {
+ case Initial:
+ if (ev.type == ReparentNotify && ev.xany.window == winid)
+ state = Reparented;
+ break;
+ case Reparented:
+ if (ev.type == MapNotify && ev.xany.window == winid)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose && ev.xany.window == winid)
+ return;
+ break;
+ }
+ }
+ } else {
+ if (!XEventsQueued(X11->display, QueuedAfterFlush))
+ qApp->syncX(); // non-busy wait
}
if (t.elapsed() > maximumWaitTime)
return;
- qApp->syncX(); // non-busy wait
- }
+ } while(1);
}
void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 194dda3..7a3da20 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1267,32 +1267,28 @@ static const uint L2CacheLineLengthInInts = L2CacheLineLength/sizeof(uint);
result = 0
d = d * cia
*/
+#define comp_func_Clear_impl(dest, length, const_alpha)\
+{\
+ if (const_alpha == 255) {\
+ QT_MEMFILL_UINT(dest, length, 0);\
+ } else {\
+ int ialpha = 255 - const_alpha;\
+ PRELOAD_INIT(dest)\
+ for (int i = 0; i < length; ++i) {\
+ PRELOAD_COND(dest)\
+ dest[i] = BYTE_MUL(dest[i], ialpha);\
+ }\
+ }\
+}
+
static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
{
- if (const_alpha == 255) {
- QT_MEMFILL_UINT(dest, length, 0);
- } else {
- int ialpha = 255 - const_alpha;
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = BYTE_MUL(dest[i], ialpha);
- }
- }
+ comp_func_Clear_impl(dest, length, const_alpha);
}
static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- QT_MEMFILL_UINT(dest, length, 0);
- } else {
- int ialpha = 255 - const_alpha;
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = BYTE_MUL(dest[i], ialpha);
- }
- }
+ comp_func_Clear_impl(dest, length, const_alpha);
}
/*
@@ -2408,7 +2404,11 @@ static inline int soft_light_op(int dst, int src, int da, int sa)
else if (4 * dst <= da)
return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025;
else {
+# ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2
+ return (dst * sa * 255 + da * (src2 - sa) * (qIntSqrtInt(dst_np * 255) - dst_np) + temp) / 65025;
+# else
return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025;
+# endif
}
}
diff --git a/src/gui/painting/qdrawhelper_mmx_p.h b/src/gui/painting/qdrawhelper_mmx_p.h
index 8482262..59b3804 100644
--- a/src/gui/painting/qdrawhelper_mmx_p.h
+++ b/src/gui/painting/qdrawhelper_mmx_p.h
@@ -146,36 +146,30 @@ struct QMMXCommonIntrinsics
result = 0
d = d * cia
*/
+#define comp_func_Clear_impl(dest, length, const_alpha)\
+{\
+ if (const_alpha == 255) {\
+ qt_memfill(static_cast<quint32*>(dest), quint32(0), length);\
+ } else {\
+ C_FF; C_80; C_00;\
+ m64 ia = MM::negate(MM::load_alpha(const_alpha));\
+ for (int i = 0; i < length; ++i) {\
+ dest[i] = MM::store(MM::byte_mul(MM::load(dest[i]), ia));\
+ }\
+ MM::end();\
+ }\
+}
+
template <class MM>
static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
{
- if (!length)
- return;
-
- if (const_alpha == 255) {
- qt_memfill(static_cast<quint32*>(dest), quint32(0), length);
- } else {
- C_FF; C_80; C_00;
- m64 ia = MM::negate(MM::load_alpha(const_alpha));
- for (int i = 0; i < length; ++i) {
- dest[i] = MM::store(MM::byte_mul(MM::load(dest[i]), ia));
- }
- }
- MM::end();
+ comp_func_Clear_impl(dest, length, const_alpha);
}
template <class MM>
static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- qt_memfill(static_cast<quint32*>(dest), quint32(0), length);
- } else {
- C_FF; C_80; C_00;
- m64 ia = MM::negate(MM::load_alpha(const_alpha));
- for (int i = 0; i < length; ++i)
- dest[i] = MM::store(MM::byte_mul(MM::load(dest[i]), ia));
- }
- MM::end();
+ comp_func_Clear_impl(dest, length, const_alpha);
}
/*
@@ -246,7 +240,10 @@ static void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int le
C_FF; C_80; C_00;
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- if ((0xff000000 & src[i]) == 0xff000000) {
+ const uint alphaMaskedSource = 0xff000000 & src[i];
+ if (alphaMaskedSource == 0)
+ continue;
+ if (alphaMaskedSource == 0xff000000) {
dest[i] = src[i];
} else {
m64 s = MM::load(src[i]);
@@ -257,6 +254,8 @@ static void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int le
} else {
m64 ca = MM::load_alpha(const_alpha);
for (int i = 0; i < length; ++i) {
+ if ((0xff000000 & src[i]) == 0)
+ continue;
m64 s = MM::byte_mul(MM::load(src[i]), ca);
m64 ia = MM::negate(MM::alpha(s));
dest[i] = MM::store(MM::add(s, MM::byte_mul(MM::load(dest[i]), ia)));
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 6c47aac..cb0db4f 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -1549,6 +1549,9 @@ template<> inline void qt_memfill(quint8 *dest, quint8 color, int count)
template <class T>
inline void qt_memfill(T *dest, T value, int count)
{
+ if (!count)
+ return;
+
int n = (count + 7) / 8;
switch (count & 0x07)
{
diff --git a/src/gui/painting/qmath_p.h b/src/gui/painting/qmath_p.h
index cd9f5ea..8a5f5ab 100644
--- a/src/gui/painting/qmath_p.h
+++ b/src/gui/painting/qmath_p.h
@@ -54,6 +54,7 @@
//
#include <math.h>
+#include <qmath.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +62,11 @@ static const qreal Q_PI = qreal(3.14159265358979323846); // pi
static const qreal Q_2PI = qreal(6.28318530717958647693); // 2*pi
static const qreal Q_PI2 = qreal(1.57079632679489661923); // pi/2
+inline int qIntSqrtInt(int v)
+{
+ return static_cast<int>(qSqrt(static_cast<qreal>(v)));
+}
+
QT_END_NAMESPACE
#endif // QMATH_P_H
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index 147491e..da48fcb 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -1989,6 +1989,9 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
}
XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh);
restore_clip = true;
+ } else if (mono_dst && !mono_src) {
+ QBitmap bitmap(pixmap);
+ XCopyArea(d->dpy, bitmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y);
} else {
XCopyArea(d->dpy, pixmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y);
}
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index cde6a2d..3bcaf8c 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1986,12 +1986,25 @@ QPaintEngine *QPainter::paintEngine() const
endNativePainting().
Note that only the states the underlying paint engine changes will be reset
- to their respective default states. If, for example, the OpenGL polygon
- mode is changed by the user inside a beginNativePaint()/endNativePainting()
- block, it will not be reset to the default state by endNativePainting().
+ to their respective default states. The states we reset may change from
+ release to release. The following states are currently reset in the OpenGL
+ 2 engine:
- Here is an example that shows intermixing of painter commands
- and raw OpenGL commands:
+ \list
+ \i blending is disabled
+ \i the depth, stencil and scissor tests are disabled
+ \i the active texture unit is reset to 0
+ \i the depth mask, depth function and the clear depth are reset to their
+ default values
+ \i the stencil mask, stencil operation and stencil function are reset to
+ their default values
+ \i the current color is reset to solid white
+ \endlist
+
+ If, for example, the OpenGL polygon mode is changed by the user inside a
+ beginNativePaint()/endNativePainting() block, it will not be reset to the
+ default state by endNativePainting(). Here is an example that shows
+ intermixing of painter commands and raw OpenGL commands:
\snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
@@ -7509,7 +7522,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
return widgetPrivate->redirected(offset);
}
- if (*globalRedirectionAtomic() == 0)
+ if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return 0;
QMutexLocker locker(globalRedirectionsMutex());
@@ -7529,7 +7542,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
void qt_painter_removePaintDevice(QPaintDevice *dev)
{
- if (*globalRedirectionAtomic() == 0)
+ if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return;
QMutex *mutex = 0;
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 7997e77..bc81514 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -90,8 +90,6 @@ static QPointF normalize(const QPointF &p)
return p / qSqrt(p.x() * p.x() + p.y() * p.y());
}
-static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
-
struct QIntersection
{
qreal alphaA;
@@ -1660,7 +1658,7 @@ static bool fuzzyCompare(qreal a, qreal b)
return qFuzzyCompare(a, b);
}
-static bool pathToRect(const QPainterPath &path, QRectF *rect)
+bool QPathClipper::pathToRect(const QPainterPath &path, QRectF *rect)
{
if (path.elementCount() != 5)
return false;
@@ -1693,7 +1691,7 @@ static bool pathToRect(const QPainterPath &path, QRectF *rect)
return false;
if (rect)
- *rect = QRectF(QPointF(x1, y1), QPointF(x2, y2));
+ rect->setCoords(x1, y1, x2, y2);
return true;
}
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 0d2c049..b900862 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -86,6 +86,8 @@ public:
bool intersect();
bool contains();
+ static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
+
private:
Q_DISABLE_COPY(QPathClipper)
diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp
index a0d2b9b..eee6bef 100644
--- a/src/gui/painting/qwindowsurface_raster.cpp
+++ b/src/gui/painting/qwindowsurface_raster.cpp
@@ -295,10 +295,8 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
CGContextRestoreGState(context);
#ifndef QT_MAC_USE_COCOA
QDEndCGContext(port, &context);
-#else
- CGContextFlush(context);
-#endif
#endif
+#endif // Q_WS_MAC
#ifdef Q_OS_SYMBIAN
Q_UNUSED(widget);
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp
index b41dc2c..6cbf3d9 100644
--- a/src/gui/painting/qwindowsurface_s60.cpp
+++ b/src/gui/painting/qwindowsurface_s60.cpp
@@ -145,12 +145,15 @@ QImage* QS60WindowSurface::buffer(const QWidget *widget)
void QS60WindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &)
{
- QWExtra *extra = widget->d_func()->extraData();
- if (extra && !extra->inExpose) {
- extra->inExpose = true; // Prevent DrawNow() from calling syncBackingStore() again
+ QWidget *window = widget->window();
+ Q_ASSERT(window);
+ QTLWExtra *topExtra = window->d_func()->maybeTopData();
+ Q_ASSERT(topExtra);
+ if (!topExtra->inExpose) {
+ topExtra->inExpose = true; // Prevent DrawNow() from calling syncBackingStore() again
TRect tr = qt_QRect2TRect(region.boundingRect());
widget->winId()->DrawNow(tr);
- extra->inExpose = false;
+ topExtra->inExpose = false;
}
}
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index 3132dd1..f8464cc 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -1149,10 +1149,10 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget
int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2;
if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth)
verticalShift = -verticalShift;
- tr.adjust(hpadding, vpadding, horizontalShift - hpadding, verticalShift - vpadding);
+ tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding);
bool selected = opt->state & QStyle::State_Selected;
if (selected) {
- tr.setBottom(tr.bottom() - verticalShift);
+ tr.setTop(tr.top() - verticalShift);
tr.setRight(tr.right() - horizontalShift);
}
@@ -5761,88 +5761,88 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
switch (standardIcon) {
#ifndef QT_NO_IMAGEFORMAT_PNG
case SP_FileDialogNewFolder:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-128.png"), QSize(128, 128));
break;
case SP_FileDialogBack:
return standardIconImplementation(SP_ArrowBack, option, widget);
case SP_FileDialogToParent:
return standardIconImplementation(SP_ArrowUp, option, widget);
case SP_FileDialogDetailedView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-128.png"), QSize(128, 128));
break;
case SP_FileDialogInfoView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-128.png"), QSize(128, 128));
break;
case SP_FileDialogContentsView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-128.png"), QSize(128, 128));
break;
case SP_FileDialogListView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-128.png"), QSize(128, 128));
break;
case SP_DialogOkButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-128.png"), QSize(128, 128));
break;
case SP_DialogCancelButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-128.png"), QSize(128, 128));
break;
case SP_DialogHelpButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-128.png"), QSize(128, 128));
break;
case SP_DialogOpenButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png"), QSize(128, 128));
break;
case SP_DialogSaveButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png"), QSize(128, 128));
break;
case SP_DialogCloseButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-128.png"), QSize(128, 128));
break;
case SP_DialogApplyButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-128.png"), QSize(128, 128));
break;
case SP_DialogResetButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-128.png"), QSize(128, 128));
break;
case SP_DialogDiscardButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-128.png"), QSize(128, 128));
break;
case SP_DialogYesButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-128.png"), QSize(128, 128));
break;
case SP_DialogNoButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-128.png"), QSize(128, 128));
break;
case SP_ArrowForward:
if (rtl)
@@ -5853,24 +5853,24 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
return standardIconImplementation(SP_ArrowRight, option, widget);
return standardIconImplementation(SP_ArrowLeft, option, widget);
case SP_ArrowLeft:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-128.png"), QSize(128, 128));
break;
case SP_ArrowRight:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-128.png"), QSize(128, 128));
break;
case SP_ArrowUp:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-128.png"), QSize(128, 128));
break;
case SP_ArrowDown:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-128.png"), QSize(128, 128));
break;
case SP_DirHomeIcon:
case SP_DirIcon:
@@ -5888,71 +5888,71 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
QSize(128, 128), QIcon::Normal, QIcon::On);
break;
case SP_DriveCDIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-128.png"), QSize(128, 128));
break;
case SP_DriveDVDIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-128.png"), QSize(128, 128));
break;
case SP_FileIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-128.png"), QSize(128, 128));
break;
case SP_FileLinkIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-128.png"), QSize(128, 128));
break;
case SP_TrashIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-128.png"), QSize(128, 128));
break;
case SP_BrowserReload:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-24.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-24.png"), QSize(24, 24));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-32.png"), QSize(32, 32));
break;
case SP_BrowserStop:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-24.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-24.png"), QSize(24, 24));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-32.png"), QSize(32, 32));
break;
case SP_MediaPlay:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-32.png"), QSize(32, 32));
break;
case SP_MediaPause:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-32.png"), QSize(32, 32));
break;
case SP_MediaStop:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-32.png"), QSize(32, 32));
break;
case SP_MediaSeekForward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-32.png"), QSize(32, 32));
break;
case SP_MediaSeekBackward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-32.png"), QSize(32, 32));
break;
case SP_MediaSkipForward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-32.png"), QSize(32, 32));
break;
case SP_MediaSkipBackward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-32.png"), QSize(32, 32));
break;
case SP_MediaVolume:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-16.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-16.png"), QSize(16, 16));
break;
case SP_MediaVolumeMuted:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-muted-16.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-muted-16.png"), QSize(16, 16));
break;
#endif // QT_NO_IMAGEFORMAT_PNG
default:
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index a077cf0..40ee31d 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -3391,8 +3391,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
needText = true;
if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
- pr.setHeight(pixmap.size().height());
- cr.adjust(0, pr.bottom() + 1, 0, 1);
+ QMainWindow *mw = qobject_cast<QMainWindow *>(w->window());
+ if (mw && mw->unifiedTitleAndToolBarOnMac()) {
+ pr.setHeight(pixmap.size().height());
+ cr.adjust(0, pr.bottom() + 1, 0, 1);
+ } else {
+ pr.setHeight(pixmap.size().height() + 6);
+ cr.adjust(0, pr.bottom(), 0, -3);
+ }
alignment |= Qt::AlignCenter;
} else {
pr.setWidth(pixmap.width() + 8);
diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp
index f87cf28..3f09ebc 100644
--- a/src/gui/styles/qs60style_simulated.cpp
+++ b/src/gui/styles/qs60style_simulated.cpp
@@ -94,12 +94,12 @@ bool saveThemeToBlob(const QString &themeBlob,
dataOut << color;
}
- const int picturesCount = partPictures.count();
- dataOut << picturesCount;
- foreach (const QString &key, partPictures.keys()) {
- const QPicture picture = partPictures.value(key);
- dataOut << key;
- dataOut << picture;
+ dataOut << partPictures.count();
+ QHashIterator<QString, QPicture> i(partPictures);
+ while (i.hasNext()) {
+ i.next();
+ dataOut << i.key();
+ dataOut << i.value(); // the QPicture
}
QDataStream blobOut(&blob);
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 9002172..1f9fc32 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -1125,6 +1125,7 @@ void QRenderRule::fixupBorder(int nativeWidth)
void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
{
+ setClip(p, rect);
static const Qt::TileRule tileMode2TileRule[] = {
Qt::StretchTile, Qt::RoundTile, Qt::StretchTile, Qt::RepeatTile, Qt::StretchTile };
@@ -1142,6 +1143,7 @@ void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins,
QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch]));
p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform);
+ unsetClip(p);
}
QRect QRenderRule::originRect(const QRect &rect, Origin origin) const
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index bbd35f1..dd9e69e 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -629,8 +629,9 @@ QFontEngineData::~QFontEngineData()
Returns the name of the font within the underlying window system.
- Only on X11 when Qt was built without FontConfig support the XLFD (X Logical Font Description)
- is returned; otherwise an empty string.
+ On X11, this function will return an empty string if Qt is built with
+ FontConfig support; otherwise the XLFD (X Logical Font Description) is
+ returned.
Using the return value of this function is usually \e not \e
portable.
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 3ae6fe9..87a73df 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -246,8 +246,8 @@ static void initializeDb()
QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces();
- const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
- Q_ASSERT(store);
+ const QFontDatabaseS60StoreImplementation *store =
+ static_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
bool fontAdded = false;
for (int i = 0; i < numTypeFaces; i++) {
TTypefaceSupport typefaceSupport;
@@ -258,8 +258,7 @@ static void initializeDb()
continue;
if (font->TypeUid() == KCFbsFontUid) {
TOpenFontFaceAttrib faceAttrib;
- const CFbsFont *cfbsFont = dynamic_cast<const CFbsFont *>(font);
- Q_ASSERT(cfbsFont);
+ const CFbsFont *cfbsFont = static_cast<const CFbsFont *>(font);
cfbsFont->GetFaceAttrib(faceAttrib);
QtFontStyle::Key styleKey;
@@ -390,8 +389,8 @@ QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *, const QFo
QFontDef request = req;
request.family = fontFamily;
#if defined(QT_NO_FREETYPE)
- const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
- Q_ASSERT(store);
+ const QFontDatabaseS60StoreImplementation *store =
+ static_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
const QFontEngineS60Extensions *extension = store->extension(fontFamily);
fe = new QFontEngineS60(request, extension);
#else
diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
index 9dd4af7..3ea084b 100644
--- a/src/gui/text/qfontengine_s60.cpp
+++ b/src/gui/text/qfontengine_s60.cpp
@@ -44,7 +44,7 @@
#include "qglobal.h"
#include <private/qapplication_p.h>
#include "qimage.h"
-#include "qt_s60_p.h"
+#include <private/qt_s60_p.h>
#include <e32base.h>
#include <e32std.h>
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index aaaa3ca..f345cd1 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -441,7 +441,6 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged()));
// convenience signal forwards
- QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool)));
@@ -452,8 +451,11 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
if (!document)
doc->setUndoRedoEnabled(false);
+ //Saving the index save some time.
+ static int contentsChangedIndex = QTextDocument::staticMetaObject.indexOfSignal("contentsChanged()");
+ static int textChangedIndex = QTextControl::staticMetaObject.indexOfSignal("textChanged()");
// avoid multiple textChanged() signals being emitted
- QObject::disconnect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
+ QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex);
if (!text.isEmpty()) {
// clear 'our' cursor for insertion to prevent
@@ -488,7 +490,7 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
}
cursor.setCharFormat(charFormatForInsertion);
- QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
+ QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex);
emit q->textChanged();
if (!document)
doc->setUndoRedoEnabled(previousUndoRedoState);
@@ -1762,8 +1764,8 @@ void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPoint
QMenu *menu = q->createStandardContextMenu(docPos, contextWidget);
if (!menu)
return;
- menu->exec(screenPos);
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(screenPos);
#endif
}
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index b8c9b94..80931c9 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -436,6 +436,23 @@ void QTextDocument::redo(QTextCursor *cursor)
}
/*!
+ \since 4.7
+ Clears the specified stacks.
+
+ This method clears any commands on the undo stack, the redo stack, or both (the
+ default). If any commands got cleared, the appropriate signals
+ (\a QTextDocument::undoAvailable or \a QTextDocument::redoAvailable) get
+ emitted.
+
+ \sa QTextDocument::undoAvailable QTextDocument::redoAvailable
+*/
+void QTextDocument::clearUndoRedoStacks(Stacks stacksToClear)
+{
+ Q_D(QTextDocument);
+ d->clearUndoRedoStacks(stacksToClear, true);
+}
+
+/*!
\overload
*/
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index b5bcb41..0140772 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -256,6 +256,13 @@ public:
void undo(QTextCursor *cursor);
void redo(QTextCursor *cursor);
+ enum Stacks {
+ UndoStack = 0x01,
+ RedoStack = 0x02,
+ UndoAndRedoStacks = UndoStack | RedoStack
+ };
+ void clearUndoRedoStacks(Stacks historyToClear = UndoAndRedoStacks);
+
int maximumBlockCount() const;
void setMaximumBlockCount(int maximum);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 372b9dc..969d5b4 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -259,8 +259,7 @@ void QTextDocumentPrivate::clear()
objects.clear();
title.clear();
- undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);
text = QString();
unreachableCharacterCount = 0;
modifiedState = 0;
@@ -292,7 +291,7 @@ QTextDocumentPrivate::~QTextDocumentPrivate()
cursors.clear();
undoState = 0;
undoEnabled = true;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
}
void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
@@ -1027,7 +1026,7 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
if (!undoEnabled)
return;
if (undoState < undoStack.size())
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
if (!undoStack.isEmpty() && modified) {
QTextUndoCommand &last = undoStack[undoState - 1];
@@ -1050,26 +1049,46 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
emit document()->undoCommandAdded();
}
-void QTextDocumentPrivate::truncateUndoStack()
+void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,
+ bool emitSignals)
{
- if (undoState == undoStack.size())
- return;
-
- for (int i = undoState; i < undoStack.size(); ++i) {
- QTextUndoCommand c = undoStack[i];
- if (c.command & QTextUndoCommand::Removed) {
- // ########
-// QTextFragment *f = c.fragment_list;
-// while (f) {
-// QTextFragment *n = f->right;
-// delete f;
-// f = n;
-// }
- } else if (c.command & QTextUndoCommand::Custom) {
- delete c.custom;
+ bool undoCommandsAvailable = undoState != 0;
+ bool redoCommandsAvailable = undoState != undoStack.size();
+ if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
+ for (int i = 0; i < undoState; ++i) {
+ QTextUndoCommand c = undoStack[undoState];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
}
+ undoStack.remove(0, undoState);
+ undoStack.resize(undoStack.size() - undoState);
+ undoState = 0;
+ if (emitSignals)
+ emitUndoAvailable(false);
+ } else if (stacksToClear == QTextDocument::RedoStack
+ && redoCommandsAvailable) {
+ for (int i = undoState; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoStack.resize(undoState);
+ if (emitSignals)
+ emitRedoAvailable(false);
+ } else if (stacksToClear == QTextDocument::UndoAndRedoStacks
+ && !undoStack.isEmpty()) {
+ for (int i = 0; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoState = 0;
+ undoStack.resize(0);
+ if (emitSignals && undoCommandsAvailable)
+ emitUndoAvailable(false);
+ if (emitSignals && redoCommandsAvailable)
+ emitRedoAvailable(false);
}
- undoStack.resize(undoState);
}
void QTextDocumentPrivate::emitUndoAvailable(bool available)
@@ -1097,7 +1116,7 @@ void QTextDocumentPrivate::enableUndoRedo(bool enable)
if (!enable) {
undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
emitUndoAvailable(false);
emitRedoAvailable(false);
}
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index 4ecc2fa..ac5ed3c 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -252,10 +252,11 @@ public:
inline QFont defaultFont() const { return formats.defaultFont(); }
inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); }
+ void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false);
+
private:
bool split(int pos);
bool unite(uint f);
- void truncateUndoStack();
void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op);
int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command);
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 26c7c1e..af91603 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1331,7 +1331,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
QTextLine l(line, d);
const QScriptLine &sl = d->lines[line];
- const qreal x = position.x() + l.cursorToX(cursorPosition);
+ qreal x = position.x() + l.cursorToX(cursorPosition);
int itm = d->findItem(cursorPosition - 1);
QFixed base = sl.base();
@@ -1350,6 +1350,10 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
&& (p->transform().type() > QTransform::TxTranslate);
if (toggleAntialiasing)
p->setRenderHint(QPainter::Antialiasing);
+#if defined(QT_MAC_USE_COCOA)
+ // Always draw the cursor aligned to pixel boundary.
+ x = qRound(x);
+#endif
p->fillRect(QRectF(x, y, qreal(width), (base + descent + 1).toReal()), p->pen().brush());
if (toggleAntialiasing)
p->setRenderHint(QPainter::Antialiasing, false);
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index 2fc1940..d30c996 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -54,10 +54,13 @@
#include <zlib.h>
#if defined(Q_OS_WIN)
-#undef S_IFREG
-#define S_IFREG 0100000
+# undef S_IFREG
+# define S_IFREG 0100000
+# ifndef S_IFDIR
+# define S_IFDIR 0040000
+# endif
# ifndef S_ISDIR
-# define S_ISDIR(x) ((x) & 0040000) > 0
+# define S_ISDIR(x) ((x) & S_IFDIR) > 0
# endif
# ifndef S_ISREG
# define S_ISREG(x) ((x) & 0170000) == S_IFREG
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index 1086464..9b73373 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -49,7 +49,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QZipReader class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
class QZipReaderPrivate;
-class Q_AUTOTEST_EXPORT QZipReader
+class Q_GUI_EXPORT QZipReader
{
public:
QZipReader(const QString &fileName, QIODevice::OpenMode mode = QIODevice::ReadOnly );
@@ -73,7 +73,7 @@ public:
bool isReadable() const;
bool exists() const;
- struct Q_AUTOTEST_EXPORT FileInfo
+ struct Q_GUI_EXPORT FileInfo
{
FileInfo();
FileInfo(const FileInfo &other);
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
index 7b97937..9322f4a 100644
--- a/src/gui/text/qzipwriter_p.h
+++ b/src/gui/text/qzipwriter_p.h
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QZipWriter class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/gui/util/qsystemtrayicon_p.h b/src/gui/util/qsystemtrayicon_p.h
index b881f68..e8bf197 100644
--- a/src/gui/util/qsystemtrayicon_p.h
+++ b/src/gui/util/qsystemtrayicon_p.h
@@ -164,7 +164,9 @@ protected:
bool x11Event(XEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
+#ifndef QT_NO_WHEELEVENT
void wheelEvent(QWheelEvent *event);
+#endif
bool event(QEvent *e);
private:
diff --git a/src/gui/util/qsystemtrayicon_x11.cpp b/src/gui/util/qsystemtrayicon_x11.cpp
index a645050..82b4325 100644
--- a/src/gui/util/qsystemtrayicon_x11.cpp
+++ b/src/gui/util/qsystemtrayicon_x11.cpp
@@ -308,10 +308,12 @@ void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev)
emit q->activated(QSystemTrayIcon::DoubleClick);
}
+#ifndef QT_NO_WHEELEVENT
void QSystemTrayIconSys::wheelEvent(QWheelEvent *e)
{
QApplication::sendEvent(q, e);
}
+#endif
bool QSystemTrayIconSys::event(QEvent *e)
{
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index 87f6c83..1d496d5 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -1134,13 +1134,10 @@ void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e)
void QAbstractScrollArea::wheelEvent(QWheelEvent *e)
{
Q_D(QAbstractScrollArea);
- QScrollBar *const bars[2] = { d->hbar, d->vbar };
- int idx = (e->orientation() == Qt::Vertical) ? 1 : 0;
- int other = (idx + 1) % 2;
- if (!bars[idx]->isVisible() && bars[other]->isVisible())
- idx = other; // If the scrollbar of the event orientation is hidden, fallback to the other.
-
- QApplication::sendEvent(bars[idx], e);
+ if (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal)
+ QApplication::sendEvent(d->hbar, e);
+ else
+ QApplication::sendEvent(d->vbar, e);
}
#endif
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 2874647..4bd7b5a 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -214,8 +214,8 @@ QT_BEGIN_NAMESPACE
*/
QAbstractSliderPrivate::QAbstractSliderPrivate()
- : minimum(0), maximum(99), singleStep(1), pageStep(10),
- value(0), position(0), pressValue(-1), offset_accumulated(0), tracking(true),
+ : minimum(0), maximum(99), pageStep(10), value(0), position(0), pressValue(-1),
+ singleStep(1), offset_accumulated(0), tracking(true),
blocktracking(false), pressed(false),
invertedAppearance(false), invertedControls(false),
orientation(Qt::Horizontal), repeatAction(QAbstractSlider::SliderNoAction)
@@ -688,51 +688,66 @@ void QAbstractSlider::sliderChange(SliderChange)
update();
}
-
-/*!
- \reimp
-*/
-#ifndef QT_NO_WHEELEVENT
-void QAbstractSlider::wheelEvent(QWheelEvent * e)
+bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::KeyboardModifiers modifiers, int delta)
{
- Q_D(QAbstractSlider);
- e->ignore();
-
+ Q_Q(QAbstractSlider);
int stepsToScroll = 0;
- qreal offset = qreal(e->delta()) / 120;
+ // in Qt scrolling to the right gives negative values.
+ if (orientation == Qt::Horizontal)
+ delta = -delta;
+ qreal offset = qreal(delta) / 120;
- if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) {
+ if ((modifiers & Qt::ControlModifier) || (modifiers & Qt::ShiftModifier)) {
// Scroll one page regardless of delta:
- stepsToScroll = qBound(-d->pageStep, int(offset * d->pageStep), d->pageStep);
- d->offset_accumulated = 0;
+ stepsToScroll = qBound(-pageStep, int(offset * pageStep), pageStep);
+ offset_accumulated = 0;
} else {
// Calculate how many lines to scroll. Depending on what delta is (and
// offset), we might end up with a fraction (e.g. scroll 1.3 lines). We can
// only scroll whole lines, so we keep the reminder until next event.
- qreal stepsToScrollF = offset * QApplication::wheelScrollLines() * d->effectiveSingleStep();
+ qreal stepsToScrollF =
+#ifndef QT_NO_WHEELEVENT
+ QApplication::wheelScrollLines() *
+#endif
+ offset * effectiveSingleStep();
// Check if wheel changed direction since last event:
- if (d->offset_accumulated != 0 && (offset / d->offset_accumulated) < 0)
- d->offset_accumulated = 0;
+ if (offset_accumulated != 0 && (offset / offset_accumulated) < 0)
+ offset_accumulated = 0;
- d->offset_accumulated += stepsToScrollF;
- stepsToScroll = qBound(-d->pageStep, int(d->offset_accumulated), d->pageStep);
- d->offset_accumulated -= int(d->offset_accumulated);
+ offset_accumulated += stepsToScrollF;
+ stepsToScroll = qBound(-pageStep, int(offset_accumulated), pageStep);
+ offset_accumulated -= int(offset_accumulated);
if (stepsToScroll == 0)
- return;
+ return false;
}
- if (d->invertedControls)
+ if (invertedControls)
stepsToScroll = -stepsToScroll;
- int prevValue = d->value;
- d->position = d->overflowSafeAdd(stepsToScroll); // value will be updated by triggerAction()
- triggerAction(SliderMove);
+ int prevValue = value;
+ position = overflowSafeAdd(stepsToScroll); // value will be updated by triggerAction()
+ q->triggerAction(QAbstractSlider::SliderMove);
- if (prevValue == d->value)
- d->offset_accumulated = 0;
- else
+ if (prevValue == value) {
+ offset_accumulated = 0;
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \reimp
+*/
+#ifndef QT_NO_WHEELEVENT
+void QAbstractSlider::wheelEvent(QWheelEvent * e)
+{
+ Q_D(QAbstractSlider);
+ e->ignore();
+ int delta = e->delta();
+ if (d->scrollByDelta(e->orientation(), e->modifiers(), delta))
e->accept();
}
+
#endif
#ifdef QT_KEYPAD_NAVIGATION
/*!
diff --git a/src/gui/widgets/qabstractslider_p.h b/src/gui/widgets/qabstractslider_p.h
index 6cde468..6e6ff6e 100644
--- a/src/gui/widgets/qabstractslider_p.h
+++ b/src/gui/widgets/qabstractslider_p.h
@@ -138,6 +138,7 @@ public:
}
q->triggerAction(repeatAction);
}
+ bool scrollByDelta(Qt::Orientation orientation, Qt::KeyboardModifiers modifiers, int delta);
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qabstractspinbox.h b/src/gui/widgets/qabstractspinbox.h
index 059943a..6c062c0 100644
--- a/src/gui/widgets/qabstractspinbox.h
+++ b/src/gui/widgets/qabstractspinbox.h
@@ -137,7 +137,9 @@ protected:
void resizeEvent(QResizeEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
+#ifndef QT_NO_WHEELEVENT
void wheelEvent(QWheelEvent *event);
+#endif
void focusInEvent(QFocusEvent *event);
void focusOutEvent(QFocusEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h
index f332d31..9b19a66 100644
--- a/src/gui/widgets/qcombobox.h
+++ b/src/gui/widgets/qcombobox.h
@@ -245,7 +245,9 @@ protected:
void mouseReleaseEvent(QMouseEvent *e);
void keyPressEvent(QKeyEvent *e);
void keyReleaseEvent(QKeyEvent *e);
+#ifndef QT_NO_WHEELEVENT
void wheelEvent(QWheelEvent *e);
+#endif
void contextMenuEvent(QContextMenuEvent *e);
void inputMethodEvent(QInputMethodEvent *);
QVariant inputMethodQuery(Qt::InputMethodQuery) const;
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index 762db86..50fa9c9 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -1175,7 +1175,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
return; }
}
QAbstractSpinBox::keyPressEvent(event);
- if (select && !(event->modifiers() & Qt::ShiftModifier) && !d->edit->hasSelectedText()) {
+ if (select && !d->edit->hasSelectedText()) {
if (inserted && d->sectionAt(d->edit->cursorPosition()) == QDateTimeParser::NoSectionIndex) {
QString str = d->displayText();
int pos = d->edit->cursorPosition();
diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp
index 48d7022..6a0e363 100644
--- a/src/gui/widgets/qdialogbuttonbox.cpp
+++ b/src/gui/widgets/qdialogbuttonbox.cpp
@@ -1017,6 +1017,8 @@ void QDialogButtonBox::removeButton(QAbstractButton *button)
If the button has already been added, it is removed and added again with the
new role.
+ \note The button box takes ownership of the button.
+
\sa removeButton(), clear()
*/
void QDialogButtonBox::addButton(QAbstractButton *button, ButtonRole role)
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index d754800..13f31df 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -220,15 +220,17 @@ static quintptr tabId(const QDockAreaLayoutItem &item)
}
#endif
+static const int zero = 0;
+
QDockAreaLayoutInfo::QDockAreaLayoutInfo()
- : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
+ : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
#ifndef QT_NO_TABBAR
, tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false)
#endif
{
}
-QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
+QDockAreaLayoutInfo::QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos,
Qt::Orientation _o, int tbshape,
QMainWindow *window)
: sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
@@ -281,7 +283,7 @@ QSize QDockAreaLayoutInfo::minimumSize() const
#endif
{
if (!first)
- a += sep;
+ a += *sep;
a += pick(o, min_size);
}
b = qMax(b, perp(o, min_size));
@@ -349,7 +351,7 @@ QSize QDockAreaLayoutInfo::maximumSize() const
#endif
{
if (!first)
- a += sep;
+ a += *sep;
a += pick(o, max_size);
}
b = qMin(b, perp(o, max_size));
@@ -415,7 +417,7 @@ QSize QDockAreaLayoutInfo::sizeHint() const
{
if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
&& !previous->hasFixedSize(o)) {
- a += sep;
+ a += *sep;
}
a += gap ? item.size : pick(o, size_hint);
}
@@ -491,7 +493,7 @@ static int realMinSize(const QDockAreaLayoutInfo &info)
min = pick(info.o, item.minimumSize());
if (!first)
- result += info.sep;
+ result += *info.sep;
result += min;
first = false;
@@ -516,7 +518,7 @@ static int realMaxSize(const QDockAreaLayoutInfo &info)
max = pick(info.o, item.maximumSize());
if (!first)
- result += info.sep;
+ result += *info.sep;
result += max;
if (result >= QWIDGETSIZE_MAX)
@@ -555,7 +557,7 @@ void QDockAreaLayoutInfo::fitItems()
if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
QLayoutStruct &ls = layout_struct_list[j++];
ls.init();
- ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep;
+ ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
ls.empty = false;
}
}
@@ -938,7 +940,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
if (item.skip()) {
ls.empty = true;
} else {
- const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
ls.empty = false;
ls.pos = item.pos;
ls.size = item.size + separatorSpace;
@@ -956,7 +958,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
if (item.skip())
continue;
QLayoutStruct &ls = list[i];
- const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
item.size = ls.size - separatorSpace;
item.pos = ls.pos;
if (item.subinfo != 0) {
@@ -1041,11 +1043,11 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
int next = this->next(index);
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- item.pos += sep;
- item.size -= sep;
+ item.pos += *sep;
+ item.size -= *sep;
}
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- item.size -= sep;
+ item.size -= *sep;
QPoint pos;
rpick(o, pos) = item.pos;
@@ -1083,11 +1085,11 @@ QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
#endif
{
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- item.pos -= sep;
- item.size += sep;
+ item.pos -= *sep;
+ item.size += *sep;
}
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- item.size += sep;
+ item.size += *sep;
}
return item.widgetItem;
@@ -1255,9 +1257,9 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid
QRect r = dockedGeometry(dockWidgetItem->widget());
gap_size = pick(o, r.size());
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
- sep_size += sep;
+ sep_size += *sep;
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- sep_size += sep;
+ sep_size += *sep;
}
if (gap_size + sep_size > space)
gap_size = pick(o, gap_item.minimumSize());
@@ -1364,7 +1366,7 @@ QRect QDockAreaLayoutInfo::separatorRect(int index) const
QPoint pos = rect.topLeft();
rpick(o, pos) = item.pos + item.size;
QSize s = rect.size();
- rpick(o, s) = sep;
+ rpick(o, s) = *sep;
return QRect(pos, s);
}
@@ -1413,7 +1415,7 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
continue;
QRect sepRect = separatorRect(i);
- if (!sepRect.isNull() && sep == 1)
+ if (!sepRect.isNull() && *sep == 1)
sepRect.adjust(-2, -2, 2, 2);
//we also make sure we don't find a separator that's not there
if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
@@ -1560,7 +1562,7 @@ void QDockAreaLayoutInfo::apply(bool animate)
}
}
#ifndef QT_NO_TABBAR
- if (sep == 1)
+ if (*sep == 1)
updateSeparatorWidgets();
#endif //QT_NO_TABBAR
}
@@ -2010,7 +2012,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
updateTabBar();
setCurrentTabId(tabId(item_list.at(index)));
}
- if (!testing && sep == 1)
+ if (!testing && *sep == 1)
updateSeparatorWidgets();
#endif
@@ -2273,13 +2275,13 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true)
const int tabShape = 0;
#endif
docks[QInternal::LeftDock]
- = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
docks[QInternal::RightDock]
- = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
docks[QInternal::TopDock]
- = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
docks[QInternal::BottomDock]
- = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
centralWidgetItem = 0;
@@ -3028,7 +3030,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do
#else
int tbshape = 0;
#endif
- QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow);
+ QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
new_info.item_list.append(new QDockAreaLayoutInfo(info));
new_info.item_list.append(dockWidgetItem);
info = new_info;
@@ -3324,6 +3326,12 @@ void QDockAreaLayout::keepSize(QDockWidget *w)
item.flags |= QDockAreaLayoutItem::KeepSize;
}
+void QDockAreaLayout::styleChangedEvent()
+{
+ sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainWindow);
+ fitLayout();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DOCKWIDGET
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 0bc1aa9..0088f00 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -128,7 +128,7 @@ class Q_AUTOTEST_EXPORT QDockAreaLayoutInfo
{
public:
QDockAreaLayoutInfo();
- QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
+ QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
int tbhape, QMainWindow *window);
QSize minimumSize() const;
@@ -189,7 +189,7 @@ public:
QMainWindowLayout *mainWindowLayout() const;
- int sep;
+ const int *sep;
mutable QVector<QWidget*> separatorWidgets;
QInternal::DockPosition dockPos;
Qt::Orientation o;
@@ -300,6 +300,7 @@ public:
QSet<QTabBar*> usedTabBars() const;
QSet<QWidget*> usedSeparatorWidgets() const;
#endif //QT_NO_TABBAR
+ void styleChangedEvent();
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index c779312..b81f04f 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -951,8 +951,8 @@ void QLabel::contextMenuEvent(QContextMenuEvent *ev)
return;
}
ev->accept();
- menu->exec(ev->globalPos());
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(ev->globalPos());
#endif
}
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index b0a64ea..db099e8 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -1371,6 +1371,8 @@ bool QLineControl::processEvent(QEvent* ev)
processInputMethodEvent(static_cast<QInputMethodEvent*>(ev)); break;
#ifndef QT_NO_SHORTCUT
case QEvent::ShortcutOverride:{
+ if (isReadOnly())
+ return false;
QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
if (ke == QKeySequence::Copy
|| ke == QKeySequence::Paste
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index 2d2df92..141f844 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -2046,9 +2046,9 @@ void QLineEdit::dropEvent(QDropEvent* e)
*/
void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
{
- QPointer<QMenu> menu = createStandardContextMenu();
- menu->exec(event->globalPos());
- delete menu;
+ QMenu *menu = createStandardContextMenu();
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(event->globalPos());
}
#if defined(Q_WS_WIN)
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index 269cd12..a63f3bf 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -1393,6 +1393,7 @@ bool QMainWindow::event(QEvent *event)
#endif // QT_NO_STATUSTIP
case QEvent::StyleChange:
+ d->layout->layoutState.dockAreaLayout.styleChangedEvent();
if (!d->explicitIconSize)
setIconSize(QSize());
break;
@@ -1554,11 +1555,15 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
#ifndef QT_NO_MENU
QMenu *popup = createPopupMenu();
- if (popup && !popup->isEmpty()) {
- popup->exec(event->globalPos());
- event->accept();
+ if (popup) {
+ if (!popup->isEmpty()) {
+ popup->setAttribute(Qt::WA_DeleteOnClose);
+ popup->popup(event->globalPos());
+ event->accept();
+ } else {
+ delete popup;
+ }
}
- delete popup;
#endif
}
#endif // QT_NO_CONTEXTMENU
diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp
index d1e7285..fc75c92 100644
--- a/src/gui/widgets/qmainwindowlayout.cpp
+++ b/src/gui/widgets/qmainwindowlayout.cpp
@@ -1627,6 +1627,13 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
tb->d_func()->plug(currentGapRect);
#endif
+ savedState.clear();
+ currentGapPos.clear();
+ pluggingWidget = 0;
+ //applying the state will make sure that the currentGap is updated correctly
+ //and all the geometries (especially the one from the central widget) is correct
+ layoutState.apply(false);
+
#ifndef QT_NO_DOCKWIDGET
#ifndef QT_NO_TABBAR
if (qobject_cast<QDockWidget*>(widget) != 0) {
@@ -1637,13 +1644,6 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
}
#endif
#endif
-
- savedState.clear();
- currentGapPos.clear();
- pluggingWidget = 0;
- //applying the state will make sure that the currentGap is updated correctly
- //and all the geometries (especially the one from the central widget) is correct
- layoutState.apply(false);
}
if (!widgetAnimator.animating()) {
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 8ce7cc0..08960da 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -2302,9 +2302,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e)
QAction *action = d->actionAt(e->pos());
if (action && action == d->currentAction) {
- if (action->menu())
- action->menu()->d_func()->setFirstActionActive();
- else {
+ if (!action->menu()){
#if defined(Q_WS_WIN)
//On Windows only context menus can be activated with the right button
if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h
index 28bd859..a040afa 100644
--- a/src/gui/widgets/qmenu.h
+++ b/src/gui/widgets/qmenu.h
@@ -162,7 +162,9 @@ protected:
void mouseReleaseEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
+#ifndef QT_NO_WHEELEVENT
void wheelEvent(QWheelEvent *);
+#endif
void enterEvent(QEvent *);
void leaveEvent(QEvent *);
void hideEvent(QHideEvent *);
diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp
index 73ce122..4eff260 100644
--- a/src/gui/widgets/qscrollbar.cpp
+++ b/src/gui/widgets/qscrollbar.cpp
@@ -521,6 +521,24 @@ bool QScrollBar::event(QEvent *event)
if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
d_func()->updateHoverControl(he->pos());
break;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel: {
+ // override wheel event without adding virtual function override
+ QWheelEvent *ev = static_cast<QWheelEvent *>(event);
+ int delta = ev->delta();
+ // scrollbar is a special case - in vertical mode it reaches minimum
+ // value in the upper position, however QSlider's minimum value is on
+ // the bottom. So we need to invert a value, but since the scrollbar is
+ // inverted by default, we need to inverse the delta value for the
+ // horizontal orientation.
+ if (ev->orientation() == Qt::Horizontal)
+ delta = -delta;
+ Q_D(QScrollBar);
+ if (d->scrollByDelta(ev->orientation(), ev->modifiers(), delta))
+ event->accept();
+ return true;
+ }
+#endif
default:
break;
}
diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp
index 7782448..7ed27ea 100644
--- a/src/gui/widgets/qtoolbar.cpp
+++ b/src/gui/widgets/qtoolbar.cpp
@@ -441,8 +441,7 @@ void QToolBarPrivate::plug(const QRect &r)
When a QToolBar is not a child of a QMainWindow, it looses the ability
to populate the extension pop up with widgets added to the toolbar using
addWidget(). Please use widget actions created by inheriting QWidgetAction
- and implementing QWidgetAction::createWidget() instead. This is a known
- issue which will be fixed in a future release.
+ and implementing QWidgetAction::createWidget() instead.
\sa QToolButton, QMenu, QAction, {Application Example}
*/
diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h
index e996a01..63734ca 100644
--- a/src/gui/widgets/qvalidator.h
+++ b/src/gui/widgets/qvalidator.h
@@ -137,10 +137,11 @@ class Q_GUI_EXPORT QDoubleValidator : public QValidator
Q_PROPERTY(double bottom READ bottom WRITE setBottom)
Q_PROPERTY(double top READ top WRITE setTop)
Q_PROPERTY(int decimals READ decimals WRITE setDecimals)
+ Q_ENUMS(Notation)
Q_PROPERTY(Notation notation READ notation WRITE setNotation)
public:
- explicit QDoubleValidator(QObject * parent);
+ explicit QDoubleValidator(QObject * parent = 0);
QDoubleValidator(double bottom, double top, int decimals, QObject * parent);
~QDoubleValidator();
@@ -184,7 +185,7 @@ class Q_GUI_EXPORT QRegExpValidator : public QValidator
Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp)
public:
- explicit QRegExpValidator(QObject *parent);
+ explicit QRegExpValidator(QObject *parent = 0);
QRegExpValidator(const QRegExp& rx, QObject *parent);
~QRegExpValidator();
diff --git a/src/multimedia/audio/qaudiodeviceinfo.cpp b/src/multimedia/audio/qaudiodeviceinfo.cpp
index 19b4669..ff04b4e 100644
--- a/src/multimedia/audio/qaudiodeviceinfo.cpp
+++ b/src/multimedia/audio/qaudiodeviceinfo.cpp
@@ -260,6 +260,8 @@ QStringList QAudioDeviceInfo::supportedCodecs() const
/*!
Returns a list of supported sample rates.
+
+ \since 4.7
*/
QList<int> QAudioDeviceInfo::supportedSampleRates() const
@@ -280,6 +282,8 @@ QList<int> QAudioDeviceInfo::supportedFrequencies() const
/*!
Returns a list of supported channel counts.
+
+ \since 4.7
*/
QList<int> QAudioDeviceInfo::supportedChannelCounts() const
diff --git a/src/multimedia/audio/qaudioformat.cpp b/src/multimedia/audio/qaudioformat.cpp
index e349b9e..86d72f6 100644
--- a/src/multimedia/audio/qaudioformat.cpp
+++ b/src/multimedia/audio/qaudioformat.cpp
@@ -225,6 +225,8 @@ bool QAudioFormat::isValid() const
/*!
Sets the sample rate to \a samplerate Hertz.
+
+ \since 4.7
*/
void QAudioFormat::setSampleRate(int samplerate)
@@ -245,6 +247,8 @@ void QAudioFormat::setFrequency(int frequency)
/*!
Returns the current sample rate in Hertz.
+
+ \since 4.7
*/
int QAudioFormat::sampleRate() const
@@ -265,6 +269,8 @@ int QAudioFormat::frequency() const
/*!
Sets the channel count to \a channels.
+
+ \since 4.7
*/
void QAudioFormat::setChannelCount(int channels)
@@ -285,6 +291,8 @@ void QAudioFormat::setChannels(int channels)
/*!
Returns the current channel count value.
+
+ \since 4.7
*/
int QAudioFormat::channelCount() const
diff --git a/src/multimedia/video/qabstractvideobuffer.cpp b/src/multimedia/video/qabstractvideobuffer.cpp
index 22b36f2..465a1e7 100644
--- a/src/multimedia/video/qabstractvideobuffer.cpp
+++ b/src/multimedia/video/qabstractvideobuffer.cpp
@@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE
/*!
\class QAbstractVideoBuffer
\brief The QAbstractVideoBuffer class is an abstraction for video data.
- \preliminary
\since 4.6
The QVideoFrame class makes use of a QAbstractVideoBuffer internally to reference a buffer of
diff --git a/src/multimedia/video/qabstractvideosurface.cpp b/src/multimedia/video/qabstractvideosurface.cpp
index 3f6bc08..3dabb6b 100644
--- a/src/multimedia/video/qabstractvideosurface.cpp
+++ b/src/multimedia/video/qabstractvideosurface.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\class QAbstractVideoSurface
\brief The QAbstractVideoSurface class is a base class for video presentation surfaces.
- \preliminary
\since 4.6
The QAbstractVideoSurface class defines the standard interface that video producers use to
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp
index f10ce97..2d66d9e 100644
--- a/src/multimedia/video/qvideoframe.cpp
+++ b/src/multimedia/video/qvideoframe.cpp
@@ -102,7 +102,6 @@ private:
/*!
\class QVideoFrame
\brief The QVideoFrame class provides a representation of a frame of video data.
- \preliminary
\since 4.6
A QVideoFrame encapsulates the data of a video frame, and information about the frame.
diff --git a/src/multimedia/video/qvideosurfaceformat.cpp b/src/multimedia/video/qvideosurfaceformat.cpp
index 6b16e6a..1fc13a6 100644
--- a/src/multimedia/video/qvideosurfaceformat.cpp
+++ b/src/multimedia/video/qvideosurfaceformat.cpp
@@ -136,7 +136,6 @@ public:
\class QVideoSurfaceFormat
\brief The QVideoSurfaceFormat class specifies the stream format of a video presentation
surface.
- \preliminary
\since 4.6
A video surface presents a stream of video frames. The surface's format describes the type of
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 70a301d..b0e632a 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -286,7 +286,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
if (!socket->bytesAvailable()) {
if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
- this->state = QHttpNetworkConnectionChannel::IdleState;
allDone();
} else {
// try to reconnect/resend before sending an error.
@@ -305,9 +304,12 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
while (socket->bytesAvailable()) {
QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState;
switch (state) {
- case QHttpNetworkReplyPrivate::NothingDoneState:
- case QHttpNetworkReplyPrivate::ReadingStatusState: {
+ case QHttpNetworkReplyPrivate::NothingDoneState: {
+ // only eat whitespace on the first call
eatWhitespace();
+ state = reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState;
+ }
+ case QHttpNetworkReplyPrivate::ReadingStatusState: {
qint64 statusBytes = reply->d_func()->readStatus(socket);
if (statusBytes == -1 && reconnectAttempts <= 0) {
// too many errors reading/receiving/parsing the status, close the socket and emit error
@@ -344,7 +346,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
emit reply->headerChanged();
if (!replyPrivate->expectContent()) {
replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState;
- this->state = QHttpNetworkConnectionChannel::IdleState;
allDone();
return;
}
@@ -421,7 +422,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
// everything done, fall through
}
case QHttpNetworkReplyPrivate::AllDoneState:
- this->state = QHttpNetworkConnectionChannel::IdleState;
allDone();
break;
default:
@@ -567,6 +567,9 @@ void QHttpNetworkConnectionChannel::allDone()
// in case of failures, each channel will attempt two reconnects before emitting error.
reconnectAttempts = 2;
+ // now the channel can be seen as free/idle again, all signal emissions for the reply have been done
+ this->state = QHttpNetworkConnectionChannel::IdleState;
+
detectPipeliningSupport();
// move next from pipeline to current request
@@ -607,19 +610,19 @@ void QHttpNetworkConnectionChannel::allDone()
void QHttpNetworkConnectionChannel::detectPipeliningSupport()
{
// detect HTTP Pipelining support
- QByteArray serverHeaderField = reply->headerField("Server");
+ QByteArray serverHeaderField;
if (
- // check for broken servers in server reply header
- // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining
- (!serverHeaderField.contains("Microsoft-IIS/4."))
- && (!serverHeaderField.contains("Microsoft-IIS/5."))
- && (!serverHeaderField.contains("Netscape-Enterprise/3."))
// check for HTTP/1.1
- && (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1)
+ (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1)
// check for not having connection close
&& (!reply->d_func()->isConnectionCloseEnabled())
// check if it is still connected
&& (socket->state() == QAbstractSocket::ConnectedState)
+ // check for broken servers in server reply header
+ // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining
+ && (serverHeaderField = reply->headerField("Server"), !serverHeaderField.contains("Microsoft-IIS/4."))
+ && (!serverHeaderField.contains("Microsoft-IIS/5."))
+ && (!serverHeaderField.contains("Netscape-Enterprise/3."))
) {
pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningProbablySupported;
} else {
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index a5223d1..512c045 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -423,13 +423,26 @@ int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteA
qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
{
+ if (fragment.isEmpty()) {
+ // reserve bytes for the status line. This is better than always append() which reallocs the byte array
+ fragment.reserve(32);
+ }
+
qint64 bytes = 0;
char c;
+ qint64 haveRead = 0;
+
+ do {
+ haveRead = socket->read(&c, 1);
+ if (haveRead == -1)
+ return -1; // unexpected EOF
+ else if (haveRead == 0)
+ break; // read more later
+
+ bytes++;
- while (socket->bytesAvailable()) {
// allow both CRLF & LF (only) line endings
- if (socket->peek(&c, 1) == 1 && c == '\n') {
- bytes += socket->read(&c, 1); // read the "n"
+ if (c == '\n') {
// remove the CR at the end
if (fragment.endsWith('\r')) {
fragment.truncate(fragment.length()-1);
@@ -442,11 +455,6 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
}
break;
} else {
- c = 0;
- int haveRead = socket->read(&c, 1);
- if (haveRead == -1)
- return -1;
- bytes += haveRead;
fragment.append(c);
}
@@ -456,8 +464,7 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
fragment.clear();
return -1;
}
-
- }
+ } while (haveRead == 1);
return bytes;
}
@@ -500,20 +507,41 @@ bool QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status)
qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket)
{
+ if (fragment.isEmpty()) {
+ // according to http://dev.opera.com/articles/view/mama-http-headers/ the average size of the header
+ // block is 381 bytes.
+ // reserve bytes. This is better than always append() which reallocs the byte array.
+ fragment.reserve(512);
+ }
+
qint64 bytes = 0;
char c = 0;
bool allHeaders = false;
- while (!allHeaders && socket->bytesAvailable()) {
- if (socket->peek(&c, 1) == 1 && c == '\n') {
- // check for possible header endings. As per HTTP rfc,
- // the header endings will be marked by CRLFCRLF. But
- // we will allow CRLFLF, LFLF & CRLFCRLF
- if (fragment.endsWith("\n\r") || fragment.endsWith('\n'))
- allHeaders = true;
+ qint64 haveRead = 0;
+ do {
+ haveRead = socket->read(&c, 1);
+ if (haveRead == 0) {
+ // read more later
+ break;
+ } else if (haveRead == -1) {
+ // connection broke down
+ return -1;
+ } else {
+ fragment.append(c);
+ bytes++;
+
+ if (c == '\n') {
+ // check for possible header endings. As per HTTP rfc,
+ // the header endings will be marked by CRLFCRLF. But
+ // we will allow CRLFCRLF, CRLFLF, LFLF
+ if (fragment.endsWith("\r\n\r\n")
+ || fragment.endsWith("\r\n\n")
+ || fragment.endsWith("\n\n"))
+ allHeaders = true;
+ }
}
- bytes += socket->read(&c, 1);
- fragment.append(c);
- }
+ } while (!allHeaders && haveRead > 0);
+
// we received all headers now parse them
if (allHeaders) {
parseHeader(fragment);
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index e16aedc..0b32533 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -549,7 +549,7 @@ void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
/*!
Posts a request to obtain the network headers for \a request
- and returns a new QNetworkReply object which will contain such headers
+ and returns a new QNetworkReply object which will contain such headers.
The function is named after the HTTP request associated (HEAD).
*/
diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h
index f34396f..3cc4cee 100644
--- a/src/network/access/qnetworkcookie.h
+++ b/src/network/access/qnetworkcookie.h
@@ -114,7 +114,7 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug, const QNetworkCookie &);
QT_END_NAMESPACE
// ### Qt5 remove this include
-#include "qnetworkcookiejar.h"
+#include <QtNetwork/QNetworkCookieJar>
Q_DECLARE_METATYPE(QNetworkCookie)
Q_DECLARE_METATYPE(QList<QNetworkCookie>)
diff --git a/src/network/access/qnetworkcookiejar.h b/src/network/access/qnetworkcookiejar.h
index 813bf3e..8086f38 100644
--- a/src/network/access/qnetworkcookiejar.h
+++ b/src/network/access/qnetworkcookiejar.h
@@ -46,7 +46,7 @@
#include <QtCore/QUrl>
// ### Qt5 remove this include
-#include "qnetworkcookie.h"
+#include <QtNetwork/QNetworkCookie>
QT_BEGIN_HEADER
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 24560d1..d2fb925 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -559,6 +559,12 @@ void QGL2PaintEngineExPrivate::resetGLState()
glStencilMask(0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, 0xff);
+ glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_OPACITY_ATTR);
+#ifndef QT_OPENGL_ES_2
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // color may have been changed by glVertexAttrib()
+#endif
}
void QGL2PaintEngineEx::endNativePainting()
@@ -1326,14 +1332,14 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat)
: d->glyphCacheType;
- if (txtype > QTransform::TxTranslate)
- glyphType = QFontEngineGlyphCache::Raster_A8;
- if (glyphType == QFontEngineGlyphCache::Raster_RGBMask
- && state()->composition_mode != QPainter::CompositionMode_Source
- && state()->composition_mode != QPainter::CompositionMode_SourceOver)
- {
- drawCached = false;
+ if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) {
+ if (d->deviceHasAlpha || txtype > QTransform::TxTranslate
+ || (state()->composition_mode != QPainter::CompositionMode_Source
+ && state()->composition_mode != QPainter::CompositionMode_SourceOver))
+ {
+ glyphType = QFontEngineGlyphCache::Raster_A8;
+ }
}
if (drawCached) {
@@ -1624,6 +1630,23 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
d->stencilClean = true;
+ switch (pdev->devType()) {
+ case QInternal::Pixmap:
+ d->deviceHasAlpha = static_cast<QPixmap *>(pdev)->hasAlphaChannel();
+ break;
+ case QInternal::FramebufferObject:
+ {
+ GLenum f = static_cast<QGLFramebufferObject *>(pdev)->format().internalTextureFormat();
+ d->deviceHasAlpha = (f != GL_RGB && f != GL_RGB5 && f != GL_RGB8);
+ }
+ break;
+ default:
+ // widget, pbuffer
+ d->deviceHasAlpha = d->ctx->d_func()->reqFormat.alpha();
+ break;
+ }
+
+
// Calling begin paint should make the correct context current. So, any
// code which calls into GL or otherwise needs a current context *must*
// go after beginPaint:
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 35c88f4..e816e17 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -278,6 +278,7 @@ public:
bool needsSync;
bool multisamplingAlwaysEnabled;
+ bool deviceHasAlpha;
GLfloat depthRange[2];
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index e9ca4c4..cfcbbf8 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -99,6 +99,10 @@ QT_BEGIN_NAMESPACE
QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
#endif
+#ifdef Q_WS_X11
+extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
+#endif
+
struct QGLThreadContext {
QGLContext *context;
};
@@ -1688,10 +1692,8 @@ QGLTextureCache::QGLTextureCache()
Q_ASSERT(qt_gl_texture_cache == 0);
qt_gl_texture_cache = this;
- QImagePixmapCleanupHooks::instance()->addPixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
+ QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTextures);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
}
@@ -1699,10 +1701,8 @@ QGLTextureCache::~QGLTextureCache()
{
qt_gl_texture_cache = 0;
- QImagePixmapCleanupHooks::instance()->removePixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->removePixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
+ QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTextures);
+ QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
}
@@ -1770,30 +1770,29 @@ void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
}
-void QGLTextureCache::cleanupTextures(QPixmap* pixmap)
+void QGLTextureCache::cleanupTextures(QPixmapData* pmd)
{
// ### remove when the GL texture cache becomes thread-safe
if (qApp->thread() == QThread::currentThread()) {
- const qint64 cacheKey = pixmap->cacheKey();
+ const qint64 cacheKey = pmd->cacheKey();
QGLTexture *texture = instance()->getTexture(cacheKey);
if (texture && texture->options & QGLContext::MemoryManagedBindOption)
instance()->remove(cacheKey);
}
}
-#if defined(Q_WS_X11)
-void QGLTextureCache::cleanupPixmapSurfaces(QPixmap* pixmap)
+void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd)
{
// Remove any bound textures first:
- cleanupTextures(pixmap);
+ cleanupTextures(pmd);
- QPixmapData *pd = pixmap->data_ptr().data();
- if (pd->classId() == QPixmapData::X11Class) {
- Q_ASSERT(pd->ref == 1); // Make sure reference counting isn't broken
- QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
+#if defined(Q_WS_X11)
+ if (pmd->classId() == QPixmapData::X11Class) {
+ Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken
+ QGLContextPrivate::destroyGlSurfaceForPixmap(pmd);
}
-}
#endif
+}
void QGLTextureCache::deleteIfEmpty()
{
@@ -2453,7 +2452,10 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
#if defined(Q_WS_X11)
// Try to use texture_from_pixmap
- if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType) {
+ const QX11Info *xinfo = qt_x11Info(paintDevice);
+ if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
+ && xinfo && xinfo->screen() == pixmap.x11Info().screen())
+ {
texture = bindTextureFromNativePixmap(pd, key, options);
if (texture) {
texture->options |= QGLContext::MemoryManagedBindOption;
diff --git a/src/opengl/qgl_mac.mm b/src/opengl/qgl_mac.mm
index c01575b..4d7532e 100644
--- a/src/opengl/qgl_mac.mm
+++ b/src/opengl/qgl_mac.mm
@@ -951,8 +951,6 @@ void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
break;
current = current->parentWidget();
}
-
- isGLWidget = 1;
}
bool QGLWidgetPrivate::renderCxPm(QPixmap*)
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index d17db3a..efd2090 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -173,7 +173,9 @@ public:
#if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
, eglSurfaceWindowId(0)
#endif
- {}
+ {
+ isGLWidget = 1;
+ }
~QGLWidgetPrivate() {}
@@ -520,7 +522,7 @@ public:
QSize bindCompressedTexturePVR(const char *buf, int len);
};
-class QGLTextureCache {
+class Q_AUTOTEST_EXPORT QGLTextureCache {
public:
QGLTextureCache();
~QGLTextureCache();
@@ -537,11 +539,8 @@ public:
static QGLTextureCache *instance();
static void deleteIfEmpty();
static void imageCleanupHook(qint64 cacheKey);
- static void cleanupTextures(QPixmap* pixmap);
-#ifdef Q_WS_X11
- // X11 needs to catch pixmap data destruction to delete EGL/GLX pixmap surfaces
- static void cleanupPixmapSurfaces(QPixmap* pixmap);
-#endif
+ static void cleanupTextures(QPixmapData* pixmap);
+ static void cleanupBeforePixmapDestruction(QPixmapData* pixmap);
private:
QCache<qint64, QGLTexture> m_cache;
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 03fca39..02d5501 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -224,6 +224,12 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx)
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
+ // Geometry shaders are optional...
+ glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT"));
+ glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT"));
+ glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT"));
+ glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT"));
+
#if defined(QT_OPENGL_ES_2)
// The GLSL shader functions are always present in OpenGL/ES 2.0.
// The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index 116dfa6..4edd5f7 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -197,6 +197,15 @@ typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1,
typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height);
+// GL_EXT_geometry_shader4
+typedef void (APIENTRY *_glProgramParameteriEXT)(GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRY *_glFramebufferTextureEXT)(GLenum target, GLenum attachment,
+ GLuint texture, GLint level);
+typedef void (APIENTRY *_glFramebufferTextureLayerEXT)(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLenum face);
+
// ARB_texture_compression
typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
GLsizei, GLint, GLsizei, const GLvoid *);
@@ -310,6 +319,10 @@ struct QGLExtensionFuncs
qt_glMapBufferARB = 0;
qt_glUnmapBufferARB = 0;
+ qt_glProgramParameteriEXT = 0;
+ qt_glFramebufferTextureEXT = 0;
+ qt_glFramebufferTextureLayerEXT = 0;
+ qt_glFramebufferTextureFaceEXT = 0;
#if !defined(QT_OPENGL_ES)
// Texture compression
qt_glCompressedTexImage2DARB = 0;
@@ -425,6 +438,11 @@ struct QGLExtensionFuncs
_glMapBufferARB qt_glMapBufferARB;
_glUnmapBufferARB qt_glUnmapBufferARB;
+ // Geometry shaders...
+ _glProgramParameteriEXT qt_glProgramParameteriEXT;
+ _glFramebufferTextureEXT qt_glFramebufferTextureEXT;
+ _glFramebufferTextureLayerEXT qt_glFramebufferTextureLayerEXT;
+ _glFramebufferTextureFaceEXT qt_glFramebufferTextureFaceEXT;
#if !defined(QT_OPENGL_ES)
// Texture compression
_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
@@ -447,11 +465,11 @@ struct QGLExtensionFuncs
#endif
#ifndef GL_RGB16
-#define GL_RGB16 32852
+#define GL_RGB16 0x8054
#endif
#ifndef GL_UNSIGNED_SHORT_5_6_5
-#define GL_UNSIGNED_SHORT_5_6_5 33635
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#endif
#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
@@ -661,6 +679,29 @@ struct QGLExtensionFuncs
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
#endif
+// Geometry shader defines
+#ifndef GL_GEOMETRY_SHADER_EXT
+# define GL_GEOMETRY_SHADER_EXT 0x8DD9
+# define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+# define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+# define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+# define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+# define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+# define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+# define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+# define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+# define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+# define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+# define GL_LINES_ADJACENCY_EXT 0xA
+# define GL_LINE_STRIP_ADJACENCY_EXT 0xB
+# define GL_TRIANGLES_ADJACENCY_EXT 0xC
+# define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
+# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+# define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+# define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+# define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+#endif
#if !defined(QT_OPENGL_ES_2)
#define glProgramStringARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramStringARB
@@ -781,6 +822,11 @@ struct QGLExtensionFuncs
#define glClearDepth glClearDepthf
#endif
+#define glProgramParameteriEXT QGLContextPrivate::extensionFuncs(ctx).qt_glProgramParameteriEXT
+#define glFramebufferTextureEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureEXT
+#define glFramebufferTextureLayerEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureLayerEXT
+#define glFramebufferTextureFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureFaceEXT
+
#if !defined(QT_OPENGL_ES)
#define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
#endif
diff --git a/src/opengl/qglpixelbuffer_x11.cpp b/src/opengl/qglpixelbuffer_x11.cpp
index 5b34cbb..32a42a2 100644
--- a/src/opengl/qglpixelbuffer_x11.cpp
+++ b/src/opengl/qglpixelbuffer_x11.cpp
@@ -181,7 +181,11 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
qt_format_to_attrib_list(f, attribs);
- GLXFBConfig *configs = glXChooseFBConfig(X11->display, X11->defaultScreen, attribs, &num_configs);
+ int screen = X11->defaultScreen;
+ if (shareWidget)
+ screen = shareWidget->x11Info().screen();
+
+ GLXFBConfig *configs = glXChooseFBConfig(X11->display, screen, attribs, &num_configs);
if (configs && num_configs) {
int res;
glXGetFBConfigAttrib(X11->display, configs[0], GLX_LEVEL, &res);
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index 11011ee..d5a11d9 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -319,14 +319,14 @@ public:
~QGLBlurTextureCache();
QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap);
- bool hasBlurTextureInfo(const QPixmap &pixmap) const;
+ bool hasBlurTextureInfo(quint64 cacheKey) const;
void insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info);
- void clearBlurTextureInfo(const QPixmap &pixmap);
+ void clearBlurTextureInfo(quint64 cacheKey);
void timerEvent(QTimerEvent *event);
private:
- static void pixmapDestroyed(QPixmap *pixmap);
+ static void pixmapDestroyed(QPixmapData *pixmap);
QCache<quint64, QGLBlurTextureInfo > cache;
@@ -379,21 +379,22 @@ QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixm
return cache.take(pixmap.cacheKey());
}
-void QGLBlurTextureCache::clearBlurTextureInfo(const QPixmap &pixmap)
+void QGLBlurTextureCache::clearBlurTextureInfo(quint64 cacheKey)
{
- cache.remove(pixmap.cacheKey());
+ cache.remove(cacheKey);
}
-bool QGLBlurTextureCache::hasBlurTextureInfo(const QPixmap &pixmap) const
+bool QGLBlurTextureCache::hasBlurTextureInfo(quint64 cacheKey) const
{
- return cache.contains(pixmap.cacheKey());
+ return cache.contains(cacheKey);
}
void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info)
{
static bool hookAdded = false;
if (!hookAdded) {
- QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(pixmapDestroyed);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(pixmapDestroyed);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(pixmapDestroyed);
hookAdded = true;
}
@@ -406,11 +407,11 @@ void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTe
timerId = startTimer(8000);
}
-void QGLBlurTextureCache::pixmapDestroyed(QPixmap *pixmap)
+void QGLBlurTextureCache::pixmapDestroyed(QPixmapData *pmd)
{
foreach (QGLBlurTextureCache *cache, blurTextureCaches) {
- if (cache->hasBlurTextureInfo(*pixmap))
- cache->clearBlurTextureInfo(*pixmap);
+ if (cache->hasBlurTextureInfo(pmd->cacheKey()))
+ cache->clearBlurTextureInfo(pmd->cacheKey());
}
}
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 80b4872..a0b332d 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -143,6 +143,8 @@ QT_BEGIN_NAMESPACE
\value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
\value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
+ \value Geometry Geometry shaders written in the OpenGL Shading
+ Language (GLSL), based on the GL_EXT_geometry_shader4 extension.
*/
#ifndef GL_FRAGMENT_SHADER
@@ -226,6 +228,8 @@ bool QGLShaderPrivate::create()
GLuint shader;
if (shaderType == QGLShader::Vertex)
shader = glCreateShader(GL_VERTEX_SHADER);
+ else if (shaderType == QGLShader::Geometry)
+ shader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
else
shader = glCreateShader(GL_FRAGMENT_SHADER);
if (!shader) {
@@ -509,6 +513,10 @@ GLuint QGLShader::shaderId() const
return d->shaderGuard.id();
}
+
+
+
+
#undef ctx
#define ctx programGuard.context()
@@ -521,8 +529,9 @@ public:
, linked(false)
, inited(false)
, removingShaders(false)
- , vertexShader(0)
- , fragmentShader(0)
+ , geometryVertexCount(64)
+ , geometryInputType(0)
+ , geometryOutputType(0)
{
}
~QGLShaderProgramPrivate();
@@ -531,11 +540,14 @@ public:
bool linked;
bool inited;
bool removingShaders;
+
+ int geometryVertexCount;
+ GLenum geometryInputType;
+ GLenum geometryOutputType;
+
QString log;
QList<QGLShader *> shaders;
QList<QGLShader *> anonShaders;
- QGLShader *vertexShader;
- QGLShader *fragmentShader;
bool hasShader(QGLShader::ShaderType type) const;
};
@@ -604,6 +616,7 @@ bool QGLShaderProgram::init()
context = QGLContext::currentContext();
d->programGuard.setContext(context);
}
+
if (!context)
return false;
if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) {
@@ -831,6 +844,7 @@ bool QGLShaderProgram::link()
GLuint program = d->programGuard.id();
if (!program)
return false;
+
GLint value;
if (d->shaders.isEmpty()) {
// If there are no explicit shaders, then it is possible that the
@@ -843,6 +857,22 @@ bool QGLShaderProgram::link()
if (d->linked)
return true;
}
+
+ // Set up the geometry shader parameters
+ if (glProgramParameteriEXT) {
+ foreach (QGLShader *shader, d->shaders) {
+ if (shader->shaderType() & QGLShader::Geometry) {
+ glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT,
+ d->geometryInputType);
+ glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT,
+ d->geometryOutputType);
+ glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT,
+ d->geometryVertexCount);
+ break;
+ }
+ }
+ }
+
glLinkProgram(program);
value = 0;
glGetProgramiv(program, GL_LINK_STATUS, &value);
@@ -1555,8 +1585,8 @@ void QGLShaderProgram::setAttributeArray
indicates the number of components per vertex: 1, 2, 3, or 4.
The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
+ on the \a name. Otherwise the value specified with
+ setAttributeValue() for \a name will be used.
The setAttributeBuffer() function can be used to set the attribute
array to an offset within a vertex buffer.
@@ -1572,15 +1602,16 @@ void QGLShaderProgram::setAttributeArray
}
/*!
- Sets an array of vertex values on the attribute at \a location
- in this shader program, starting at a specific \a offset in the
+ Sets an array of vertex values on the attribute at \a location in
+ this shader program, starting at a specific \a offset in the
currently bound vertex buffer. The \a stride indicates the number
of bytes between vertices. A default \a stride value of zero
- indicates that the vertices are densely packed in \a values.
+ indicates that the vertices are densely packed in the value array.
- The \a type indicates the type of elements in the \a values array,
- usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize
- indicates the number of components per vertex: 1, 2, 3, or 4.
+ The \a type indicates the type of elements in the vertex value
+ array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a
+ tupleSize indicates the number of components per vertex: 1, 2, 3,
+ or 4.
The array will become active when enableAttributeArray() is called
on the \a location. Otherwise the value specified with
@@ -1607,15 +1638,16 @@ void QGLShaderProgram::setAttributeBuffer
in this shader program, starting at a specific \a offset in the
currently bound vertex buffer. The \a stride indicates the number
of bytes between vertices. A default \a stride value of zero
- indicates that the vertices are densely packed in \a values.
+ indicates that the vertices are densely packed in the value array.
- The \a type indicates the type of elements in the \a values array,
- usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize
- indicates the number of components per vertex: 1, 2, 3, or 4.
+ The \a type indicates the type of elements in the vertex value
+ array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a
+ tupleSize indicates the number of components per vertex: 1, 2, 3,
+ or 4.
The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
+ on the \a name. Otherwise the value specified with
+ setAttributeValue() for \a name will be used.
\sa setAttributeArray()
\since 4.7
@@ -3045,6 +3077,109 @@ void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *
#undef ctx
/*!
+ Returns the hardware limit for how many vertices a geometry shader
+ can output.
+
+ \since 4.7
+
+ \sa setGeometryShaderOutputVertexCount
+*/
+int QGLShaderProgram::maxGeometryOutputVertices() const
+{
+ int n;
+ glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
+ return n;
+}
+
+
+
+/*!
+ Sets the maximum number of vertices the current geometry shader
+ program will produce, if active.
+
+ \since 4.7
+
+ This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryOutputVertexCount(int count)
+{
+#ifndef QT_NO_DEBUG
+ int max = maxGeometryOutputVertices();
+ if (count > max) {
+ qWarning("QGLShaderProgram::setGeometryOutputVertexCount: count: %d higher than maximum: %d",
+ count, max);
+ }
+#endif
+ d_func()->geometryVertexCount = count;
+}
+
+
+/*!
+ Returns the maximum number of vertices the current geometry shader
+ program will produce, if active.
+
+ \since 4.7
+
+ This parameter takes effect the ntext time the program is linked.
+*/
+int QGLShaderProgram::geometryOutputVertexCount() const
+{
+ return d_func()->geometryVertexCount;
+}
+
+
+/*!
+ Sets the output type from the geometry shader, if active.
+
+ This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryInputType(GLenum inputType)
+{
+ d_func()->geometryInputType = inputType;
+}
+
+
+/*!
+ Returns the geometry shader input type, if active.
+
+ This parameter takes effect the next time the program is linked.
+
+ \since 4.7
+ */
+
+GLenum QGLShaderProgram::geometryInputType() const
+{
+ return d_func()->geometryInputType;
+}
+
+
+/*!
+ Sets the output type from the geometry shader, if active.
+
+ This parameter takes effect the next time the program is linked.
+
+ \since 4.7
+*/
+void QGLShaderProgram::setGeometryOutputType(GLenum outputType)
+{
+ d_func()->geometryOutputType = outputType;
+}
+
+
+/*!
+ Returns the geometry shader output type, if active.
+
+ This parameter takes effect the next time the program is linked.
+
+ \since 4.7
+ */
+GLenum QGLShaderProgram::geometryOutputType() const
+{
+ return d_func()->geometryOutputType;
+}
+
+
+/*!
Returns true if shader programs written in the OpenGL Shading
Language (GLSL) are supported on this system; false otherwise.
@@ -3076,8 +3211,71 @@ void QGLShaderProgram::shaderDestroyed()
removeShader(shader);
}
+
+#undef ctx
+#undef context
+
+/*!
+ Returns true if shader programs of type \a type are supported on
+ this system; false otherwise.
+
+ The \a context is used to resolve the GLSL extensions.
+ If \a context is null, then QGLContext::currentContext() is used.
+
+ \since 4.7
+*/
+bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
+{
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+
+ if ((type & ~(Geometry | Vertex | Fragment)) || type == 0)
+ return false;
+
+ bool resolved = qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
+ if (!resolved)
+ return false;
+
+ if ((type & Geometry) && !QByteArray((const char *) glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
+ return false;
+
+ return true;
+}
+
+
+
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
/*! \internal */
+void QGLShaderProgram::setAttributeArray
+ (int location, QMacCompatGLenum type, const void *values, int tupleSize, int stride)
+{
+ setAttributeArray(location, GLenum(type), values, tupleSize, stride);
+}
+
+/*! \internal */
+void QGLShaderProgram::setAttributeArray
+ (const char *name, QMacCompatGLenum type, const void *values, int tupleSize, int stride)
+{
+ setAttributeArray(name, GLenum(type), values, tupleSize, stride);
+}
+
+/*! \internal */
+void QGLShaderProgram::setAttributeBuffer
+ (int location, QMacCompatGLenum type, int offset, int tupleSize, int stride)
+{
+ setAttributeBuffer(location, GLenum(type), offset, tupleSize, stride);
+}
+
+/*! \internal */
+void QGLShaderProgram::setAttributeBuffer
+ (const char *name, QMacCompatGLenum type, int offset, int tupleSize, int stride)
+{
+ setAttributeBuffer(name, GLenum(type), offset, tupleSize, stride);
+}
+
+/*! \internal */
void QGLShaderProgram::setUniformValue(int location, QMacCompatGLint value)
{
setUniformValue(location, GLint(value));
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index 2500275..d612b05 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -66,7 +66,8 @@ public:
enum ShaderTypeBit
{
Vertex = 0x0001,
- Fragment = 0x0002
+ Fragment = 0x0002,
+ Geometry = 0x0004
};
Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit)
@@ -88,6 +89,8 @@ public:
GLuint shaderId() const;
+ static bool hasOpenGLShaders(ShaderType type, const QGLContext *context = 0);
+
private:
friend class QGLShaderProgram;
@@ -100,6 +103,14 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QGLShader::ShaderType)
class QGLShaderProgramPrivate;
+#ifndef GL_EXT_geometry_shader4
+# define GL_LINES_ADJACENCY_EXT 0xA
+# define GL_LINE_STRIP_ADJACENCY_EXT 0xB
+# define GL_TRIANGLES_ADJACENCY_EXT 0xC
+# define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
+#endif
+
+
class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
{
Q_OBJECT
@@ -128,6 +139,17 @@ public:
GLuint programId() const;
+ int maxGeometryOutputVertices() const;
+
+ void setGeometryOutputVertexCount(int count);
+ int geometryOutputVertexCount() const;
+
+ void setGeometryInputType(GLenum inputType);
+ GLenum geometryInputType() const;
+
+ void setGeometryOutputType(GLenum outputType);
+ GLenum geometryOutputType() const;
+
void bindAttributeLocation(const char *name, int location);
void bindAttributeLocation(const QByteArray& name, int location);
void bindAttributeLocation(const QString& name, int location);
@@ -182,6 +204,17 @@ public:
void setAttributeBuffer
(const char *name, GLenum type, int offset, int tupleSize, int stride = 0);
+#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
+ void setAttributeArray
+ (int location, QMacCompatGLenum type, const void *values, int tupleSize, int stride = 0);
+ void setAttributeArray
+ (const char *name, QMacCompatGLenum type, const void *values, int tupleSize, int stride = 0);
+ void setAttributeBuffer
+ (int location, QMacCompatGLenum type, int offset, int tupleSize, int stride = 0);
+ void setAttributeBuffer
+ (const char *name, QMacCompatGLenum type, int offset, int tupleSize, int stride = 0);
+#endif
+
void enableAttributeArray(int location);
void enableAttributeArray(const char *name);
void disableAttributeArray(int location);
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index cc9ba77..18d6b0a 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -188,6 +188,7 @@ public:
bool maskValid; // True if vgMask() contains valid data.
bool maskIsSet; // True if mask would be fully set if it was valid.
+ bool scissorMask; // True if scissor is used in place of the mask.
bool rawVG; // True if processing a raw VG escape.
QRect maskRect; // Rectangle version of mask if it is simple.
@@ -355,6 +356,7 @@ void QVGPaintEnginePrivate::init()
maskValid = false;
maskIsSet = false;
+ scissorMask = false;
rawVG = false;
scissorActive = false;
@@ -978,7 +980,7 @@ static QImage colorizeBitmap(const QImage &image, const QColor &color)
int height = sourceImage.height();
int width = sourceImage.width();
for (int y=0; y<height; ++y) {
- uchar *source = sourceImage.scanLine(y);
+ const uchar *source = sourceImage.constScanLine(y);
QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y));
for (int x=0; x < width; ++x)
target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
@@ -986,9 +988,6 @@ static QImage colorizeBitmap(const QImage &image, const QColor &color)
return dest;
}
-// defined in qpixmapdata_vg.cpp.
-const uchar *qt_vg_imageBits(const QImage& image);
-
static VGImage toVGImage
(const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor)
{
@@ -1022,7 +1021,7 @@ static VGImage toVGImage
break;
}
- const uchar *pixels = qt_vg_imageBits(img);
+ const uchar *pixels = img.constBits();
VGImage vgImg = QVGImagePool::instance()->createPermanentImage
(format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
@@ -1066,7 +1065,7 @@ static VGImage toVGImageSubRect
break;
}
- const uchar *pixels = qt_vg_imageBits(img) + bpp * sr.x() +
+ const uchar *pixels = img.constBits() + bpp * sr.x() +
img.bytesPerLine() * sr.y();
VGImage vgImg = QVGImagePool::instance()->createPermanentImage
@@ -1088,7 +1087,7 @@ static VGImage toVGImageWithOpacity(const QImage & image, qreal opacity)
painter.drawImage(0, 0, image);
painter.end();
- const uchar *pixels = qt_vg_imageBits(img);
+ const uchar *pixels = img.constBits();
VGImage vgImg = QVGImagePool::instance()->createPermanentImage
(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
@@ -1110,7 +1109,7 @@ static VGImage toVGImageWithOpacitySubRect
painter.drawImage(QPoint(0, 0), image, sr);
painter.end();
- const uchar *pixels = qt_vg_imageBits(img);
+ const uchar *pixels = img.constBits();
VGImage vgImg = QVGImagePool::instance()->createPermanentImage
(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
@@ -1542,7 +1541,28 @@ void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline bool clipTransformIsSimple(const QTransform& transform)
{
QTransform::TransformationType type = transform.type();
- return (type == QTransform::TxNone || type == QTransform::TxTranslate);
+ if (type == QTransform::TxNone || type == QTransform::TxTranslate)
+ return true;
+ if (type == QTransform::TxRotate) {
+ // Check for 0, 90, 180, and 270 degree rotations.
+ // (0 might happen after 4 rotations of 90 degrees).
+ qreal m11 = transform.m11();
+ qreal m12 = transform.m12();
+ qreal m21 = transform.m21();
+ qreal m22 = transform.m22();
+ if (m11 == 0.0f && m22 == 0.0f) {
+ if (m12 == 1.0f && m21 == -1.0f)
+ return true; // 90 degrees.
+ else if (m12 == -1.0f && m21 == 1.0f)
+ return true; // 270 degrees.
+ } else if (m12 == 0.0f && m21 == 0.0f) {
+ if (m11 == -1.0f && m22 == -1.0f)
+ return true; // 180 degrees.
+ else if (m11 == 1.0f && m22 == 1.0f)
+ return true; // 0 degrees.
+ }
+ }
+ return false;
}
#if defined(QVG_SCISSOR_CLIP)
@@ -1664,12 +1684,12 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
if (op == Qt::NoClip) {
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
return;
}
-#if defined(QVG_NO_RENDER_TO_MASK)
// We don't have vgRenderToMask(), so handle simple QRectF's only.
if (path.shape() == QVectorPath::RectangleHint &&
path.elementCount() == 4 && clipTransformIsSimple(d->transform)) {
@@ -1679,8 +1699,10 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
QRectF rect(points[0], points[1], points[2] - points[0],
points[5] - points[1]);
clip(rect.toRect(), op);
+ return;
}
-#else
+
+#if !defined(QVG_NO_RENDER_TO_MASK)
QPaintDevice *pdev = paintDevice();
int width = pdev->width();
int height = pdev->height();
@@ -1711,6 +1733,7 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_TRUE);
d->maskValid = true;
d->maskIsSet = false;
+ d->scissorMask = false;
#endif
}
@@ -1731,6 +1754,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
{
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
}
@@ -1746,6 +1770,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
// Special case: if the intersection of the system
@@ -1763,6 +1788,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
if (clip.rectCount() != 1) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
d->modifyMask(this, VG_FILL_MASK, r);
break;
@@ -1771,6 +1797,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
}
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = true;
d->maskRect = clipRect;
vgSeti(VG_MASKING, VG_FALSE);
updateScissor();
@@ -1781,13 +1808,30 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
case Qt::IntersectClip:
{
QRect r = d->transform.mapRect(rect);
- if (d->maskIsSet && isDefaultClipRect(r)) {
+ if (!d->maskValid) {
+ // Mask has not been used yet, so intersect with
+ // the previous scissor-based region in maskRect.
+ if (d->scissorMask)
+ r = r.intersect(d->maskRect);
+ if (isDefaultClipRect(r)) {
+ // The clip is the full window, so turn off clipping.
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ } else {
+ // Activate the scissor on a smaller maskRect.
+ d->maskIsSet = false;
+ d->maskRect = r;
+ }
+ d->scissorMask = true;
+ updateScissor();
+ } else 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->scissorMask = false;
d->maskRect = QRect();
} else {
d->modifyMask(this, VG_INTERSECT_MASK, r);
@@ -1829,6 +1873,7 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
{
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
}
@@ -1844,6 +1889,7 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
// Special case: if the intersection of the system
@@ -1857,12 +1903,14 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
if (clip.rectCount() == 1) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = true;
d->maskRect = clip.boundingRect();
vgSeti(VG_MASKING, VG_FALSE);
updateScissor();
} else {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
d->modifyMask(this, VG_FILL_MASK, r);
}
@@ -1887,6 +1935,7 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
d->modifyMask(this, VG_INTERSECT_MASK, r);
@@ -1965,6 +2014,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
if (op == Qt::NoClip) {
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
return;
@@ -2000,6 +2050,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_TRUE);
d->maskValid = true;
d->maskIsSet = false;
+ d->scissorMask = false;
#else
QPaintEngineEx::clip(path, op);
#endif
@@ -2043,6 +2094,7 @@ void QVGPaintEnginePrivate::modifyMask
vgSeti(VG_MASKING, VG_TRUE);
maskValid = true;
maskIsSet = false;
+ scissorMask = false;
}
void QVGPaintEnginePrivate::modifyMask
@@ -2064,6 +2116,7 @@ void QVGPaintEnginePrivate::modifyMask
vgSeti(VG_MASKING, VG_TRUE);
maskValid = true;
maskIsSet = false;
+ scissorMask = false;
}
#endif // !QVG_SCISSOR_CLIP
@@ -2096,7 +2149,7 @@ void QVGPaintEngine::updateScissor()
{
#if !defined(QVG_SCISSOR_CLIP)
// Combine the system clip with the simple mask rectangle.
- if (!d->maskRect.isNull()) {
+ if (d->scissorMask) {
if (region.isEmpty())
region = d->maskRect;
else
@@ -2187,6 +2240,7 @@ void QVGPaintEngine::clipEnabledChanged()
// Replay the entire clip stack to put the mask into the right state.
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
s->clipRegion = defaultClipRegion();
d->replayClipOperations();
@@ -2196,6 +2250,7 @@ void QVGPaintEngine::clipEnabledChanged()
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
}
#endif
@@ -2314,12 +2369,7 @@ bool QVGPaintEngine::clearRect(const QRectF &rect, const QColor &color)
Q_D(QVGPaintEngine);
QVGPainterState *s = state();
if (!s->clipEnabled || s->clipOperation == Qt::NoClip) {
- // The transform will either be identity or a simple translation,
- // so do a simpler version of "r = d->transform.map(rect).toRect()".
- QRect r = QRect(qRound(rect.x() + d->transform.dx()),
- qRound(rect.y() + d->transform.dy()),
- qRound(rect.width()),
- qRound(rect.height()));
+ QRect r = d->transform.mapRect(rect).toRect();
int height = paintDevice()->height();
if (d->clearColor != color || d->clearOpacity != s->opacity) {
VGfloat values[4];
@@ -3175,15 +3225,15 @@ void QVGFontGlyphCache::cacheGlyphs
if (!scaledImage.isNull()) { // Not a space character
if (scaledImage.format() == QImage::Format_Indexed8) {
vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER);
- vgImageSubData(vgImage, qt_vg_imageBits(scaledImage), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
+ vgImageSubData(vgImage, scaledImage.constBits(), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
} else if (scaledImage.format() == QImage::Format_Mono) {
QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8);
vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
- vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
+ vgImageSubData(vgImage, img.constBits(), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
} else {
QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
- vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
+ vgImageSubData(vgImage, img.constBits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
}
}
origin[0] = -metrics.x.toReal() + 0.5f;
@@ -3398,6 +3448,7 @@ void QVGPaintEngine::restoreState(QPaintEngine::DirtyFlags dirty)
QPaintEngine::DirtyClipEnabled)) != 0) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
clipEnabledChanged();
}
@@ -3650,7 +3701,7 @@ void QVGCompositionHelper::drawCursorPixmap
if (vgImage == VG_INVALID_HANDLE)
return;
vgImageSubData
- (vgImage, qt_vg_imageBits(img) + img.bytesPerLine() * (img.height() - 1),
+ (vgImage, img.constBits() + img.bytesPerLine() * (img.height() - 1),
-(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0,
img.width(), img.height());
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index 3087b77..44814cc 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -231,14 +231,6 @@ QPaintEngine* QVGPixmapData::paintEngine() const
return source.paintEngine();
}
-// This function works around QImage::bits() making a deep copy if the
-// QImage is not const. We force it to be const and then get the bits.
-// XXX: Should add a QImage::constBits() in the future to replace this.
-const uchar *qt_vg_imageBits(const QImage& image)
-{
- return image.bits();
-}
-
VGImage QVGPixmapData::toVGImage()
{
if (!isValid())
@@ -271,7 +263,7 @@ VGImage QVGPixmapData::toVGImage()
if (!source.isNull() && recreate) {
vgImageSubData
(vgImage,
- qt_vg_imageBits(source), source.bytesPerLine(),
+ source.constBits(), source.bytesPerLine(),
VG_sARGB_8888_PRE, 0, 0, w, h);
}
@@ -670,7 +662,7 @@ void* QVGPixmapData::toNativeType(NativeType type)
if (bitmap) {
if (bitmap->Create(TSize(source.width(), source.height()),
EColor16MAP) == KErrNone) {
- const uchar *sptr = qt_vg_imageBits(source);
+ const uchar *sptr = source.constBits();
bitmap->BeginDataAccess();
uchar *dptr = (uchar*)bitmap->DataAddress();
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
index ad33d0b..499eb1d 100644
--- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
+++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
@@ -176,7 +176,7 @@ static inline QWidget *mdiAreaNavigate(QWidget *area,
int minimumDistance = INT_MAX;
QWidget *target = 0;
- foreach (QWidget *candidate, candidates.values()) {
+ foreach (QWidget *candidate, candidates) {
switch (relation) {
case QAccessible::Up:
case QAccessible::Down:
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index f27440e..ba50329 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -593,6 +593,17 @@ void QDirectFBPixmapData::invalidate()
imageFormat = QImage::Format_Invalid;
}
+#ifndef QT_DIRECTFB_PLUGIN
+Q_GUI_EXPORT IDirectFBSurface *qt_directfb_surface_for_pixmap(const QPixmap &pixmap)
+{
+ const QPixmapData *data = pixmap.pixmapData();
+ if (!data || data->classId() != QPixmapData::DirectFBClass)
+ return 0;
+ const QDirectFBPixmapData *dfbData = static_cast<const QDirectFBPixmapData*>(data);
+ return dfbData->directFBSurface();
+}
+#endif
+
QT_END_NAMESPACE
#endif // QT_NO_QWS_DIRECTFB
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 6b251c7..cd4d5c2 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -921,7 +921,7 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
qPrintable(flip));
}
} else {
- flipFlags = DSFLIP_BLIT;
+ flipFlags = DSFLIP_BLIT|DSFLIP_ONSYNC;
}
}
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index 6f049be..25d3dfa 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -71,7 +71,8 @@ public:
~QGIFFormat();
int decode(QImage *image, const uchar* buffer, int length,
- int *nextFrameDelay, int *loopCount, QSize *nextSize);
+ int *nextFrameDelay, int *loopCount);
+ static void scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount);
bool newFrame;
bool partialNewFrame;
@@ -229,7 +230,7 @@ void QGIFFormat::disposePrevious(QImage *image)
Returns the number of bytes consumed.
*/
int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
- int *nextFrameDelay, int *loopCount, QSize *nextSize)
+ int *nextFrameDelay, int *loopCount)
{
// We are required to state that
// "The Graphics Interchange Format(c) is the Copyright property of
@@ -346,10 +347,6 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
bpl = image->bytesPerLine();
bits = image->bits();
memset(bits, 0, image->byteCount());
-
- // ### size of the upcoming frame, should rather
- // be known before decoding it.
- *nextSize = QSize(swidth, sheight);
}
disposePrevious(image);
@@ -645,6 +642,273 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
return initial-length;
}
+/*!
+ Scans through the data stream defined by \a device and returns the image
+ sizes found in the stream in the \a imageSizes vector.
+*/
+void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount)
+{
+ if (!device)
+ return;
+
+ qint64 oldPos = device->pos();
+ if (!device->seek(0))
+ return;
+
+ int colorCount = 0;
+ int localColorCount = 0;
+ int globalColorCount = 0;
+ int colorReadCount = 0;
+ bool localColormap = false;
+ bool globalColormap = false;
+ int count = 0;
+ int blockSize = 0;
+ int imageWidth = 0;
+ int imageHeight = 0;
+ bool done = false;
+ uchar hold[16];
+ State state = Header;
+
+ const int readBufferSize = 40960; // 40k read buffer
+ QByteArray readBuffer(device->read(readBufferSize));
+
+ if (readBuffer.isEmpty()) {
+ device->seek(oldPos);
+ return;
+ }
+
+ // This is a specialized version of the state machine from decode(),
+ // which doesn't do any image decoding or mallocing, and has an
+ // optimized way of skipping SkipBlocks, ImageDataBlocks and
+ // Global/LocalColorMaps.
+
+ while (!readBuffer.isEmpty()) {
+ int length = readBuffer.size();
+ const uchar *buffer = (const uchar *) readBuffer.constData();
+ while (!done && length) {
+ length--;
+ uchar ch = *buffer++;
+ switch (state) {
+ case Header:
+ hold[count++] = ch;
+ if (count == 6) {
+ state = LogicalScreenDescriptor;
+ count = 0;
+ }
+ break;
+ case LogicalScreenDescriptor:
+ hold[count++] = ch;
+ if (count == 7) {
+ imageWidth = LM(hold[0], hold[1]);
+ imageHeight = LM(hold[2], hold[3]);
+ globalColormap = !!(hold[4] & 0x80);
+ globalColorCount = 2 << (hold[4] & 0x7);
+ count = 0;
+ colorCount = globalColorCount;
+ if (globalColormap) {
+ int colorTableSize = 3 * globalColorCount;
+ if (length >= colorTableSize) {
+ // skip the global color table in one go
+ length -= colorTableSize;
+ buffer += colorTableSize;
+ state = Introducer;
+ } else {
+ colorReadCount = 0;
+ state = GlobalColorMap;
+ }
+ } else {
+ state=Introducer;
+ }
+ }
+ break;
+ case GlobalColorMap:
+ case LocalColorMap:
+ hold[count++] = ch;
+ if (count == 3) {
+ if (++colorReadCount >= colorCount) {
+ if (state == LocalColorMap)
+ state = TableImageLZWSize;
+ else
+ state = Introducer;
+ }
+ count = 0;
+ }
+ break;
+ case Introducer:
+ hold[count++] = ch;
+ switch (ch) {
+ case 0x2c:
+ state = ImageDescriptor;
+ break;
+ case 0x21:
+ state = ExtensionLabel;
+ break;
+ case 0x3b:
+ state = Done;
+ break;
+ default:
+ done = true;
+ state = Error;
+ }
+ break;
+ case ImageDescriptor:
+ hold[count++] = ch;
+ if (count == 10) {
+ int newLeft = LM(hold[1], hold[2]);
+ int newTop = LM(hold[3], hold[4]);
+ int newWidth = LM(hold[5], hold[6]);
+ int newHeight = LM(hold[7], hold[8]);
+
+ if (imageWidth/10 > qMax(newWidth,200))
+ imageWidth = -1;
+ if (imageHeight/10 > qMax(newHeight,200))
+ imageHeight = -1;
+
+ if (imageWidth <= 0)
+ imageWidth = newLeft + newWidth;
+ if (imageHeight <= 0)
+ imageHeight = newTop + newHeight;
+
+ *imageSizes << QSize(imageWidth, imageHeight);
+
+ localColormap = !!(hold[9] & 0x80);
+ localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
+ if (localColorCount)
+ colorCount = localColorCount;
+ else
+ colorCount = globalColorCount;
+
+ count = 0;
+ if (localColormap) {
+ int colorTableSize = 3 * localColorCount;
+ if (length >= colorTableSize) {
+ // skip the local color table in one go
+ length -= colorTableSize;
+ buffer += colorTableSize;
+ state = TableImageLZWSize;
+ } else {
+ colorReadCount = 0;
+ state = LocalColorMap;
+ }
+ } else {
+ state = TableImageLZWSize;
+ }
+ }
+ break;
+ case TableImageLZWSize:
+ if (ch > max_lzw_bits)
+ state = Error;
+ else
+ state = ImageDataBlockSize;
+ count = 0;
+ break;
+ case ImageDataBlockSize:
+ blockSize = ch;
+ if (blockSize) {
+ if (length >= blockSize) {
+ // we can skip the block in one go
+ length -= blockSize;
+ buffer += blockSize;
+ count = 0;
+ } else {
+ state = ImageDataBlock;
+ }
+ } else {
+ state = Introducer;
+ }
+ break;
+ case ImageDataBlock:
+ ++count;
+ if (count == blockSize) {
+ count = 0;
+ state = ImageDataBlockSize;
+ }
+ break;
+ case ExtensionLabel:
+ switch (ch) {
+ case 0xf9:
+ state = GraphicControlExtension;
+ break;
+ case 0xff:
+ state = ApplicationExtension;
+ break;
+ default:
+ state = SkipBlockSize;
+ }
+ count = 0;
+ break;
+ case ApplicationExtension:
+ if (count < 11)
+ hold[count] = ch;
+ ++count;
+ if (count == hold[0] + 1) {
+ if (qstrncmp((char*)(hold+1), "NETSCAPE", 8) == 0)
+ state=NetscapeExtensionBlockSize;
+ else
+ state=SkipBlockSize;
+ count = 0;
+ }
+ break;
+ case GraphicControlExtension:
+ if (count < 5)
+ hold[count] = ch;
+ ++count;
+ if (count == hold[0] + 1) {
+ count = 0;
+ state = SkipBlockSize;
+ }
+ break;
+ case NetscapeExtensionBlockSize:
+ blockSize = ch;
+ count = 0;
+ if (blockSize)
+ state = NetscapeExtensionBlock;
+ else
+ state = Introducer;
+ break;
+ case NetscapeExtensionBlock:
+ if (count < 3)
+ hold[count] = ch;
+ count++;
+ if (count == blockSize) {
+ *loopCount = LM(hold[1], hold[2]);
+ state = SkipBlockSize;
+ }
+ break;
+ case SkipBlockSize:
+ blockSize = ch;
+ count = 0;
+ if (blockSize) {
+ if (length >= blockSize) {
+ // we can skip the block in one go
+ length -= blockSize;
+ buffer += blockSize;
+ } else {
+ state = SkipBlock;
+ }
+ } else {
+ state = Introducer;
+ }
+ break;
+ case SkipBlock:
+ ++count;
+ if (count == blockSize)
+ state = SkipBlockSize;
+ break;
+ case Done:
+ done = true;
+ break;
+ case Error:
+ device->seek(oldPos);
+ return;
+ }
+ }
+ readBuffer = device->read(readBufferSize);
+ }
+ device->seek(oldPos);
+ return;
+}
+
void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb color)
{
if (w>0) {
@@ -763,9 +1027,9 @@ QGifHandler::QGifHandler()
{
gifFormat = new QGIFFormat;
nextDelay = 0;
- loopCnt = 0;
+ loopCnt = 1;
frameNumber = -1;
- nextSize = QSize();
+ scanIsCached = false;
}
QGifHandler::~QGifHandler()
@@ -787,7 +1051,7 @@ bool QGifHandler::imageIsComing() const
}
int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
- &nextDelay, &loopCnt, &nextSize);
+ &nextDelay, &loopCnt);
if (decoded == -1)
break;
buffer.remove(0, decoded);
@@ -831,7 +1095,7 @@ bool QGifHandler::read(QImage *image)
}
int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
- &nextDelay, &loopCnt, &nextSize);
+ &nextDelay, &loopCnt);
if (decoded == -1)
break;
buffer.remove(0, decoded);
@@ -862,8 +1126,18 @@ bool QGifHandler::supportsOption(ImageOption option) const
QVariant QGifHandler::option(ImageOption option) const
{
if (option == Size) {
- if (imageIsComing())
- return nextSize;
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes, &loopCnt);
+ scanIsCached = true;
+ }
+ // before the first frame is read, or we have an empty data stream
+ if (frameNumber == -1)
+ return (imageSizes.count() > 0) ? QVariant(imageSizes.at(0)) : QVariant();
+ // after the last frame has been read, the next size is undefined
+ if (frameNumber >= imageSizes.count() - 1)
+ return QVariant();
+ // and the last case: the size of the next frame
+ return imageSizes.at(frameNumber + 1);
} else if (option == Animation) {
return true;
}
@@ -883,11 +1157,19 @@ int QGifHandler::nextImageDelay() const
int QGifHandler::imageCount() const
{
- return 0; // Don't know
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes, &loopCnt);
+ scanIsCached = true;
+ }
+ return imageSizes.count();
}
int QGifHandler::loopCount() const
{
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes, &loopCnt);
+ scanIsCached = true;
+ }
return loopCnt-1; // In GIF, loop count is iteration count, so subtract one
}
diff --git a/src/plugins/imageformats/gif/qgifhandler.h b/src/plugins/imageformats/gif/qgifhandler.h
index a6e520f..8e07aff 100644
--- a/src/plugins/imageformats/gif/qgifhandler.h
+++ b/src/plugins/imageformats/gif/qgifhandler.h
@@ -87,7 +87,8 @@ private:
mutable int nextDelay;
mutable int loopCnt;
int frameNumber;
- mutable QSize nextSize;
+ mutable QVector<QSize> imageSizes;
+ mutable bool scanIsCached;
};
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index b2351fa..4edb87a 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -53,6 +53,7 @@
#include <QtGui/QImage>
#include <QtCore/QFile>
#include <QtCore/QBuffer>
+#include <qvariant.h>
// These next two structs represent how the icon information is stored
// in an ICO file.
typedef struct
@@ -772,6 +773,29 @@ QtIcoHandler::~QtIcoHandler()
delete m_pICOReader;
}
+QVariant QtIcoHandler::option(ImageOption option) const
+{
+ if (option == Size) {
+ QIODevice *device = QImageIOHandler::device();
+ qint64 oldPos = device->pos();
+ ICONDIRENTRY iconEntry;
+ if (device->seek(oldPos + ICONDIR_SIZE + (m_currentIconIndex * ICONDIRENTRY_SIZE))) {
+ if (readIconDirEntry(device, &iconEntry)) {
+ device->seek(oldPos);
+ return QSize(iconEntry.bWidth, iconEntry.bHeight);
+ }
+ }
+ if (!device->isSequential())
+ device->seek(oldPos);
+ }
+ return QVariant();
+}
+
+bool QtIcoHandler::supportsOption(ImageOption option) const
+{
+ return option == Size;
+}
+
/*!
* Verifies if some values (magic bytes) are set as expected in the header of the file.
* If the magic bytes were found, it is assumed that the QtIcoHandler can read the file.
diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h
index b9ef27e..394a5eb 100644
--- a/src/plugins/imageformats/ico/qicohandler.h
+++ b/src/plugins/imageformats/ico/qicohandler.h
@@ -62,6 +62,9 @@ public:
static bool canRead(QIODevice *device);
+ bool supportsOption(ImageOption option) const;
+ QVariant option(ImageOption option) const;
+
private:
int m_currentIconIndex;
ICOReader *m_pICOReader;
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index 6cb93ad..4b4712c 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -52,8 +52,6 @@
#undef FAR
#endif
-// hw: optimize smoothscaler for returning 24-bit images
-
// including jpeglib.h seems to be a little messy
extern "C" {
// mingw includes rpcndr.h but does not define boolean
@@ -76,433 +74,6 @@ extern "C" {
QT_BEGIN_NAMESPACE
-//#define QT_NO_IMAGE_SMOOTHSCALE
-#ifndef QT_NO_IMAGE_SMOOTHSCALE
-class QImageSmoothScalerPrivate;
-class QImageSmoothScaler
-{
-public:
- QImageSmoothScaler(const int w, const int h, const QImage &src);
- QImageSmoothScaler(const int srcWidth, const int srcHeight,
- const int dstWidth, const int dstHeight);
-
- virtual ~QImageSmoothScaler(void);
-
- QImage scale();
-
-private:
- QImageSmoothScalerPrivate *d;
- virtual QRgb *scanLine(const int line = 0, const QImage *src = 0);
-};
-
-class QImageSmoothScalerPrivate
-{
-public:
- int cols;
- int newcols;
- int rows;
- int newrows;
- bool hasAlpha;
-
- const QImage *src;
-
- void setup(const int srcWidth, const int srcHeight, const int dstWidth,
- const int dstHeight, bool hasAlphaChannel);
-};
-
-QImageSmoothScaler::QImageSmoothScaler(const int w, const int h,
- const QImage &src)
-{
- d = new QImageSmoothScalerPrivate;
-
- d->setup(src.width(), src.height(), w, h, src.hasAlphaChannel() );
- this->d->src = &src;
-}
-
-QImageSmoothScaler::QImageSmoothScaler(const int srcWidth, const int srcHeight,
- const int dstWidth, const int dstHeight)
-{
- d = new QImageSmoothScalerPrivate;
- d->setup(srcWidth, srcHeight, dstWidth, dstHeight, 0);
-}
-
-void QImageSmoothScalerPrivate::setup(const int srcWidth, const int srcHeight,
- const int dstWidth, const int dstHeight,
- bool hasAlphaChannel)
-{
- cols = srcWidth;
- rows = srcHeight;
- newcols = dstWidth;
- newrows = dstHeight;
- hasAlpha = hasAlphaChannel;
-}
-
-QImageSmoothScaler::~QImageSmoothScaler()
-{
- delete d;
-}
-
-inline QRgb *QImageSmoothScaler::scanLine(const int line, const QImage *src)
-{
- return (QRgb*)src->scanLine(line);
-}
-
-/*
- This function uses code based on pnmscale.c by Jef Poskanzer.
-
- pnmscale.c - read a portable anymap and scale it
-
- Copyright (C) 1989, 1991 by Jef Poskanzer.
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted, provided
- that the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation. This software is provided "as is" without express or
- implied warranty.
-*/
-
-QImage QImageSmoothScaler::scale()
-{
- long SCALE;
- long HALFSCALE;
- QRgb *xelrow = 0;
- QRgb *tempxelrow = 0;
- QRgb *xP;
- QRgb *nxP;
- int row, rowsread;
- int col, needtoreadrow;
- uchar maxval = 255;
- qreal xscale, yscale;
- long sxscale, syscale;
- long fracrowtofill, fracrowleft;
- long *as;
- long *rs;
- long *gs;
- long *bs;
- int rowswritten = 0;
- QImage dst;
-
- if (d->cols > 4096) {
- SCALE = 4096;
- HALFSCALE = 2048;
- } else {
- int fac = 4096;
- while (d->cols * fac > 4096)
- fac /= 2;
-
- SCALE = fac * d->cols;
- HALFSCALE = fac * d->cols / 2;
- }
-
- xscale = (qreal)d->newcols / (qreal)d->cols;
- yscale = (qreal)d->newrows / (qreal)d->rows;
- sxscale = (long)(xscale * SCALE);
- syscale = (long)(yscale * SCALE);
-
- // shortcut Y scaling if possible
- if (d->newrows != d->rows)
- tempxelrow = new QRgb[d->cols];
-
- if (d->hasAlpha) {
- as = new long[d->cols];
- for (col = 0; col < d->cols; ++col)
- as[col] = HALFSCALE;
- } else {
- as = 0;
- }
- rs = new long[d->cols];
- gs = new long[d->cols];
- bs = new long[d->cols];
- rowsread = 0;
- fracrowleft = syscale;
- needtoreadrow = 1;
- for (col = 0; col < d->cols; ++col)
- rs[col] = gs[col] = bs[col] = HALFSCALE;
- fracrowtofill = SCALE;
-
- dst = QImage(d->newcols, d->newrows, d->hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
-
- for (row = 0; row < d->newrows; ++row) {
- // First scale Y from xelrow into tempxelrow.
- if (d->newrows == d->rows) {
- // shortcut Y scaling if possible
- tempxelrow = xelrow = scanLine(rowsread++, d->src);
- } else {
- while (fracrowleft < fracrowtofill) {
- if (needtoreadrow && rowsread < d->rows)
- xelrow = scanLine(rowsread++, d->src);
- for (col = 0, xP = xelrow; col < d->cols; ++col, ++xP) {
- if (as) {
- as[col] += fracrowleft * qAlpha(*xP);
- rs[col] += fracrowleft * qRed(*xP) * qAlpha(*xP) / 255;
- gs[col] += fracrowleft * qGreen(*xP) * qAlpha(*xP) / 255;
- bs[col] += fracrowleft * qBlue(*xP) * qAlpha(*xP) / 255;
- } else {
- rs[col] += fracrowleft * qRed(*xP);
- gs[col] += fracrowleft * qGreen(*xP);
- bs[col] += fracrowleft * qBlue(*xP);
- }
- }
- fracrowtofill -= fracrowleft;
- fracrowleft = syscale;
- needtoreadrow = 1;
- }
- // Now fracrowleft is >= fracrowtofill, so we can produce a row.
- if (needtoreadrow && rowsread < d->rows) {
- xelrow = scanLine(rowsread++, d->src);
- needtoreadrow = 0;
- }
- for (col = 0, xP = xelrow, nxP = tempxelrow; col < d->cols; ++col, ++xP, ++nxP) {
- register long a, r, g, b;
-
- if (as) {
- r = rs[col] + fracrowtofill * qRed(*xP) * qAlpha(*xP) / 255;
- g = gs[col] + fracrowtofill * qGreen(*xP) * qAlpha(*xP) / 255;
- b = bs[col] + fracrowtofill * qBlue(*xP) * qAlpha(*xP) / 255;
- a = as[col] + fracrowtofill * qAlpha(*xP);
- if (a) {
- r = r * 255 / a * SCALE;
- g = g * 255 / a * SCALE;
- b = b * 255 / a * SCALE;
- }
- } else {
- r = rs[col] + fracrowtofill * qRed(*xP);
- g = gs[col] + fracrowtofill * qGreen(*xP);
- b = bs[col] + fracrowtofill * qBlue(*xP);
- a = 0; // unwarn
- }
- r /= SCALE;
- if (r > maxval)
- r = maxval;
- g /= SCALE;
- if (g > maxval)
- g = maxval;
- b /= SCALE;
- if (b > maxval)
- b = maxval;
- if (as) {
- a /= SCALE;
- if (a > maxval)
- a = maxval;
- *nxP = qRgba((int)r, (int)g, (int)b, (int)a);
- as[col] = HALFSCALE;
- } else {
- *nxP = qRgb((int)r, (int)g, (int)b);
- }
- rs[col] = gs[col] = bs[col] = HALFSCALE;
- }
- fracrowleft -= fracrowtofill;
- if (fracrowleft == 0) {
- fracrowleft = syscale;
- needtoreadrow = 1;
- }
- fracrowtofill = SCALE;
- }
-
- // Now scale X from tempxelrow into dst and write it out.
- if (d->newcols == d->cols) {
- // shortcut X scaling if possible
- memcpy(dst.scanLine(rowswritten++), tempxelrow, d->newcols * 4);
- } else {
- register long a, r, g, b;
- register long fraccoltofill, fraccolleft = 0;
- register int needcol;
-
- nxP = (QRgb *)dst.scanLine(rowswritten++);
- QRgb *nxPEnd = nxP + d->newcols;
- fraccoltofill = SCALE;
- a = r = g = b = HALFSCALE;
- needcol = 0;
- for (col = 0, xP = tempxelrow; col < d->cols; ++col, ++xP) {
- fraccolleft = sxscale;
- while (fraccolleft >= fraccoltofill) {
- if (needcol) {
- ++nxP;
- a = r = g = b = HALFSCALE;
- }
- if (as) {
- r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255;
- g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255;
- b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255;
- a += fraccoltofill * qAlpha(*xP);
- if (a) {
- r = r * 255 / a * SCALE;
- g = g * 255 / a * SCALE;
- b = b * 255 / a * SCALE;
- }
- } else {
- r += fraccoltofill * qRed(*xP);
- g += fraccoltofill * qGreen(*xP);
- b += fraccoltofill * qBlue(*xP);
- }
- r /= SCALE;
- if (r > maxval)
- r = maxval;
- g /= SCALE;
- if (g > maxval)
- g = maxval;
- b /= SCALE;
- if (b > maxval)
- b = maxval;
- if (as) {
- a /= SCALE;
- if (a > maxval)
- a = maxval;
- *nxP = qRgba((int)r, (int)g, (int)b, (int)a);
- } else {
- *nxP = qRgb((int)r, (int)g, (int)b);
- }
- fraccolleft -= fraccoltofill;
- fraccoltofill = SCALE;
- needcol = 1;
- }
- if (fraccolleft > 0) {
- if (needcol) {
- ++nxP;
- a = r = g = b = HALFSCALE;
- needcol = 0;
- }
- if (as) {
- a += fraccolleft * qAlpha(*xP);
- r += fraccolleft * qRed(*xP) * qAlpha(*xP) / 255;
- g += fraccolleft * qGreen(*xP) * qAlpha(*xP) / 255;
- b += fraccolleft * qBlue(*xP) * qAlpha(*xP) / 255;
- } else {
- r += fraccolleft * qRed(*xP);
- g += fraccolleft * qGreen(*xP);
- b += fraccolleft * qBlue(*xP);
- }
- fraccoltofill -= fraccolleft;
- }
- }
- if (fraccoltofill > 0) {
- --xP;
- if (as) {
- a += fraccolleft * qAlpha(*xP);
- r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255;
- g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255;
- b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255;
- if (a) {
- r = r * 255 / a * SCALE;
- g = g * 255 / a * SCALE;
- b = b * 255 / a * SCALE;
- }
- } else {
- r += fraccoltofill * qRed(*xP);
- g += fraccoltofill * qGreen(*xP);
- b += fraccoltofill * qBlue(*xP);
- }
- }
- if (nxP < nxPEnd) {
- r /= SCALE;
- if (r > maxval)
- r = maxval;
- g /= SCALE;
- if (g > maxval)
- g = maxval;
- b /= SCALE;
- if (b > maxval)
- b = maxval;
- if (as) {
- a /= SCALE;
- if (a > maxval)
- a = maxval;
- *nxP = qRgba((int)r, (int)g, (int)b, (int)a);
- } else {
- *nxP = qRgb((int)r, (int)g, (int)b);
- }
- while (++nxP != nxPEnd)
- nxP[0] = nxP[-1];
- }
- }
- }
-
- if (d->newrows != d->rows && tempxelrow)// Robust, tempxelrow might be 0 1 day
- delete [] tempxelrow;
- if (as) // Avoid purify complaint
- delete [] as;
- if (rs) // Robust, rs might be 0 one day
- delete [] rs;
- if (gs) // Robust, gs might be 0 one day
- delete [] gs;
- if (bs) // Robust, bs might be 0 one day
- delete [] bs;
-
- return dst;
-}
-
-class jpegSmoothScaler : public QImageSmoothScaler
-{
-public:
- jpegSmoothScaler(struct jpeg_decompress_struct *info, const QSize& dstSize, const QRect& clipRect)
- : QImageSmoothScaler(clipRect.width(), clipRect.height(),
- dstSize.width(), dstSize.height())
- {
- cinfo = info;
- clip = clipRect;
- imageCache = QImage(info->output_width, 1, QImage::Format_RGB32);
- }
-
-private:
- QRect clip;
- QImage imageCache;
- struct jpeg_decompress_struct *cinfo;
-
- QRgb *scanLine(const int line = 0, const QImage *src = 0)
- {
- QRgb *out;
- uchar *in;
-
- Q_UNUSED(line);
- Q_UNUSED(src);
-
- uchar* data = imageCache.bits();
-
- // Read ahead if we haven't reached the first clipped scanline yet.
- while (int(cinfo->output_scanline) < clip.y() &&
- cinfo->output_scanline < cinfo->output_height)
- jpeg_read_scanlines(cinfo, &data, 1);
-
- // Read the next scanline. We assume that "line"
- // will never be >= clip.height().
- jpeg_read_scanlines(cinfo, &data, 1);
- if (cinfo->output_scanline == cinfo->output_height)
- jpeg_finish_decompress(cinfo);
-
- out = ((QRgb*)data) + clip.x();
-
- //
- // The smooth scale algorithm only works on 32-bit images;
- // convert from (8|24) bits to 32.
- //
- if (cinfo->output_components == 1) {
- in = data + clip.right();
- for (int i = clip.width(); i--; ) {
- out[i] = qRgb(*in, *in, *in);
- in--;
- }
- } else if (cinfo->out_color_space == JCS_CMYK) {
- in = data + clip.right() * 4;
- for (int i = clip.width(); i--; ) {
- int k = in[3];
- out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255);
- in -= 4;
- }
- } else {
- in = data + clip.right() * 3;
- for (int i = clip.width(); i--; ) {
- out[i] = qRgb(in[0], in[1], in[2]);
- in -= 3;
- }
- }
-
- return out;
- }
-
-};
-#endif
-
struct my_error_mgr : public jpeg_error_mgr {
jmp_buf setjmp_buffer;
};
@@ -844,93 +415,82 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage,
clip = clip.intersected(imageRect);
}
-#ifndef QT_NO_IMAGE_SMOOTHSCALE
- if (scaledSize.isValid() && scaledSize != clip.size()
- && quality >= HIGH_QUALITY_THRESHOLD) {
+ // Allocate memory for the clipped QImage.
+ if (!ensureValidImage(outImage, &cinfo, clip.size()))
+ longjmp(jerr.setjmp_buffer, 1);
+
+ // Avoid memcpy() overhead if grayscale with no clipping.
+ bool quickGray = (cinfo.output_components == 1 &&
+ clip == imageRect);
+ if (!quickGray) {
+ // Ask the jpeg library to allocate a temporary row.
+ // The library will automatically delete it for us later.
+ // The libjpeg docs say we should do this before calling
+ // jpeg_start_decompress(). We can't use "new" here
+ // because we are inside the setjmp() block and an error
+ // in the jpeg input stream would cause a memory leak.
+ JSAMPARRAY rows = (cinfo.mem->alloc_sarray)
+ ((j_common_ptr)&cinfo, JPOOL_IMAGE,
+ cinfo.output_width * cinfo.output_components, 1);
(void) jpeg_start_decompress(&cinfo);
- jpegSmoothScaler scaler(&cinfo, scaledSize, clip);
- *outImage = scaler.scale();
- } else
-#endif
- {
- // Allocate memory for the clipped QImage.
- if (!ensureValidImage(outImage, &cinfo, clip.size()))
- longjmp(jerr.setjmp_buffer, 1);
-
- // Avoid memcpy() overhead if grayscale with no clipping.
- bool quickGray = (cinfo.output_components == 1 &&
- clip == imageRect);
- if (!quickGray) {
- // Ask the jpeg library to allocate a temporary row.
- // The library will automatically delete it for us later.
- // The libjpeg docs say we should do this before calling
- // jpeg_start_decompress(). We can't use "new" here
- // because we are inside the setjmp() block and an error
- // in the jpeg input stream would cause a memory leak.
- JSAMPARRAY rows = (cinfo.mem->alloc_sarray)
- ((j_common_ptr)&cinfo, JPOOL_IMAGE,
- cinfo.output_width * cinfo.output_components, 1);
-
- (void) jpeg_start_decompress(&cinfo);
-
- while (cinfo.output_scanline < cinfo.output_height) {
- int y = int(cinfo.output_scanline) - clip.y();
- if (y >= clip.height())
- break; // We've read the entire clip region, so abort.
-
- (void) jpeg_read_scanlines(&cinfo, rows, 1);
-
- if (y < 0)
- continue; // Haven't reached the starting line yet.
-
- if (cinfo.output_components == 3) {
- // Expand 24->32 bpp.
- uchar *in = rows[0] + clip.x() * 3;
- QRgb *out = (QRgb*)outImage->scanLine(y);
- for (int i = 0; i < clip.width(); ++i) {
- *out++ = qRgb(in[0], in[1], in[2]);
- in += 3;
- }
- } else if (cinfo.out_color_space == JCS_CMYK) {
- // Convert CMYK->RGB.
- uchar *in = rows[0] + clip.x() * 4;
- QRgb *out = (QRgb*)outImage->scanLine(y);
- for (int i = 0; i < clip.width(); ++i) {
- int k = in[3];
- *out++ = qRgb(k * in[0] / 255, k * in[1] / 255,
- k * in[2] / 255);
- in += 4;
- }
- } else if (cinfo.output_components == 1) {
- // Grayscale.
- memcpy(outImage->scanLine(y),
- rows[0] + clip.x(), clip.width());
+ while (cinfo.output_scanline < cinfo.output_height) {
+ int y = int(cinfo.output_scanline) - clip.y();
+ if (y >= clip.height())
+ break; // We've read the entire clip region, so abort.
+
+ (void) jpeg_read_scanlines(&cinfo, rows, 1);
+
+ if (y < 0)
+ continue; // Haven't reached the starting line yet.
+
+ if (cinfo.output_components == 3) {
+ // Expand 24->32 bpp.
+ uchar *in = rows[0] + clip.x() * 3;
+ QRgb *out = (QRgb*)outImage->scanLine(y);
+ for (int i = 0; i < clip.width(); ++i) {
+ *out++ = qRgb(in[0], in[1], in[2]);
+ in += 3;
}
- }
- } else {
- // Load unclipped grayscale data directly into the QImage.
- (void) jpeg_start_decompress(&cinfo);
- while (cinfo.output_scanline < cinfo.output_height) {
- uchar *row = outImage->scanLine(cinfo.output_scanline);
- (void) jpeg_read_scanlines(&cinfo, &row, 1);
+ } else if (cinfo.out_color_space == JCS_CMYK) {
+ // Convert CMYK->RGB.
+ uchar *in = rows[0] + clip.x() * 4;
+ QRgb *out = (QRgb*)outImage->scanLine(y);
+ for (int i = 0; i < clip.width(); ++i) {
+ int k = in[3];
+ *out++ = qRgb(k * in[0] / 255, k * in[1] / 255,
+ k * in[2] / 255);
+ in += 4;
+ }
+ } else if (cinfo.output_components == 1) {
+ // Grayscale.
+ memcpy(outImage->scanLine(y),
+ rows[0] + clip.x(), clip.width());
}
}
+ } else {
+ // Load unclipped grayscale data directly into the QImage.
+ (void) jpeg_start_decompress(&cinfo);
+ while (cinfo.output_scanline < cinfo.output_height) {
+ uchar *row = outImage->scanLine(cinfo.output_scanline);
+ (void) jpeg_read_scanlines(&cinfo, &row, 1);
+ }
+ }
- if (cinfo.output_scanline == cinfo.output_height)
- (void) jpeg_finish_decompress(&cinfo);
+ if (cinfo.output_scanline == cinfo.output_height)
+ (void) jpeg_finish_decompress(&cinfo);
- if (cinfo.density_unit == 1) {
- outImage->setDotsPerMeterX(int(100. * cinfo.X_density / 2.54));
- outImage->setDotsPerMeterY(int(100. * cinfo.Y_density / 2.54));
- } else if (cinfo.density_unit == 2) {
- outImage->setDotsPerMeterX(int(100. * cinfo.X_density));
- outImage->setDotsPerMeterY(int(100. * cinfo.Y_density));
- }
+ if (cinfo.density_unit == 1) {
+ outImage->setDotsPerMeterX(int(100. * cinfo.X_density / 2.54));
+ outImage->setDotsPerMeterY(int(100. * cinfo.Y_density / 2.54));
+ } else if (cinfo.density_unit == 2) {
+ outImage->setDotsPerMeterX(int(100. * cinfo.X_density));
+ outImage->setDotsPerMeterY(int(100. * cinfo.Y_density));
+ }
- if (scaledSize.isValid() && scaledSize != clip.size())
- *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::FastTransformation);
+ if (scaledSize.isValid() && scaledSize != clip.size()) {
+ *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, quality >= HIGH_QUALITY_THRESHOLD ? Qt::SmoothTransformation : Qt::FastTransformation);
}
}
diff --git a/src/plugins/kbddrivers/linuxinput/main.cpp b/src/plugins/kbddrivers/linuxinput/main.cpp
index 19a3145..db5167e 100644
--- a/src/plugins/kbddrivers/linuxinput/main.cpp
+++ b/src/plugins/kbddrivers/linuxinput/main.cpp
@@ -69,7 +69,7 @@ QWSKeyboardHandler* QLinuxInputKbdDriver::create(const QString &driver,
Q_UNUSED(device);
if (driver.compare(QLatin1String("LinuxInput"), Qt::CaseInsensitive))
return 0;
- return new QWSLinuxInputKeyboardHandler(driver, device);
+ return new QWSLinuxInputKeyboardHandler(device);
}
Q_EXPORT_PLUGIN2(qwslinuxinputkbddriver, QLinuxInputKbdDriver)
diff --git a/src/qt3support/dialogs/q3filedialog.cpp b/src/qt3support/dialogs/q3filedialog.cpp
index 9b8e4d3..35f7890 100644
--- a/src/qt3support/dialogs/q3filedialog.cpp
+++ b/src/qt3support/dialogs/q3filedialog.cpp
@@ -475,9 +475,17 @@ static int sortFilesBy = (int)QDir::Name;
static bool sortAscending = true;
static bool detailViewMode = false;
-static Q3CleanupHandler<QPixmap> qfd_cleanup_pixmap;
static Q3CleanupHandler<QString> qfd_cleanup_string;
+static void qt_cleanup_fd_pixmaps();
+typedef QList<QPixmap *> FDPixmaps;
+Q_GLOBAL_STATIC_WITH_INITIALIZER(FDPixmaps, qfd_pixmaps, qAddPostRoutine(qt_cleanup_fd_pixmaps))
+
+static void qt_cleanup_fd_pixmaps()
+{
+ qDeleteAll(*qfd_pixmaps());
+}
+
static QString toRootIfNotExists( const QString &path )
{
if ( !path.isEmpty() )
@@ -533,37 +541,37 @@ static void makeVariables() {
qfd_cleanup_string.add(&workingDirectory);
openFolderIcon = new QPixmap((const char **)open_xpm);
- qfd_cleanup_pixmap.add(&openFolderIcon);
+ qfd_pixmaps()->append(openFolderIcon);
symLinkDirIcon = new QPixmap((const char **)link_dir_xpm);
- qfd_cleanup_pixmap.add(&symLinkDirIcon);
+ qfd_pixmaps()->append(symLinkDirIcon);
symLinkFileIcon = new QPixmap((const char **)link_file_xpm);
- qfd_cleanup_pixmap.add(&symLinkFileIcon);
+ qfd_pixmaps()->append(symLinkFileIcon);
fileIcon = new QPixmap((const char **)file_xpm);
- qfd_cleanup_pixmap.add(&fileIcon);
+ qfd_pixmaps()->append(fileIcon);
closedFolderIcon = new QPixmap((const char **)closed_xpm);
- qfd_cleanup_pixmap.add(&closedFolderIcon);
+ qfd_pixmaps()->append(closedFolderIcon);
detailViewIcon = new QPixmap((const char **)detailedview_xpm);
- qfd_cleanup_pixmap.add(&detailViewIcon);
+ qfd_pixmaps()->append(detailViewIcon);
multiColumnListViewIcon = new QPixmap((const char **)mclistview_xpm);
- qfd_cleanup_pixmap.add(&multiColumnListViewIcon);
+ qfd_pixmaps()->append(multiColumnListViewIcon);
cdToParentIcon = new QPixmap((const char **)cdtoparent_xpm);
- qfd_cleanup_pixmap.add(&cdToParentIcon);
+ qfd_pixmaps()->append(cdToParentIcon);
newFolderIcon = new QPixmap((const char **)newfolder_xpm);
- qfd_cleanup_pixmap.add(&newFolderIcon);
+ qfd_pixmaps()->append(newFolderIcon);
previewInfoViewIcon
= new QPixmap((const char **)previewinfoview_xpm);
- qfd_cleanup_pixmap.add(&previewInfoViewIcon);
+ qfd_pixmaps()->append(previewInfoViewIcon);
previewContentsViewIcon
= new QPixmap((const char **)previewcontentsview_xpm);
- qfd_cleanup_pixmap.add(&previewContentsViewIcon);
+ qfd_pixmaps()->append(previewContentsViewIcon);
startCopyIcon = new QPixmap((const char **)start_xpm);
- qfd_cleanup_pixmap.add(&startCopyIcon);
+ qfd_pixmaps()->append(startCopyIcon);
endCopyIcon = new QPixmap((const char **)end_xpm);
- qfd_cleanup_pixmap.add(&endCopyIcon);
+ qfd_pixmaps()->append(endCopyIcon);
goBackIcon = new QPixmap((const char **)back_xpm);
- qfd_cleanup_pixmap.add(&goBackIcon);
+ qfd_pixmaps()->append(goBackIcon);
fifteenTransparentPixels = new QPixmap(closedFolderIcon->width(), 1);
- qfd_cleanup_pixmap.add(&fifteenTransparentPixels);
+ qfd_pixmaps()->append(fifteenTransparentPixels);
QBitmap m(fifteenTransparentPixels->width(), 1);
m.fill(Qt::color0);
fifteenTransparentPixels->setMask(m);
diff --git a/src/qt3support/itemviews/q3iconview.cpp b/src/qt3support/itemviews/q3iconview.cpp
index 67c956e..683e3d6 100644
--- a/src/qt3support/itemviews/q3iconview.cpp
+++ b/src/qt3support/itemviews/q3iconview.cpp
@@ -132,14 +132,21 @@ static QPixmap *qiv_selection = 0;
#endif
static bool optimize_layout = false;
-static Q3CleanupHandler<QPixmap> qiv_cleanup_pixmap;
+static void qt_cleanup_iv_pixmaps();
+typedef QList<QPixmap *> IVPixmaps;
+Q_GLOBAL_STATIC_WITH_INITIALIZER(IVPixmaps, qiv_pixmaps, qAddPostRoutine(qt_cleanup_iv_pixmaps))
+
+static void qt_cleanup_iv_pixmaps()
+{
+ qDeleteAll(*qiv_pixmaps());
+}
static QPixmap *get_qiv_buffer_pixmap(const QSize &s)
{
if (!qiv_buffer_pixmap) {
qiv_buffer_pixmap = new QPixmap(s);
- qiv_cleanup_pixmap.add(&qiv_buffer_pixmap);
+ qiv_pixmaps()->append(qiv_buffer_pixmap);
return qiv_buffer_pixmap;
}
@@ -2580,7 +2587,7 @@ Q3IconView::Q3IconView(QWidget *parent, const char *name, Qt::WindowFlags f)
{
if (!unknown_icon) {
unknown_icon = new QPixmap((const char **)unknown_xpm);
- qiv_cleanup_pixmap.add(&unknown_icon);
+ qiv_pixmaps()->append(unknown_icon);
}
d = new Q3IconViewPrivate;
diff --git a/src/qt3support/itemviews/q3listview.cpp b/src/qt3support/itemviews/q3listview.cpp
index 2c15ad0..12dad84 100644
--- a/src/qt3support/itemviews/q3listview.cpp
+++ b/src/qt3support/itemviews/q3listview.cpp
@@ -70,9 +70,6 @@ QT_BEGIN_NAMESPACE
const int Unsorted = 16383;
-static Q3CleanupHandler<QBitmap> qlv_cleanup_bitmap;
-
-
struct Q3ListViewPrivate
{
// classes that are here to avoid polluting the global name space
diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def
index 155e3e7..4f30cb5 100644
--- a/src/s60installs/bwins/QtGuiu.def
+++ b/src/s60installs/bwins/QtGuiu.def
@@ -2081,8 +2081,8 @@ EXPORTS
?addPixmap@QGraphicsScene@@QAEPAVQGraphicsPixmapItem@@ABVQPixmap@@@Z @ 2080 NONAME ; class QGraphicsPixmapItem * QGraphicsScene::addPixmap(class QPixmap const &)
?addPixmap@QIcon@@QAEXABVQPixmap@@W4Mode@1@W4State@1@@Z @ 2081 NONAME ; void QIcon::addPixmap(class QPixmap const &, enum QIcon::Mode, enum QIcon::State)
?addPixmap@QIconEngine@@UAEXABVQPixmap@@W4Mode@QIcon@@W4State@4@@Z @ 2082 NONAME ; void QIconEngine::addPixmap(class QPixmap const &, enum QIcon::Mode, enum QIcon::State)
- ?addPixmapDestructionHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 2083 NONAME ; void QImagePixmapCleanupHooks::addPixmapDestructionHook(void (*)(class QPixmap *))
- ?addPixmapModificationHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 2084 NONAME ; void QImagePixmapCleanupHooks::addPixmapModificationHook(void (*)(class QPixmap *))
+ ?addPixmapDestructionHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 2083 NONAME ABSENT ; void QImagePixmapCleanupHooks::addPixmapDestructionHook(void (*)(class QPixmap *))
+ ?addPixmapModificationHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 2084 NONAME ABSENT ; void QImagePixmapCleanupHooks::addPixmapModificationHook(void (*)(class QPixmap *))
?addPolygon@QGraphicsScene@@QAEPAVQGraphicsPolygonItem@@ABVQPolygonF@@ABVQPen@@ABVQBrush@@@Z @ 2085 NONAME ; class QGraphicsPolygonItem * QGraphicsScene::addPolygon(class QPolygonF const &, class QPen const &, class QBrush const &)
?addPolygon@QPainterPath@@QAEXABVQPolygonF@@@Z @ 2086 NONAME ; void QPainterPath::addPolygon(class QPolygonF const &)
?addRect@QGraphicsScene@@QAEPAVQGraphicsRectItem@@ABVQRectF@@ABVQPen@@ABVQBrush@@@Z @ 2087 NONAME ; class QGraphicsRectItem * QGraphicsScene::addRect(class QRectF const &, class QPen const &, class QBrush const &)
@@ -4283,8 +4283,8 @@ EXPORTS
?executeDelayedItemsLayout@QAbstractItemView@@IAEXXZ @ 4282 NONAME ; void QAbstractItemView::executeDelayedItemsLayout(void)
?executeImageHooks@QImagePixmapCleanupHooks@@SAX_J@Z @ 4283 NONAME ; void QImagePixmapCleanupHooks::executeImageHooks(long long)
?executePendingSort@QTreeWidgetItem@@ABEXXZ @ 4284 NONAME ; void QTreeWidgetItem::executePendingSort(void) const
- ?executePixmapDestructionHooks@QImagePixmapCleanupHooks@@SAXPAVQPixmap@@@Z @ 4285 NONAME ; void QImagePixmapCleanupHooks::executePixmapDestructionHooks(class QPixmap *)
- ?executePixmapModificationHooks@QImagePixmapCleanupHooks@@SAXPAVQPixmap@@@Z @ 4286 NONAME ; void QImagePixmapCleanupHooks::executePixmapModificationHooks(class QPixmap *)
+ ?executePixmapDestructionHooks@QImagePixmapCleanupHooks@@SAXPAVQPixmap@@@Z @ 4285 NONAME ABSENT ; void QImagePixmapCleanupHooks::executePixmapDestructionHooks(class QPixmap *)
+ ?executePixmapModificationHooks@QImagePixmapCleanupHooks@@SAXPAVQPixmap@@@Z @ 4286 NONAME ABSENT ; void QImagePixmapCleanupHooks::executePixmapModificationHooks(class QPixmap *)
?expand@QTreeView@@QAEXABVQModelIndex@@@Z @ 4287 NONAME ; void QTreeView::expand(class QModelIndex const &)
?expandAll@QTreeView@@QAEXXZ @ 4288 NONAME ; void QTreeView::expandAll(void)
?expandItem@QTreeWidget@@QAEXPBVQTreeWidgetItem@@@Z @ 4289 NONAME ; void QTreeWidget::expandItem(class QTreeWidgetItem const *)
@@ -7927,8 +7927,8 @@ EXPORTS
?removeItemWidget@QTreeWidget@@QAEXPAVQTreeWidgetItem@@H@Z @ 7926 NONAME ; void QTreeWidget::removeItemWidget(class QTreeWidgetItem *, int)
?removeMapping@QDataWidgetMapper@@QAEXPAVQWidget@@@Z @ 7927 NONAME ; void QDataWidgetMapper::removeMapping(class QWidget *)
?removePage@QWizard@@QAEXH@Z @ 7928 NONAME ; void QWizard::removePage(int)
- ?removePixmapDestructionHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 7929 NONAME ; void QImagePixmapCleanupHooks::removePixmapDestructionHook(void (*)(class QPixmap *))
- ?removePixmapModificationHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 7930 NONAME ; void QImagePixmapCleanupHooks::removePixmapModificationHook(void (*)(class QPixmap *))
+ ?removePixmapDestructionHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 7929 NONAME ABSENT ; void QImagePixmapCleanupHooks::removePixmapDestructionHook(void (*)(class QPixmap *))
+ ?removePixmapModificationHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmap@@@Z@Z @ 7930 NONAME ABSENT ; void QImagePixmapCleanupHooks::removePixmapModificationHook(void (*)(class QPixmap *))
?removeRow@QStandardItem@@QAEXH@Z @ 7931 NONAME ; void QStandardItem::removeRow(int)
?removeRow@QTableWidget@@QAEXH@Z @ 7932 NONAME ; void QTableWidget::removeRow(int)
?removeRows@QSortFilterProxyModel@@UAE_NHHABVQModelIndex@@@Z @ 7933 NONAME ; bool QSortFilterProxyModel::removeRows(int, int, class QModelIndex const &)
@@ -12533,4 +12533,72 @@ EXPORTS
?symbianHandleCommand@QApplicationPrivate@@QAEHPBVQSymbianEvent@@@Z @ 12532 NONAME ; int QApplicationPrivate::symbianHandleCommand(class QSymbianEvent const *)
?symbianProcessWsEvent@QApplicationPrivate@@QAEHPBVQSymbianEvent@@@Z @ 12533 NONAME ; int QApplicationPrivate::symbianProcessWsEvent(class QSymbianEvent const *)
?symbianResourceChange@QApplicationPrivate@@QAEHPBVQSymbianEvent@@@Z @ 12534 NONAME ; int QApplicationPrivate::symbianResourceChange(class QSymbianEvent const *)
+ ?addPixmapDataDestructionHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmapData@@@Z@Z @ 12535 NONAME ; void QImagePixmapCleanupHooks::addPixmapDataDestructionHook(void (*)(class QPixmapData *))
+ ?addPixmapDataModificationHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmapData@@@Z@Z @ 12536 NONAME ; void QImagePixmapCleanupHooks::addPixmapDataModificationHook(void (*)(class QPixmapData *))
+ ?cacheKey@QPixmapData@@QBE_JXZ @ 12537 NONAME ; long long QPixmapData::cacheKey(void) const
+ ?eventFilter@QS60Style@@MAE_NPAVQObject@@PAVQEvent@@@Z @ 12538 NONAME ; bool QS60Style::eventFilter(class QObject *, class QEvent *)
+ ?executePixmapDataDestructionHooks@QImagePixmapCleanupHooks@@SAXPAVQPixmapData@@@Z @ 12539 NONAME ; void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(class QPixmapData *)
+ ?executePixmapDataModificationHooks@QImagePixmapCleanupHooks@@SAXPAVQPixmapData@@@Z @ 12540 NONAME ; void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(class QPixmapData *)
+ ?invalidateChildGraphicsEffectsRecursively@QGraphicsItemPrivate@@QAEXW4InvalidateReason@1@@Z @ 12541 NONAME ; void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(enum QGraphicsItemPrivate::InvalidateReason)
+ ?invalidateParentGraphicsEffectsRecursively@QGraphicsItemPrivate@@QAEXXZ @ 12542 NONAME ; void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively(void)
+ ?markParentDirty@QGraphicsItemPrivate@@QAEX_N@Z @ 12543 NONAME ; void QGraphicsItemPrivate::markParentDirty(bool)
+ ?removePixmapDataDestructionHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmapData@@@Z@Z @ 12544 NONAME ; void QImagePixmapCleanupHooks::removePixmapDataDestructionHook(void (*)(class QPixmapData *))
+ ?removePixmapDataModificationHook@QImagePixmapCleanupHooks@@QAEXP6AXPAVQPixmapData@@@Z@Z @ 12545 NONAME ; void QImagePixmapCleanupHooks::removePixmapDataModificationHook(void (*)(class QPixmapData *))
+ ?setParentItemHelper@QGraphicsItemPrivate@@QAEXPAVQGraphicsItem@@PBVQVariant@@1@Z @ 12546 NONAME ; void QGraphicsItemPrivate::setParentItemHelper(class QGraphicsItem *, class QVariant const *, class QVariant const *)
+ ?timerEvent@QS60Style@@MAEXPAVQTimerEvent@@@Z @ 12547 NONAME ; void QS60Style::timerEvent(class QTimerEvent *)
+ ?updateAncestorFlags@QGraphicsItemPrivate@@QAEXXZ @ 12548 NONAME ; void QGraphicsItemPrivate::updateAncestorFlags(void)
+ ?updateChildWithGraphicsEffectFlagRecursively@QGraphicsItemPrivate@@QAEXXZ @ 12549 NONAME ; void QGraphicsItemPrivate::updateChildWithGraphicsEffectFlagRecursively(void)
+ ?isOpacityNull@QGraphicsItemPrivate@@SA_NM@Z @ 12550 NONAME ; bool QGraphicsItemPrivate::isOpacityNull(float)
+ ?isOpacityNull@QGraphicsItemPrivate@@QBE_NXZ @ 12551 NONAME ; bool QGraphicsItemPrivate::isOpacityNull(void) const
+ ?api@QEglContext@@QBE?AW4API@QEgl@@XZ @ 12552 NONAME ABSENT ; enum QEgl::API QEglContext::api(void) const
+ ?chooseConfig@QEglContext@@QAE_NABVQEglProperties@@W4PixelFormatMatch@QEgl@@@Z @ 12553 NONAME ABSENT ; bool QEglContext::chooseConfig(class QEglProperties const &, enum QEgl::PixelFormatMatch)
+ ?destroySurface@QEglContext@@QAEXH@Z @ 12554 NONAME ABSENT ; void QEglContext::destroySurface(int)
+ ?lazyDoneCurrent@QEglContext@@QAE_NXZ @ 12555 NONAME ABSENT ; bool QEglContext::lazyDoneCurrent(void)
+ ?waitNative@QEglContext@@QAEXXZ @ 12556 NONAME ABSENT ; void QEglContext::waitNative(void)
+ ?context@QEglContext@@QBEHXZ @ 12557 NONAME ABSENT ; int QEglContext::context(void) const
+ ?configAttrib@QEglContext@@QBE_NHPAH@Z @ 12558 NONAME ABSENT ; bool QEglContext::configAttrib(int, int *) const
+ ??0QEglProperties@@QAE@ABV0@@Z @ 12559 NONAME ABSENT ; QEglProperties::QEglProperties(class QEglProperties const &)
+ ?config@QEglContext@@QBEHXZ @ 12560 NONAME ABSENT ; int QEglContext::config(void) const
+ ?openDisplay@QEglContext@@QAE_NPAVQPaintDevice@@@Z @ 12561 NONAME ABSENT ; bool QEglContext::openDisplay(class QPaintDevice *)
+ ?error@QEglContext@@SAHXZ @ 12562 NONAME ABSENT ; int QEglContext::error(void)
+ ?swapBuffers@QEglContext@@QAE_NH@Z @ 12563 NONAME ABSENT ; bool QEglContext::swapBuffers(int)
+ ?setApi@QEglContext@@QAEXW4API@QEgl@@@Z @ 12564 NONAME ABSENT ; void QEglContext::setApi(enum QEgl::API)
+ ?makeCurrent@QEglContext@@QAE_NH@Z @ 12565 NONAME ABSENT ; bool QEglContext::makeCurrent(int)
+ ?createSurface@QEglContext@@QAEHPAVQPaintDevice@@PBVQEglProperties@@@Z @ 12566 NONAME ABSENT ; int QEglContext::createSurface(class QPaintDevice *, class QEglProperties const *)
+ ?dumpAllConfigs@QEglContext@@QAEXXZ @ 12567 NONAME ABSENT ; void QEglContext::dumpAllConfigs(void)
+ ?reduceConfiguration@QEglProperties@@QAE_NXZ @ 12568 NONAME ABSENT ; bool QEglProperties::reduceConfiguration(void)
+ ?removeValue@QEglProperties@@QAE_NH@Z @ 12569 NONAME ABSENT ; bool QEglProperties::removeValue(int)
+ ?toString@QEglProperties@@QBE?AVQString@@XZ @ 12570 NONAME ABSENT ; class QString QEglProperties::toString(void) const
+ ?dumpAllConfigs@QEglProperties@@SAXXZ @ 12571 NONAME ABSENT ; void QEglProperties::dumpAllConfigs(void)
+ ?defaultDisplay@QEglContext@@SAHPAVQPaintDevice@@@Z @ 12572 NONAME ABSENT ; int QEglContext::defaultDisplay(class QPaintDevice *)
+ ?configProperties@QEglContext@@QBE?AVQEglProperties@@H@Z @ 12573 NONAME ABSENT ; class QEglProperties QEglContext::configProperties(int) const
+ ?properties@QEglProperties@@QBEPBHXZ @ 12574 NONAME ABSENT ; int const * QEglProperties::properties(void) const
+ ??0QEglContext@@QAE@XZ @ 12575 NONAME ABSENT ; QEglContext::QEglContext(void)
+ ??1QEglContext@@QAE@XZ @ 12576 NONAME ABSENT ; QEglContext::~QEglContext(void)
+ ?isValid@QEglContext@@QBE_NXZ @ 12577 NONAME ABSENT ; bool QEglContext::isValid(void) const
+ ?value@QEglProperties@@QBEHH@Z @ 12578 NONAME ABSENT ; int QEglProperties::value(int) const
+ ?clearError@QEglContext@@SAXXZ @ 12579 NONAME ABSENT ; void QEglContext::clearError(void)
+ ??0QEglProperties@@QAE@H@Z @ 12580 NONAME ABSENT ; QEglProperties::QEglProperties(int)
+ ?setValue@QEglProperties@@QAEXHH@Z @ 12581 NONAME ABSENT ; void QEglProperties::setValue(int, int)
+ ?setPaintDeviceFormat@QEglProperties@@QAEXPAVQPaintDevice@@@Z @ 12582 NONAME ABSENT ; void QEglProperties::setPaintDeviceFormat(class QPaintDevice *)
+ ?destroy@QEglContext@@QAEXXZ @ 12583 NONAME ABSENT ; void QEglContext::destroy(void)
+ ?setRenderableType@QEglProperties@@QAEXW4API@QEgl@@@Z @ 12584 NONAME ABSENT ; void QEglProperties::setRenderableType(enum QEgl::API)
+ ?setContext@QEglContext@@QAEXH@Z @ 12585 NONAME ABSENT ; void QEglContext::setContext(int)
+ ?waitClient@QEglContext@@QAEXXZ @ 12586 NONAME ABSENT ; void QEglContext::waitClient(void)
+ ?isEmpty@QEglProperties@@QBE_NXZ @ 12587 NONAME ABSENT ; bool QEglProperties::isEmpty(void) const
+ ?getDisplay@QEglContext@@CAHPAVQPaintDevice@@@Z @ 12588 NONAME ABSENT ; int QEglContext::getDisplay(class QPaintDevice *)
+ ?isSharing@QEglContext@@QBE_NXZ @ 12589 NONAME ABSENT ; bool QEglContext::isSharing(void) const
+ ?isCurrent@QEglContext@@QBE_NXZ @ 12590 NONAME ABSENT ; bool QEglContext::isCurrent(void) const
+ ??0QEglProperties@@QAE@XZ @ 12591 NONAME ABSENT ; QEglProperties::QEglProperties(void)
+ ?extensions@QEglContext@@SA?AVQString@@XZ @ 12592 NONAME ABSENT ; class QString QEglContext::extensions(void)
+ ?setCurrentContext@QEglContext@@CAXW4API@QEgl@@PAV1@@Z @ 12593 NONAME ABSENT ; void QEglContext::setCurrentContext(enum QEgl::API, class QEglContext *)
+ ??1QEglProperties@@QAE@XZ @ 12594 NONAME ABSENT ; QEglProperties::~QEglProperties(void)
+ ?createContext@QEglContext@@QAE_NPAV1@PBVQEglProperties@@@Z @ 12595 NONAME ABSENT ; bool QEglContext::createContext(class QEglContext *, class QEglProperties const *)
+ ?setConfig@QEglContext@@QAEXH@Z @ 12596 NONAME ABSENT ; void QEglContext::setConfig(int)
+ ?hasExtension@QEglContext@@SA_NPBD@Z @ 12597 NONAME ABSENT ; bool QEglContext::hasExtension(char const *)
+ ?doneCurrent@QEglContext@@QAE_NXZ @ 12598 NONAME ABSENT ; bool QEglContext::doneCurrent(void)
+ ?display@QEglContext@@QBEHXZ @ 12599 NONAME ABSENT ; int QEglContext::display(void) const
+ ?setPixelFormat@QEglProperties@@QAEXW4Format@QImage@@@Z @ 12600 NONAME ABSENT ; void QEglProperties::setPixelFormat(enum QImage::Format)
+ ?currentContext@QEglContext@@CAPAV1@W4API@QEgl@@@Z @ 12601 NONAME ABSENT ; class QEglContext * QEglContext::currentContext(enum QEgl::API)
+ ?errorString@QEglContext@@SA?AVQString@@H@Z @ 12602 NONAME ABSENT ; class QString QEglContext::errorString(int)
diff --git a/src/s60installs/bwins/QtOpenVGu.def b/src/s60installs/bwins/QtOpenVGu.def
index 88e724f..26ee862 100644
--- a/src/s60installs/bwins/QtOpenVGu.def
+++ b/src/s60installs/bwins/QtOpenVGu.def
@@ -48,7 +48,7 @@ EXPORTS
?paintEngine@QVGWindowSurface@@UBEPAVQPaintEngine@@XZ @ 47 NONAME ; class QPaintEngine * QVGWindowSurface::paintEngine(void) const
??0QVGPainterState@@QAE@XZ @ 48 NONAME ; QVGPainterState::QVGPainterState(void)
?d_func@QVGPaintEngine@@ABEPBVQVGPaintEnginePrivate@@XZ @ 49 NONAME ; class QVGPaintEnginePrivate const * QVGPaintEngine::d_func(void) const
- ?qt_vg_create_context@@YAPAVQEglContext@@PAVQPaintDevice@@@Z @ 50 NONAME ; class QEglContext * qt_vg_create_context(class QPaintDevice *)
+ ?qt_vg_create_context@@YAPAVQEglContext@@PAVQPaintDevice@@@Z @ 50 NONAME ABSENT ; class QEglContext * qt_vg_create_context(class QPaintDevice *)
?clip@QVGPaintEngine@@UAEXABVQRegion@@W4ClipOperation@Qt@@@Z @ 51 NONAME ; void QVGPaintEngine::clip(class QRegion const &, enum Qt::ClipOperation)
?endNativePainting@QVGPaintEngine@@UAEXXZ @ 52 NONAME ; void QVGPaintEngine::endNativePainting(void)
?brushChanged@QVGPaintEngine@@UAEXXZ @ 53 NONAME ; void QVGPaintEngine::brushChanged(void)
@@ -78,7 +78,7 @@ EXPORTS
?beginPaint@QVGEGLWindowSurfaceVGImage@@UAEXPAVQWidget@@@Z @ 77 NONAME ; void QVGEGLWindowSurfaceVGImage::beginPaint(class QWidget *)
?createState@QVGPaintEngine@@UBEPAVQPainterState@@PAV2@@Z @ 78 NONAME ; class QPainterState * QVGPaintEngine::createState(class QPainterState *) const
?buffer@QVGPixmapData@@UAEPAVQImage@@XZ @ 79 NONAME ; class QImage * QVGPixmapData::buffer(void)
- ?qt_vg_destroy_context@@YAXPAVQEglContext@@@Z @ 80 NONAME ; void qt_vg_destroy_context(class QEglContext *)
+ ?qt_vg_destroy_context@@YAXPAVQEglContext@@@Z @ 80 NONAME ABSENT ; void qt_vg_destroy_context(class QEglContext *)
?clip@QVGPaintEngine@@UAEXABVQVectorPath@@W4ClipOperation@Qt@@@Z @ 81 NONAME ; void QVGPaintEngine::clip(class QVectorPath const &, enum Qt::ClipOperation)
?drawPolygon@QVGPaintEngine@@UAEXPBVQPoint@@HW4PolygonDrawMode@QPaintEngine@@@Z @ 82 NONAME ; void QVGPaintEngine::drawPolygon(class QPoint const *, int, enum QPaintEngine::PolygonDrawMode)
?fromImage@QVGPixmapData@@UAEXABVQImage@@V?$QFlags@W4ImageConversionFlag@Qt@@@@@Z @ 83 NONAME ; void QVGPixmapData::fromImage(class QImage const &, class QFlags<enum Qt::ImageConversionFlag>)
@@ -139,4 +139,29 @@ EXPORTS
??_EQVGPaintEngine@@UAE@I@Z @ 138 NONAME ; QVGPaintEngine::~QVGPaintEngine(unsigned int)
?clip@QVGPaintEngine@@UAEXABVQPainterPath@@W4ClipOperation@Qt@@@Z @ 139 NONAME ; void QVGPaintEngine::clip(class QPainterPath const &, enum Qt::ClipOperation)
?vgPrivate@QVGPaintEngine@@QAEPAVQVGPaintEnginePrivate@@XZ @ 140 NONAME ; class QVGPaintEnginePrivate * QVGPaintEngine::vgPrivate(void)
+ ?removeFromLRU@QVGImagePool@@IAEXPAVQVGPixmapData@@@Z @ 141 NONAME ; void QVGImagePool::removeFromLRU(class QVGPixmapData *)
+ ?releaseImage@QVGImagePool@@UAEXPAVQVGPixmapData@@K@Z @ 142 NONAME ; void QVGImagePool::releaseImage(class QVGPixmapData *, unsigned long)
+ ?d_func@QVGImagePool@@AAEPAVQVGImagePoolPrivate@@XZ @ 143 NONAME ; class QVGImagePoolPrivate * QVGImagePool::d_func(void)
+ ?detachImageFromPool@QVGPixmapData@@UAEXXZ @ 144 NONAME ; void QVGPixmapData::detachImageFromPool(void)
+ ?createImageForPixmap@QVGImagePool@@UAEKW4VGImageFormat@@JJKPAVQVGPixmapData@@@Z @ 145 NONAME ; unsigned long QVGImagePool::createImageForPixmap(enum VGImageFormat, long, long, unsigned long, class QVGPixmapData *)
+ ?destroyImageAndContext@QVGPixmapData@@IAEXXZ @ 146 NONAME ; void QVGPixmapData::destroyImageAndContext(void)
+ ?moveToHeadOfLRU@QVGImagePool@@IAEXPAVQVGPixmapData@@@Z @ 147 NONAME ; void QVGImagePool::moveToHeadOfLRU(class QVGPixmapData *)
+ ?instance@QVGImagePool@@SAPAV1@XZ @ 148 NONAME ; class QVGImagePool * QVGImagePool::instance(void)
+ ?useImage@QVGImagePool@@UAEXPAVQVGPixmapData@@@Z @ 149 NONAME ; void QVGImagePool::useImage(class QVGPixmapData *)
+ ??1QVGImagePool@@UAE@XZ @ 150 NONAME ; QVGImagePool::~QVGImagePool(void)
+ ?destroyImages@QVGPixmapData@@IAEXXZ @ 151 NONAME ; void QVGPixmapData::destroyImages(void)
+ ?reclaimSpace@QVGImagePool@@UAE_NW4VGImageFormat@@JJPAVQVGPixmapData@@@Z @ 152 NONAME ; bool QVGImagePool::reclaimSpace(enum VGImageFormat, long, long, class QVGPixmapData *)
+ ?detachImage@QVGImagePool@@UAEXPAVQVGPixmapData@@@Z @ 153 NONAME ; void QVGImagePool::detachImage(class QVGPixmapData *)
+ ?createPermanentImage@QVGImagePool@@UAEKW4VGImageFormat@@JJK@Z @ 154 NONAME ; unsigned long QVGImagePool::createPermanentImage(enum VGImageFormat, long, long, unsigned long)
+ ?d_func@QVGImagePool@@ABEPBVQVGImagePoolPrivate@@XZ @ 155 NONAME ; class QVGImagePoolPrivate const * QVGImagePool::d_func(void) const
+ ?createTemporaryImage@QVGImagePool@@UAEKW4VGImageFormat@@JJKPAVQVGPixmapData@@@Z @ 156 NONAME ; unsigned long QVGImagePool::createTemporaryImage(enum VGImageFormat, long, long, unsigned long, class QVGPixmapData *)
+ ??_EQVGImagePool@@UAE@I@Z @ 157 NONAME ; QVGImagePool::~QVGImagePool(unsigned int)
+ ?hibernate@QVGImagePool@@UAEXXZ @ 158 NONAME ; void QVGImagePool::hibernate(void)
+ ?qt_vg_destroy_context@@YAXPAVQEglContext@@H@Z @ 159 NONAME ; void qt_vg_destroy_context(class QEglContext *, int)
+ ??0QVGImagePool@@QAE@XZ @ 160 NONAME ; QVGImagePool::QVGImagePool(void)
+ ?setImagePool@QVGImagePool@@SAXPAV1@@Z @ 161 NONAME ; void QVGImagePool::setImagePool(class QVGImagePool *)
+ ?pixmapLRU@QVGImagePool@@IAEPAVQVGPixmapData@@XZ @ 162 NONAME ; class QVGPixmapData * QVGImagePool::pixmapLRU(void)
+ ?qt_vg_create_context@@YAPAVQEglContext@@PAVQPaintDevice@@H@Z @ 163 NONAME ; class QEglContext * qt_vg_create_context(class QPaintDevice *, int)
+ ?reclaimImages@QVGPixmapData@@UAEXXZ @ 164 NONAME ; void QVGPixmapData::reclaimImages(void)
+ ?hibernate@QVGPixmapData@@UAEXXZ @ 165 NONAME ; void QVGPixmapData::hibernate(void)
diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def
index a9a69aa..5cf700b 100644
--- a/src/s60installs/eabi/QtGuiu.def
+++ b/src/s60installs/eabi/QtGuiu.def
@@ -11648,12 +11648,12 @@ EXPORTS
_ZN24QImagePixmapCleanupHooks18enableCleanupHooksEP11QPixmapData @ 11647 NONAME
_ZN24QImagePixmapCleanupHooks18enableCleanupHooksERK6QImage @ 11648 NONAME
_ZN24QImagePixmapCleanupHooks18enableCleanupHooksERK7QPixmap @ 11649 NONAME
- _ZN24QImagePixmapCleanupHooks24addPixmapDestructionHookEPFvP7QPixmapE @ 11650 NONAME
- _ZN24QImagePixmapCleanupHooks25addPixmapModificationHookEPFvP7QPixmapE @ 11651 NONAME
- _ZN24QImagePixmapCleanupHooks27removePixmapDestructionHookEPFvP7QPixmapE @ 11652 NONAME
- _ZN24QImagePixmapCleanupHooks28removePixmapModificationHookEPFvP7QPixmapE @ 11653 NONAME
- _ZN24QImagePixmapCleanupHooks29executePixmapDestructionHooksEP7QPixmap @ 11654 NONAME
- _ZN24QImagePixmapCleanupHooks30executePixmapModificationHooksEP7QPixmap @ 11655 NONAME
+ _ZN24QImagePixmapCleanupHooks24addPixmapDestructionHookEPFvP7QPixmapE @ 11650 NONAME ABSENT
+ _ZN24QImagePixmapCleanupHooks25addPixmapModificationHookEPFvP7QPixmapE @ 11651 NONAME ABSENT
+ _ZN24QImagePixmapCleanupHooks27removePixmapDestructionHookEPFvP7QPixmapE @ 11652 NONAME ABSENT
+ _ZN24QImagePixmapCleanupHooks28removePixmapModificationHookEPFvP7QPixmapE @ 11653 NONAME ABSENT
+ _ZN24QImagePixmapCleanupHooks29executePixmapDestructionHooksEP7QPixmap @ 11654 NONAME ABSENT
+ _ZN24QImagePixmapCleanupHooks30executePixmapModificationHooksEP7QPixmap @ 11655 NONAME ABSENT
_ZN25QGraphicsDropShadowEffect13setBlurRadiusEf @ 11656 NONAME
_ZN25QGraphicsDropShadowEffect17blurRadiusChangedEf @ 11657 NONAME
_ZN25QGraphicsDropShadowEffect4drawEP8QPainter @ 11658 NONAME
@@ -11792,4 +11792,17 @@ EXPORTS
_ZN19QApplicationPrivate20symbianHandleCommandEPK13QSymbianEvent @ 11791 NONAME
_ZN19QApplicationPrivate21symbianProcessWsEventEPK13QSymbianEvent @ 11792 NONAME
_ZN19QApplicationPrivate21symbianResourceChangeEPK13QSymbianEvent @ 11793 NONAME
+ _ZN20QGraphicsItemPrivate19setParentItemHelperEP13QGraphicsItemPK8QVariantS4_ @ 11794 NONAME
+ _ZN20QGraphicsItemPrivate19updateAncestorFlagsEv @ 11795 NONAME
+ _ZN20QGraphicsItemPrivate41invalidateChildGraphicsEffectsRecursivelyENS_16InvalidateReasonE @ 11796 NONAME
+ _ZN20QGraphicsItemPrivate42invalidateParentGraphicsEffectsRecursivelyEv @ 11797 NONAME
+ _ZN20QGraphicsItemPrivate44updateChildWithGraphicsEffectFlagRecursivelyEv @ 11798 NONAME
+ _ZN24QImagePixmapCleanupHooks28addPixmapDataDestructionHookEPFvP11QPixmapDataE @ 11799 NONAME
+ _ZN24QImagePixmapCleanupHooks29addPixmapDataModificationHookEPFvP11QPixmapDataE @ 11800 NONAME
+ _ZN24QImagePixmapCleanupHooks31removePixmapDataDestructionHookEPFvP11QPixmapDataE @ 11801 NONAME
+ _ZN24QImagePixmapCleanupHooks32removePixmapDataModificationHookEPFvP11QPixmapDataE @ 11802 NONAME
+ _ZN24QImagePixmapCleanupHooks33executePixmapDataDestructionHooksEP11QPixmapData @ 11803 NONAME
+ _ZN24QImagePixmapCleanupHooks34executePixmapDataModificationHooksEP11QPixmapData @ 11804 NONAME
+ _ZN9QS60Style10timerEventEP11QTimerEvent @ 11805 NONAME
+ _ZN9QS60Style11eventFilterEP7QObjectP6QEvent @ 11806 NONAME
diff --git a/src/s60installs/eabi/QtOpenVGu.def b/src/s60installs/eabi/QtOpenVGu.def
index 7526632..eb4caef 100644
--- a/src/s60installs/eabi/QtOpenVGu.def
+++ b/src/s60installs/eabi/QtOpenVGu.def
@@ -173,4 +173,27 @@ EXPORTS
_Z21qt_vg_destroy_contextP11QEglContexti @ 172 NONAME
_ZN13QVGPixmapData22destroyImageAndContextEv @ 173 NONAME
_ZN13QVGPixmapData9hibernateEv @ 174 NONAME
+ _ZN12QVGImagePool11detachImageEP13QVGPixmapData @ 175 NONAME
+ _ZN12QVGImagePool12reclaimSpaceE13VGImageFormatllP13QVGPixmapData @ 176 NONAME
+ _ZN12QVGImagePool12releaseImageEP13QVGPixmapDatam @ 177 NONAME
+ _ZN12QVGImagePool12setImagePoolEPS_ @ 178 NONAME
+ _ZN12QVGImagePool13removeFromLRUEP13QVGPixmapData @ 179 NONAME
+ _ZN12QVGImagePool15moveToHeadOfLRUEP13QVGPixmapData @ 180 NONAME
+ _ZN12QVGImagePool20createImageForPixmapE13VGImageFormatllmP13QVGPixmapData @ 181 NONAME
+ _ZN12QVGImagePool20createPermanentImageE13VGImageFormatllm @ 182 NONAME
+ _ZN12QVGImagePool20createTemporaryImageE13VGImageFormatllmP13QVGPixmapData @ 183 NONAME
+ _ZN12QVGImagePool8instanceEv @ 184 NONAME
+ _ZN12QVGImagePool8useImageEP13QVGPixmapData @ 185 NONAME
+ _ZN12QVGImagePool9hibernateEv @ 186 NONAME
+ _ZN12QVGImagePool9pixmapLRUEv @ 187 NONAME
+ _ZN12QVGImagePoolC1Ev @ 188 NONAME
+ _ZN12QVGImagePoolC2Ev @ 189 NONAME
+ _ZN12QVGImagePoolD0Ev @ 190 NONAME
+ _ZN12QVGImagePoolD1Ev @ 191 NONAME
+ _ZN12QVGImagePoolD2Ev @ 192 NONAME
+ _ZN13QVGPixmapData13destroyImagesEv @ 193 NONAME
+ _ZN13QVGPixmapData13reclaimImagesEv @ 194 NONAME
+ _ZN13QVGPixmapData19detachImageFromPoolEv @ 195 NONAME
+ _ZTI12QVGImagePool @ 196 NONAME
+ _ZTV12QVGImagePool @ 197 NONAME
diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby
index bdd668c..a6a96ec 100644
--- a/src/s60installs/qt.iby
+++ b/src/s60installs/qt.iby
@@ -113,6 +113,7 @@ data=\epoc32\data\z\resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin resou
data=\epoc32\data\z\resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin
// Stub sis file
-data=ZSYSTEM\install\qt.sis System\Install\qt.sis
+data=ZSYSTEM\install\qt_stub.sis System\Install\qt_stub.sis
+data=ZSYSTEM\install\qtwebkit_stub.sis System\Install\qtwebkit_stub.sis
#endif // __QT_IBY__
diff --git a/src/s60main/s60main.pro b/src/s60main/s60main.pro
index 47cf020..25fb188 100644
--- a/src/s60main/s60main.pro
+++ b/src/s60main/s60main.pro
@@ -22,6 +22,9 @@ symbian {
# staticlib should not have any lib depencies in s60
# This seems not to work, some hard coded libs are still added as dependency
LIBS =
+
+ # Workaround for abld toolchain problem to make ARMV6 qtmain.lib link with GCCE apps
+ symbian-abld: QMAKE_CXXFLAGS.ARMCC += --dllimport_runtime
} else {
error("$$_FILE_ is intended only for Symbian!")
}
diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp
index 24037e1..ce2fc23 100644
--- a/src/script/bridge/qscriptdeclarativeclass.cpp
+++ b/src/script/bridge/qscriptdeclarativeclass.cpp
@@ -35,7 +35,113 @@
QT_BEGIN_NAMESPACE
+/*!
+\class QScriptDeclarativeClass::Value
+\internal
+\brief The QScriptDeclarativeClass::Value class acts as a container for JavaScript data types.
+
+QScriptDeclarativeClass::Value class is similar to QScriptValue, but it is slightly faster.
+Unlike QScriptValue, however, Value instances cannot be stored as they may not survive garbage
+collection. If you need to store a Value, convert it to a QScriptValue and store that.
+*/
+
+QScriptDeclarativeClass::Value::Value()
+{
+ new (this) JSC::JSValue(JSC::jsUndefined());
+}
+
+QScriptDeclarativeClass::Value::Value(const Value &other)
+{
+ new (this) JSC::JSValue((JSC::JSValue &)other);
+}
+
+static QScriptDeclarativeClass::Value jscToValue(const JSC::JSValue &val)
+{
+ return QScriptDeclarativeClass::Value((QScriptDeclarativeClass::Value &)val);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, int value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, uint value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, bool value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, double value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, float value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QString &value)
+{
+ new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::frameForContext(ctxt), value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QScriptValue &value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(ctxt->engine())->scriptValueToJSCValue(value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, int value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, uint value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, bool value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, double value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, float value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QString &value)
+{
+ new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::get(eng)->currentFrame, value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QScriptValue &value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->scriptValueToJSCValue(value));
+}
+
+QScriptDeclarativeClass::Value::~Value()
+{
+ ((JSC::JSValue *)(this))->~JSValue();
+}
+
+QScriptValue QScriptDeclarativeClass::Value::toScriptValue(QScriptEngine *engine) const
+{
+ return QScriptEnginePrivate::get(engine)->scriptValueFromJSCValue((JSC::JSValue &)*this);
+}
+
QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier()
+: identifier(0)
{
new (&d) JSC::Identifier();
}
@@ -82,6 +188,22 @@ QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine,
return p->scriptValueFromJSCValue(result);
}
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::newObjectValue(QScriptEngine *engine,
+ QScriptDeclarativeClass *scriptClass,
+ Object *object)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(scriptClass);
+
+ QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
+
+ JSC::ExecState* exec = p->currentFrame;
+ QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
+ result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
+ return jscToValue(JSC::JSValue(result));
+}
+
QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v)
{
QScriptValuePrivate *d = QScriptValuePrivate::get(v);
@@ -151,6 +273,53 @@ QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Iden
return QScriptValue();
}
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::functionValue(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return Value();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::JSObject *object = d->jscValue.getObject();
+ JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+ JSC::JSValue result;
+
+ JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+ if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+ result = slot.getValue(exec, id);
+ if (QScript::isFunction(result))
+ return jscToValue(result);
+ }
+
+ return Value();
+}
+
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::propertyValue(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return Value();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::JSObject *object = d->jscValue.getObject();
+ JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+ JSC::JSValue result;
+
+ JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+ if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+ result = slot.getValue(exec, id);
+ return jscToValue(result);
+ }
+
+ return Value();
+}
+
/*
Returns the scope chain entry at \a index. If index is less than 0, returns
entries starting at the end. For example, scopeChainValue(context, -1) will return
@@ -241,6 +410,16 @@ QScriptEngine *QScriptDeclarativeClass::engine() const
return d_ptr->engine;
}
+bool QScriptDeclarativeClass::supportsCall() const
+{
+ return d_ptr->supportsCall;
+}
+
+void QScriptDeclarativeClass::setSupportsCall(bool c)
+{
+ d_ptr->supportsCall = c;
+}
+
QScriptDeclarativeClass::PersistentIdentifier
QScriptDeclarativeClass::createPersistentIdentifier(const QString &str)
{
@@ -290,11 +469,12 @@ QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name,
return 0;
}
-QScriptValue QScriptDeclarativeClass::property(Object *object, const Identifier &name)
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::property(Object *object, const Identifier &name)
{
Q_UNUSED(object);
Q_UNUSED(name);
- return QScriptValue();
+ return Value();
}
void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name,
@@ -313,6 +493,14 @@ QScriptDeclarativeClass::propertyFlags(Object *object, const Identifier &name)
return 0;
}
+QScriptDeclarativeClass::Value QScriptDeclarativeClass::call(Object *object,
+ QScriptContext *ctxt)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(ctxt);
+ return Value();
+}
+
QStringList QScriptDeclarativeClass::propertyNames(Object *object)
{
Q_UNUSED(object);
diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h
index d28a371..a0fd6d5 100644
--- a/src/script/bridge/qscriptdeclarativeclass_p.h
+++ b/src/script/bridge/qscriptdeclarativeclass_p.h
@@ -47,16 +47,47 @@ class QScriptContext;
class Q_SCRIPT_EXPORT QScriptDeclarativeClass
{
public:
+#define QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE
+ class Q_SCRIPT_EXPORT Value
+ {
+ public:
+ Value();
+ Value(const Value &);
+
+ Value(QScriptContext *, int);
+ Value(QScriptContext *, uint);
+ Value(QScriptContext *, bool);
+ Value(QScriptContext *, double);
+ Value(QScriptContext *, float);
+ Value(QScriptContext *, const QString &);
+ Value(QScriptContext *, const QScriptValue &);
+ Value(QScriptEngine *, int);
+ Value(QScriptEngine *, uint);
+ Value(QScriptEngine *, bool);
+ Value(QScriptEngine *, double);
+ Value(QScriptEngine *, float);
+ Value(QScriptEngine *, const QString &);
+ Value(QScriptEngine *, const QScriptValue &);
+ ~Value();
+
+ QScriptValue toScriptValue(QScriptEngine *) const;
+ private:
+ char dummy[8];
+ };
+
typedef void* Identifier;
struct Object { virtual ~Object() {} };
static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object *);
+ static Value newObjectValue(QScriptEngine *, QScriptDeclarativeClass *, Object *);
static QScriptDeclarativeClass *scriptClass(const QScriptValue &);
static Object *object(const QScriptValue &);
static QScriptValue function(const QScriptValue &, const Identifier &);
static QScriptValue property(const QScriptValue &, const Identifier &);
+ static Value functionValue(const QScriptValue &, const Identifier &);
+ static Value propertyValue(const QScriptValue &, const Identifier &);
static QScriptValue scopeChainValue(QScriptContext *, int index);
static QScriptContext *pushCleanContext(QScriptEngine *);
@@ -82,6 +113,9 @@ public:
QScriptEngine *engine() const;
+ bool supportsCall() const;
+ void setSupportsCall(bool);
+
PersistentIdentifier createPersistentIdentifier(const QString &);
PersistentIdentifier createPersistentIdentifier(const Identifier &);
@@ -91,9 +125,10 @@ public:
virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
QScriptClass::QueryFlags flags);
- virtual QScriptValue property(Object *, const Identifier &);
+ virtual Value property(Object *, const Identifier &);
virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
virtual QScriptValue::PropertyFlags propertyFlags(Object *, const Identifier &);
+ virtual Value call(Object *, QScriptContext *);
virtual QStringList propertyNames(Object *);
diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp
index aecb09a..c6ab6a7 100644
--- a/src/script/bridge/qscriptdeclarativeobject.cpp
+++ b/src/script/bridge/qscriptdeclarativeobject.cpp
@@ -74,9 +74,9 @@ bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object,
QScriptClass::QueryFlags flags =
m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess);
if (flags & QScriptClass::HandlesReadAccess) {
- QScriptValue value = m_class->property(m_object, identifier);
+ QScriptDeclarativeClass::Value val = m_class->property(m_object, identifier);
p->context = 0;
- slot.setValue(engine->scriptValueToJSCValue(value));
+ slot.setValue((const JSC::JSValue &)val);
return true;
}
p->context = 0;
@@ -155,7 +155,36 @@ void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::
JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData)
{
- return QScriptObjectDelegate::getCallData(object, callData);
+ if (!QScriptDeclarativeClassPrivate::get(m_class)->supportsCall)
+ return JSC::CallTypeNone;
+ callData.native.function = call;
+ return JSC::CallTypeHost;
+}
+
+JSC::JSValue DeclarativeObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ if (!callee->inherits(&QScriptObject::info))
+ return JSC::throwError(exec, JSC::TypeError, "callee is not a DeclarativeObject object");
+ QScriptObject *obj = static_cast<QScriptObject*>(callee);
+ QScriptObjectDelegate *delegate = obj->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return JSC::throwError(exec, JSC::TypeError, "callee is not a DeclarativeObject object");
+
+ QScriptDeclarativeClass *scriptClass = static_cast<DeclarativeObjectDelegate*>(delegate)->m_class;
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+
+ JSC::ExecState *oldFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, thisValue, args, callee);
+ QScriptContext *ctxt = eng_p->contextForFrame(eng_p->currentFrame);
+
+ QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj);
+ QScriptDeclarativeClass::Value result =
+ scriptClass->call(static_cast<DeclarativeObjectDelegate*>(delegate)->m_object, ctxt);
+
+ eng_p->popContext();
+ eng_p->currentFrame = oldFrame;
+ return (JSC::JSValue &)(result);
}
JSC::ConstructType DeclarativeObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData &constructData)
diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h
index d5bf673..ec8a43e 100644
--- a/src/script/bridge/qscriptdeclarativeobject_p.h
+++ b/src/script/bridge/qscriptdeclarativeobject_p.h
@@ -48,11 +48,12 @@ class QScriptClass;
class QScriptDeclarativeClassPrivate
{
public:
- QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0), context(0) {}
+ QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0), context(0), supportsCall(false) {}
QScriptEngine *engine;
QScriptDeclarativeClass *q_ptr;
QScriptContext *context;
+ bool supportsCall:1;
static QScriptDeclarativeClassPrivate *get(QScriptDeclarativeClass *c) {
return c->d_ptr.data();
@@ -90,6 +91,9 @@ public:
bool includeNonEnumerable = false);
virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&);
+ static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*,
+ JSC::JSValue, const JSC::ArgList&);
+
virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&);
virtual bool hasInstance(QScriptObject*, JSC::ExecState*,
diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp
index 9fff552..d3be304 100644
--- a/src/sql/drivers/sqlite/qsql_sqlite.cpp
+++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp
@@ -500,32 +500,6 @@ bool QSQLiteDriver::hasFeature(DriverFeature f) const
return false;
}
-static int qGetSqliteTimeout(QString opts)
-{
- enum { DefaultTimeout = 5000 };
-
- opts.remove(QLatin1Char(' '));
- foreach(QString option, opts.split(QLatin1Char(';'))) {
- if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
- bool ok;
- int nt = option.mid(21).toInt(&ok);
- if (ok)
- return nt;
- }
- }
- return DefaultTimeout;
-}
-
-static int qGetSqliteOpenMode(QString opts)
-{
- opts.remove(QLatin1Char(' '));
- foreach(QString option, opts.split(QLatin1Char(';'))) {
- if (option == QLatin1String("QSQLITE_OPEN_READONLY"))
- return SQLITE_OPEN_READONLY;
- }
- return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
-}
-
/*
SQLite dbs have no user name, passwords, hosts or ports.
just file names.
@@ -537,9 +511,26 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c
if (db.isEmpty())
return false;
+ bool sharedCache = false;
+ int openMode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, timeOut=5000;
+ QStringList opts=QString(conOpts).remove(QLatin1Char(' ')).split(QLatin1Char(';'));
+ foreach(const QString &option, opts) {
+ if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
+ bool ok;
+ int nt = option.mid(21).toInt(&ok);
+ if (ok)
+ timeOut = nt;
+ }
+ if (option == QLatin1String("QSQLITE_OPEN_READONLY"))
+ openMode = SQLITE_OPEN_READONLY;
+ if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE"))
+ sharedCache = true;
+ }
+
+ sqlite3_enable_shared_cache(sharedCache);
- if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, qGetSqliteOpenMode(conOpts), NULL) == SQLITE_OK) {
- sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts));
+ if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL) == SQLITE_OK) {
+ sqlite3_busy_timeout(d->access, timeOut);
setOpen(true);
setOpenError(false);
return true;
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index 031261d..1416ee3 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -1267,6 +1267,7 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const
\list
\i QSQLITE_BUSY_TIMEOUT
\i QSQLITE_OPEN_READONLY
+ \i QSQLITE_ENABLE_SHARED_CACHE
\endlist
\i
diff --git a/src/testlib/qbenchmark.cpp b/src/testlib/qbenchmark.cpp
index 95e2658..52b5287 100644
--- a/src/testlib/qbenchmark.cpp
+++ b/src/testlib/qbenchmark.cpp
@@ -282,6 +282,8 @@ quint64 QTest::endBenchmarkMeasurement()
Note that the -iterations command line argument has no effect
on test functions without the QBENCHMARK macro.
+
+ \since 4.7
*/
void QTest::setBenchmarkResult(qreal result, QTest::QBenchmarkMetric metric)
{
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 8099ffa..dc1d181 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -721,8 +721,9 @@ void WriteInitialization::acceptWidget(DomWidget *node)
m_output << m_indent << parentWidget << "->addDockWidget(" << area << varName << ");\n";
} else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"))) {
m_output << m_indent << parentWidget << "->setStatusBar(" << varName << ");\n";
- } else {
- m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n";
+ } else if (!m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DockWindow"))
+ && !m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ToolBar"))) {
+ m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n";
}
}
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp
index cae959b..8d9ae4f 100644
--- a/src/xml/dom/qdom.cpp
+++ b/src/xml/dom/qdom.cpp
@@ -2973,7 +2973,7 @@ QDomElement QDomNode::lastChildElement(const QString &tagName) const
}
/*!
- Returns the next sibilng element with tag name \a tagName if \a tagName
+ Returns the next sibling element with tag name \a tagName if \a tagName
is non-empty; otherwise returns any next sibling element.
Returns a null element if no such sibling exists.
diff --git a/src/xmlpatterns/data/qatomicvalue.cpp b/src/xmlpatterns/data/qatomicvalue.cpp
index 6858e27..c4f3578 100644
--- a/src/xmlpatterns/data/qatomicvalue.cpp
+++ b/src/xmlpatterns/data/qatomicvalue.cpp
@@ -226,6 +226,8 @@ ItemType::Ptr AtomicValue::qtToXDMType(const QXmlItem &item)
/* Fallthrough. */
case QVariant::Time:
return BuiltinTypes::xsDateTime;
+ case QMetaType::Float:
+ return BuiltinTypes::xsFloat;
case QVariant::Double:
return BuiltinTypes::xsDouble;
default:
diff --git a/src/xmlpatterns/schema/qxsdschemaparser.cpp b/src/xmlpatterns/schema/qxsdschemaparser.cpp
index 6d878e8..6ed28af 100644
--- a/src/xmlpatterns/schema/qxsdschemaparser.cpp
+++ b/src/xmlpatterns/schema/qxsdschemaparser.cpp
@@ -4832,7 +4832,7 @@ XsdTerm::Ptr XsdSchemaParser::parseLocalElement(const XsdParticle::Ptr &particle
if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
const XsdAnnotation::Ptr annotation = parseAnnotation();
- element->addAnnotation(annotation);
+ term->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.")
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 960cc43..4eda172 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -599,3 +599,11 @@ contains(QT_CONFIG, declarative): SUBDIRS += declarative
xmlpatternsview \
xmlpatternsxqts \
xmlpatternsxslts
+
+
+############### make check recursively for testcases ##################
+check.CONFIG = recursive
+check.recurse = $$SUBDIRS
+check.recurse_target = check
+QMAKE_EXTRA_TARGETS += check
+###########################################################
diff --git a/tests/auto/declarative/.gitignore b/tests/auto/declarative/.gitignore
new file mode 100644
index 0000000..d937eb4
--- /dev/null
+++ b/tests/auto/declarative/.gitignore
@@ -0,0 +1,4 @@
+tst_*
+!tst_*.*
+tst_*.debug
+tst_*~
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
new file mode 100644
index 0000000..8773026
--- /dev/null
+++ b/tests/auto/declarative/declarative.pro
@@ -0,0 +1,65 @@
+TEMPLATE = subdirs
+SUBDIRS += \
+ graphicswidgets \ # Cover
+ layouts \ # Cover
+ parserstress \ # Cover
+ qmetaobjectbuilder \ # Cover
+ qmlanimations \ # Cover
+ qmlbehaviors \ # Cover
+ qmlbinding \ # Cover
+ qmlconnection \ # Cover
+ qmlcontext \ # Cover
+ qmldatetimeformatter \ # Cover
+ qmldebug \ # Cover
+ qmldebugclient \ # Cover
+ qmldebugservice \ # Cover
+ qmldom \ # Cover
+ qmleasefollow \ # Cover
+ qmlecmascript \ # Cover
+ qmlengine \ # Cover
+ qmlerror \ # Cover
+ qmlfontloader \ # Cover
+ qmlgraphicsanchors \ # Cover
+ qmlgraphicsanimatedimage \ # Cover
+ qmlgraphicsimage \ # Cover
+ qmlgraphicsborderimage \ # Cover
+ qmlgraphicsflickable \ # Cover
+ qmlgraphicsflipable \ # Cover
+ qmlgraphicsgridview \ # Cover
+ qmlgraphicsitem \ # Cover
+ qmlgraphicslistview \ # Cover
+ qmlgraphicsloader \ # Cover
+ qmlgraphicsparticles \ # Cover
+ qmlgraphicspathview \ # Cover
+ qmlgraphicspositioners \ # Cover
+ qmlgraphicstext \ # Cover
+ qmlgraphicstextedit \ # Cover
+ qmlgraphicstextinput \ # Cover
+ qmlgraphicswebview \ # Cover
+ qmlinfo \ # Cover
+ qmlinstruction \ # Cover
+ qmllanguage \ # Cover
+ qmllist \ # Cover
+ qmllistaccessor \ # Cover
+ qmllistmodel \ # Cover
+ qmlmetaproperty \ # Cover
+ qmlmetatype \ # Cover
+ qmlnumberformatter \ # Cover
+ qmlpixmapcache \ # Cover
+ qmlpropertymap \ # Cover
+ qmlqt \ # Cover
+ qmlspringfollow \ # Cover
+ qmlstates \ # Cover
+ qmlsystempalette \ # Cover
+ qmltimer \ # Cover
+ qmlxmllistmodel \ # Cover
+ qpacketprotocol \ # Cover
+ qmlgraphicsrepeater \ # Cover
+ qmlvaluetypes \ # Cover
+ qmlxmlhttprequest \ # Cover
+ sql # Cover
+
+
+# Tests which should run in Pulse
+PULSE_TESTS = $$SUBDIRS
+
diff --git a/tests/auto/declarative/examples/data/dummytest.qml b/tests/auto/declarative/examples/data/dummytest.qml
new file mode 100644
index 0000000..b20e907
--- /dev/null
+++ b/tests/auto/declarative/examples/data/dummytest.qml
@@ -0,0 +1,6 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame { msec: 0 }
+ Frame { msec: 10 }
+}
diff --git a/tests/auto/declarative/examples/data/webbrowser/webbrowser.qml b/tests/auto/declarative/examples/data/webbrowser/webbrowser.qml
new file mode 100644
index 0000000..d31787b
--- /dev/null
+++ b/tests/auto/declarative/examples/data/webbrowser/webbrowser.qml
@@ -0,0 +1,6 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame { msec: 0 }
+ Frame { msec: 2000 }
+}
diff --git a/tests/auto/declarative/examples/examples.pro b/tests/auto/declarative/examples/examples.pro
new file mode 100644
index 0000000..b9bcd28
--- /dev/null
+++ b/tests/auto/declarative/examples/examples.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_examples.cpp
diff --git a/tests/auto/declarative/examples/tst_examples.cpp b/tests/auto/declarative/examples/tst_examples.cpp
new file mode 100644
index 0000000..fa4526a1
--- /dev/null
+++ b/tests/auto/declarative/examples/tst_examples.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QLibraryInfo>
+#include <QDir>
+#include <QProcess>
+#include <QDebug>
+
+class tst_examples : public QObject
+{
+ Q_OBJECT
+public:
+ tst_examples();
+
+private slots:
+ void examples_data();
+ void examples();
+
+ void namingConvention();
+private:
+ QString qmlviewer;
+ QStringList excludedDirs;
+
+ void namingConvention(const QDir &);
+ QStringList findQmlFiles(const QDir &);
+};
+
+tst_examples::tst_examples()
+{
+ QString binaries = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+
+#if defined(Q_WS_MAC)
+ qmlviewer = QDir(binaries).absoluteFilePath("qmlviewer.app/Contents/MacOS/qmlviewer");
+#elif defined(Q_WS_WIN)
+ qmlviewer = QDir(binaries).absoluteFilePath("qmlviewer.exe");
+#else
+ qmlviewer = QDir(binaries).absoluteFilePath("qmlviewer");
+#endif
+
+
+ // Add directories you want excluded here
+ excludedDirs << "examples/declarative/extending";
+ excludedDirs << "examples/declarative/plugins";
+}
+
+/*
+This tests that the demos and examples follow the naming convention required
+to have them tested by the examples() test.
+*/
+void tst_examples::namingConvention(const QDir &d)
+{
+ for (int ii = 0; ii < excludedDirs.count(); ++ii) {
+ QString s = QDir::toNativeSeparators(excludedDirs.at(ii));
+ if (d.absolutePath().endsWith(s))
+ return;
+ }
+
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+
+ bool seenQml = !files.isEmpty();
+ bool seenLowercase = false;
+
+ foreach (const QString &file, files) {
+ if (file.at(0).isLower())
+ seenLowercase = true;
+ }
+
+ if (!seenQml) {
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ namingConvention(sub);
+ }
+ } else if(!seenLowercase) {
+ QTest::qFail(QString("Directory " + d.absolutePath() + " violates naming convention").toLatin1().constData(), __FILE__, __LINE__);
+ }
+}
+
+void tst_examples::namingConvention()
+{
+ QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
+ QString demos = QLibraryInfo::location(QLibraryInfo::DemosPath);
+
+ namingConvention(QDir(examples));
+ namingConvention(QDir(demos));
+}
+
+QStringList tst_examples::findQmlFiles(const QDir &d)
+{
+ for (int ii = 0; ii < excludedDirs.count(); ++ii) {
+ QString s = QDir::toNativeSeparators(excludedDirs.at(ii));
+ if (d.absolutePath().endsWith(s))
+ return QStringList();
+ }
+
+ QStringList rv;
+
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+ foreach (const QString &file, files) {
+ if (file.at(0).isLower()) {
+ rv << d.absoluteFilePath(file);
+ }
+ }
+
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ rv << findQmlFiles(sub);
+ }
+
+ return rv;
+}
+
+/*
+This test runs all the examples in the declarative UI source tree and ensures
+that they start and exit cleanly.
+
+Examples are any .qml files under the examples/ or demos/ directory that start
+with a lower case letter.
+*/
+void tst_examples::examples_data()
+{
+ QTest::addColumn<QString>("file");
+
+ QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
+ QString demos = QLibraryInfo::location(QLibraryInfo::DemosPath);
+
+ QStringList files;
+ files << findQmlFiles(QDir(examples));
+ files << findQmlFiles(QDir(demos));
+
+ foreach (const QString &file, files)
+ QTest::newRow(file.toLatin1().constData()) << file;
+}
+
+void tst_examples::examples()
+{
+ QFETCH(QString, file);
+
+ QFileInfo fi(file);
+ QFileInfo dir(fi.path());
+ QString script = "data/"+dir.baseName()+"/"+fi.baseName();
+ QFileInfo testdata(script+".qml");
+ QStringList arguments;
+ arguments << "-script" << (testdata.exists() ? script : QLatin1String("data/dummytest"))
+ << "-scriptopts" << "play,testerror,exitoncomplete,exitonfailure"
+ << file;
+ QProcess p;
+ p.start(qmlviewer, arguments);
+ QVERIFY(p.waitForFinished());
+ QCOMPARE(p.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(p.exitCode(), 0);
+}
+
+QTEST_MAIN(tst_examples)
+
+#include "tst_examples.moc"
diff --git a/tests/auto/declarative/graphicswidgets/data/graphicswidgets.qml b/tests/auto/declarative/graphicswidgets/data/graphicswidgets.qml
new file mode 100644
index 0000000..70fafd6
--- /dev/null
+++ b/tests/auto/declarative/graphicswidgets/data/graphicswidgets.qml
@@ -0,0 +1,57 @@
+import Qt 4.6
+
+QGraphicsView {
+ objectName: "GView"
+ size: "800x600"
+
+ QGraphicsScene {
+ objectName: "GScene"
+ sceneRect: "0,0,500x300"
+
+ QGraphicsWidget {
+ layout: QGraphicsLinearLayout {
+ orientation: Qt.Horizontal
+ QGraphicsWidget {
+ layout: QGraphicsLinearLayout {
+ spacing: 10; orientation: Qt.Vertical
+ LayoutItem {
+ QGraphicsLinearLayout.stretchFactor: 1
+ objectName: "left"
+ minimumSize: "100x100"
+ maximumSize: "300x300"
+ preferredSize: "100x100"
+ Rectangle { objectName: "yellowRect"; color: "yellow"; anchors.fill: parent }
+ }
+ LayoutItem {
+ QGraphicsLinearLayout.stretchFactor: 10
+ objectName: "left"
+ minimumSize: "100x100"
+ maximumSize: "300x300"
+ preferredSize: "100x100"
+ Rectangle { objectName: "yellowRect"; color: "blue"; anchors.fill: parent }
+ }
+ }
+ }
+ QGraphicsWidget {
+ layout: QGraphicsLinearLayout {
+ spacing: 10; orientation: Qt.Vertical
+ LayoutItem {
+ objectName: "left"
+ minimumSize: "100x100"
+ maximumSize: "300x300"
+ preferredSize: "100x100"
+ Rectangle { objectName: "yellowRect"; color: "red"; anchors.fill: parent }
+ }
+ LayoutItem {
+ objectName: "left"
+ minimumSize: "100x100"
+ maximumSize: "300x300"
+ preferredSize: "100x100"
+ Rectangle { objectName: "yellowRect"; color: "green"; anchors.fill: parent }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/graphicswidgets/graphicswidgets.pro b/tests/auto/declarative/graphicswidgets/graphicswidgets.pro
new file mode 100644
index 0000000..712c34c
--- /dev/null
+++ b/tests/auto/declarative/graphicswidgets/graphicswidgets.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_graphicswidgets.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/graphicswidgets/tst_graphicswidgets.cpp b/tests/auto/declarative/graphicswidgets/tst_graphicswidgets.cpp
new file mode 100644
index 0000000..1bb8c14
--- /dev/null
+++ b/tests/auto/declarative/graphicswidgets/tst_graphicswidgets.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QFile>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/graphicswidgets_p.h>
+
+class tst_graphicswidgets : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_graphicswidgets();
+
+private slots:
+ void widgets();
+};
+
+tst_graphicswidgets::tst_graphicswidgets()
+{
+}
+
+void tst_graphicswidgets::widgets()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/graphicswidgets.qml"));
+ QGraphicsView *obj = qobject_cast<QGraphicsView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->scene() != 0);
+ QList<QObject*> list;
+ QVERIFY(obj->scene()->children() != list);
+ delete obj;
+}
+
+QTEST_MAIN(tst_graphicswidgets)
+
+#include "tst_graphicswidgets.moc"
diff --git a/tests/auto/declarative/layouts/data/layouts.qml b/tests/auto/declarative/layouts/data/layouts.qml
new file mode 100644
index 0000000..00d785d
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/layouts.qml
@@ -0,0 +1,33 @@
+import Qt 4.6
+
+Item {
+ id: resizable
+ width:300
+ height:300
+
+ GraphicsObjectContainer {
+ anchors.fill: parent
+ synchronizedResizing: true
+
+ QGraphicsWidget {
+
+ layout: QGraphicsLinearLayout {
+ spacing: 0
+ LayoutItem {
+ objectName: "left"
+ minimumSize: "100x100"
+ maximumSize: "300x300"
+ preferredSize: "100x100"
+ Rectangle { objectName: "yellowRect"; color: "yellow"; anchors.fill: parent }
+ }
+ LayoutItem {
+ objectName: "right"
+ minimumSize: "100x100"
+ maximumSize: "400x400"
+ preferredSize: "200x200"
+ Rectangle { objectName: "greenRect"; color: "green"; anchors.fill: parent }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/layouts/layouts.pro b/tests/auto/declarative/layouts/layouts.pro
new file mode 100644
index 0000000..f38e155
--- /dev/null
+++ b/tests/auto/declarative/layouts/layouts.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_layouts.cpp
+macx:CONFIG -= app_bundle
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/layouts/tst_layouts.cpp b/tests/auto/declarative/layouts/tst_layouts.cpp
new file mode 100644
index 0000000..0f832bf
--- /dev/null
+++ b/tests/auto/declarative/layouts/tst_layouts.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <private/qlistmodelinterface_p.h>
+#include <qmlview.h>
+#include <private/qmlgraphicslayoutitem_p.h>
+#include <qmlexpression.h>
+#include <QStyle>
+
+class tst_QmlGraphicsLayouts : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsLayouts();
+
+private slots:
+ void test_qml();//GraphicsLayout set up in Qml
+ void test_cpp();//GraphicsLayout set up in C++
+
+private:
+ QmlView *createView(const QString &filename);
+};
+
+tst_QmlGraphicsLayouts::tst_QmlGraphicsLayouts()
+{
+}
+
+void tst_QmlGraphicsLayouts::test_qml()
+{
+ QmlView *canvas = createView(SRCDIR "/data/layouts.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+ QmlGraphicsLayoutItem *left = static_cast<QmlGraphicsLayoutItem*>(canvas->root()->findChild<QmlGraphicsItem*>("left"));
+ QVERIFY(left != 0);
+
+ QmlGraphicsLayoutItem *right = static_cast<QmlGraphicsLayoutItem*>(canvas->root()->findChild<QmlGraphicsItem*>("right"));
+ QVERIFY(right != 0);
+
+ qreal l = QApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
+ qreal r = QApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin);
+ qreal t = QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin);
+ qreal b = QApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin);
+ QVERIFY2(l == r && r == t && t == b, "Test assumes equal margins.");
+ qreal gvMargin = l;
+ //Preferred Size
+ canvas->root()->setWidth(300 + 2*gvMargin);
+ canvas->root()->setHeight(300 + 2*gvMargin);
+
+ QCOMPARE(left->x(), gvMargin);
+ QCOMPARE(left->y(), gvMargin);
+ QCOMPARE(left->width(), 100.0);
+ QCOMPARE(left->height(), 300.0);
+
+ QCOMPARE(right->x(), 100.0 + gvMargin);
+ QCOMPARE(right->y(), 0.0 + gvMargin);
+ QCOMPARE(right->width(), 200.0);
+ QCOMPARE(right->height(), 300.0);
+
+ //Minimum Size
+ canvas->root()->setWidth(10+2*gvMargin);
+ canvas->root()->setHeight(10+2*gvMargin);
+
+ QCOMPARE(left->x(), gvMargin);
+ QCOMPARE(left->width(), 100.0);
+ QCOMPARE(left->height(), 100.0);
+
+ QCOMPARE(right->x(), 100.0 + gvMargin);
+ QCOMPARE(right->width(), 100.0);
+ QCOMPARE(right->height(), 100.0);
+
+ //Between preferred and Maximum Size
+ /*Note that if set to maximum size (or above) GraphicsLinearLayout behavior
+ is to shrink them down to preferred size. So the exact maximum size can't
+ be used*/
+ canvas->root()->setWidth(670 + 2*gvMargin);
+ canvas->root()->setHeight(300 + 2*gvMargin);
+
+ QCOMPARE(left->x(), gvMargin);
+ QCOMPARE(left->width(), 270.0);
+ QCOMPARE(left->height(), 300.0);
+
+ QCOMPARE(right->x(), 270.0 + gvMargin);
+ QCOMPARE(right->width(), 400.0);
+ QCOMPARE(right->height(), 300.0);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsLayouts::test_cpp()
+{
+ //TODO: Waiting on QT-2407 to write this test
+}
+
+QmlView *tst_QmlGraphicsLayouts::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ return canvas;
+}
+
+
+QTEST_MAIN(tst_QmlGraphicsLayouts)
+
+#include "tst_layouts.moc"
diff --git a/tests/auto/declarative/parserstress/parserstress.pro b/tests/auto/declarative/parserstress/parserstress.pro
new file mode 100644
index 0000000..48f147a
--- /dev/null
+++ b/tests/auto/declarative/parserstress/parserstress.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_parserstress.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/parserstress/tst_parserstress.cpp b/tests/auto/declarative/parserstress/tst_parserstress.cpp
new file mode 100644
index 0000000..a607bb3
--- /dev/null
+++ b/tests/auto/declarative/parserstress/tst_parserstress.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+
+class tst_parserstress : public QObject
+{
+ Q_OBJECT
+public:
+ tst_parserstress() {}
+
+private slots:
+ void ecmascript_data();
+ void ecmascript();
+
+private:
+ static QStringList findJSFiles(const QDir &);
+ QmlEngine engine;
+};
+
+QStringList tst_parserstress::findJSFiles(const QDir &d)
+{
+ QStringList rv;
+
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.js"),
+ QDir::Files);
+ foreach (const QString &file, files) {
+ if (file == "browser.js")
+ continue;
+ rv << d.absoluteFilePath(file);
+ }
+
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ rv << findJSFiles(sub);
+ }
+
+ return rv;
+}
+
+void tst_parserstress::ecmascript_data()
+{
+ QDir dir(SRCDIR);
+ dir.cdUp();
+ dir.cdUp();
+ dir.cd("qscriptjstestsuite");
+ dir.cd("tests");
+
+ QStringList files = findJSFiles(dir);
+
+ QTest::addColumn<QString>("file");
+ foreach (const QString &file, files) {
+ QTest::newRow(qPrintable(file)) << file;
+ }
+}
+
+void tst_parserstress::ecmascript()
+{
+ QFETCH(QString, file);
+
+ QFile f(file);
+ QVERIFY(f.open(QIODevice::ReadOnly));
+
+ QByteArray data = f.readAll();
+
+ QVERIFY(!data.isEmpty());
+
+ QString dataStr = QString::fromUtf8(data);
+
+ QString qml = "import Qt 4.6\n";
+ qml+= "\n";
+ qml+= "QtObject {\n";
+ qml+= " property int test\n";
+ qml+= " test: {\n";
+ qml+= dataStr + "\n";
+ qml+= " return 1;\n";
+ qml+= " }\n";
+ qml+= " Script {\n";
+ qml+= " function stress() {\n";
+ qml+= dataStr;
+ qml+= " }\n";
+ qml+= " }\n";
+ qml+= "}\n";
+
+ QByteArray qmlData = qml.toUtf8();
+
+ QmlComponent component(&engine);
+ component.setData(qmlData, QUrl::fromLocalFile(SRCDIR + QString("/dummy.qml")));
+ QSet<QString> failingTests;
+ failingTests << "uc-003.js" << "uc-005.js" << "regress-352044-02-n.js"
+ << "regress-334158.js" << "regress-58274.js" << "dowhile-006.js" << "dowhile-005.js";
+ QFileInfo info(file);
+ foreach (const QString &failing, failingTests) {
+ if (info.fileName().endsWith(failing)) {
+ QEXPECT_FAIL("", "QTBUG-8108", Continue);
+ break;
+ }
+ }
+ QVERIFY(!component.isError());
+}
+
+
+QTEST_MAIN(tst_parserstress)
+
+#include "tst_parserstress.moc"
diff --git a/tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro b/tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro
new file mode 100644
index 0000000..94ffe4b
--- /dev/null
+++ b/tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += \
+ tst_qmetaobjectbuilder.cpp
+
diff --git a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..b82372a
--- /dev/null
+++ b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -0,0 +1,1258 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <private/qmetaobjectbuilder_p.h>
+
+class tst_QMetaObjectBuilder : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMetaObjectBuilder() {}
+ ~tst_QMetaObjectBuilder() {}
+
+private slots:
+ void mocVersionCheck();
+ void create();
+ void className();
+ void superClass();
+ void flags();
+ void method();
+ void slot();
+ void signal();
+ void constructor();
+ void property();
+ void notifySignal();
+ void enumerator();
+ void classInfo();
+ void relatedMetaObject();
+ void staticMetacall();
+ void copyMetaObject();
+ void serialize();
+ void removeNotifySignal();
+
+private:
+ static bool checkForSideEffects
+ (const QMetaObjectBuilder& builder,
+ QMetaObjectBuilder::AddMembers members);
+ static bool sameMetaObject
+ (const QMetaObject *meta1, const QMetaObject *meta2);
+};
+
+// Dummy class that has something of every type of thing moc can generate.
+class SomethingOfEverything : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("ci_foo", "ABC")
+ Q_CLASSINFO("ci_bar", "DEF")
+ Q_PROPERTY(QString prop READ prop WRITE setProp NOTIFY propChanged)
+ Q_PROPERTY(QString prop2 READ prop WRITE setProp)
+ Q_PROPERTY(SomethingEnum eprop READ eprop)
+ Q_PROPERTY(SomethingFlagEnum fprop READ fprop)
+ Q_PROPERTY(QLocale::Language language READ language)
+ Q_ENUMS(SomethingEnum)
+ Q_FLAGS(SomethingFlagEnum)
+public:
+ Q_INVOKABLE SomethingOfEverything() {}
+ ~SomethingOfEverything() {}
+
+ enum SomethingEnum
+ {
+ GHI,
+ JKL = 10
+ };
+
+ enum SomethingFlagEnum
+ {
+ XYZ = 1,
+ UVW = 8
+ };
+
+ Q_INVOKABLE Q_SCRIPTABLE void method1() {}
+
+ QString prop() const { return QString(); }
+ void setProp(const QString& v) { Q_UNUSED(v); }
+
+ SomethingOfEverything::SomethingEnum eprop() const { return GHI; }
+ SomethingOfEverything::SomethingFlagEnum fprop() const { return XYZ; }
+ QLocale::Language language() const { return QLocale::English; }
+
+public slots:
+ void slot1(const QString&) {}
+ void slot2(int, const QString&) {}
+
+private slots:
+ void slot3() {}
+
+protected slots:
+ Q_SCRIPTABLE void slot4(int) {}
+ void slot5(int a, const QString& b) { Q_UNUSED(a); Q_UNUSED(b); }
+
+signals:
+ void sig1();
+ void sig2(int x, const QString& y);
+ void propChanged(const QString&);
+};
+
+void tst_QMetaObjectBuilder::mocVersionCheck()
+{
+ // This test will fail when the moc version number is changed.
+ // It is intended as a reminder to also update QMetaObjectBuilder
+ // whenenver moc changes. Once QMetaObjectBuilder has been
+ // updated, this test can be changed to check for the next version.
+ QEXPECT_FAIL("", "QT-2918", Continue);
+ QCOMPARE(int(QObject::staticMetaObject.d.data[0]), 4);
+ QEXPECT_FAIL("", "QT-2918", Continue);
+ QCOMPARE(int(staticMetaObject.d.data[0]), 4);
+}
+
+void tst_QMetaObjectBuilder::create()
+{
+ QMetaObjectBuilder builder;
+ QVERIFY(builder.className().isEmpty());
+ QVERIFY(builder.superClass() == &QObject::staticMetaObject);
+ QCOMPARE(builder.methodCount(), 0);
+ QCOMPARE(builder.constructorCount(), 0);
+ QCOMPARE(builder.propertyCount(), 0);
+ QCOMPARE(builder.enumeratorCount(), 0);
+ QCOMPARE(builder.classInfoCount(), 0);
+ QCOMPARE(builder.relatedMetaObjectCount(), 0);
+ QVERIFY(builder.staticMetacallFunction() == 0);
+}
+
+void tst_QMetaObjectBuilder::className()
+{
+ QMetaObjectBuilder builder;
+
+ // Change the class name.
+ builder.setClassName("Foo");
+ QCOMPARE(builder.className(), QByteArray("Foo"));
+
+ // Change it again.
+ builder.setClassName("Bar");
+ QCOMPARE(builder.className(), QByteArray("Bar"));
+
+ // Clone the class name off a static QMetaObject.
+ builder.addMetaObject(&QObject::staticMetaObject, QMetaObjectBuilder::ClassName);
+ QCOMPARE(builder.className(), QByteArray("QObject"));
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::ClassName));
+}
+
+void tst_QMetaObjectBuilder::superClass()
+{
+ QMetaObjectBuilder builder;
+
+ // Change the super class.
+ builder.setSuperClass(&QObject::staticMetaObject);
+ QVERIFY(builder.superClass() == &QObject::staticMetaObject);
+
+ // Change it again.
+ builder.setSuperClass(&staticMetaObject);
+ QVERIFY(builder.superClass() == &staticMetaObject);
+
+ // Clone the super class off a static QMetaObject.
+ builder.addMetaObject(&QObject::staticMetaObject, QMetaObjectBuilder::SuperClass);
+ QVERIFY(builder.superClass() == 0);
+ builder.addMetaObject(&staticMetaObject, QMetaObjectBuilder::SuperClass);
+ QVERIFY(builder.superClass() == staticMetaObject.superClass());
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::SuperClass));
+}
+
+void tst_QMetaObjectBuilder::flags()
+{
+ QMetaObjectBuilder builder;
+
+ // Check default
+ QVERIFY(builder.flags() == 0);
+
+ // Set flags
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ QVERIFY(builder.flags() == QMetaObjectBuilder::DynamicMetaObject);
+}
+
+void tst_QMetaObjectBuilder::method()
+{
+ QMetaObjectBuilder builder;
+
+ // Check null method
+ QMetaMethodBuilder nullMethod;
+ QCOMPARE(nullMethod.signature(), QByteArray());
+ QVERIFY(nullMethod.methodType() == QMetaMethod::Method);
+ QVERIFY(nullMethod.returnType().isEmpty());
+ QVERIFY(nullMethod.parameterNames().isEmpty());
+ QVERIFY(nullMethod.tag().isEmpty());
+ QVERIFY(nullMethod.access() == QMetaMethod::Public);
+ QCOMPARE(nullMethod.attributes(), 0);
+ QCOMPARE(nullMethod.index(), 0);
+
+ // Add a method and check its attributes.
+ QMetaMethodBuilder method1 = builder.addMethod("foo(const QString&, int)");
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Method);
+ QVERIFY(method1.returnType().isEmpty());
+ QVERIFY(method1.parameterNames().isEmpty());
+ QVERIFY(method1.tag().isEmpty());
+ QVERIFY(method1.access() == QMetaMethod::Public);
+ QCOMPARE(method1.attributes(), 0);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(builder.methodCount(), 1);
+
+ // Add another method and check again.
+ QMetaMethodBuilder method2 = builder.addMethod("bar(QString)", "int");
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QCOMPARE(method2.returnType(), QByteArray("int"));
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Public);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfMethod("foo(const QString&, int)"), 0);
+ QCOMPARE(builder.indexOfMethod("bar(QString)"), 1);
+ QCOMPARE(builder.indexOfMethod("baz()"), -1);
+
+ // Modify the attributes on method1.
+ method1.setReturnType("int");
+ method1.setParameterNames(QList<QByteArray>() << "a" << "b");
+ method1.setTag("tag");
+ method1.setAccess(QMetaMethod::Private);
+ method1.setAttributes(42);
+
+ // Check that method1 is changed, but method2 is not.
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Method);
+ QCOMPARE(method1.returnType(), QByteArray("int"));
+ QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(method1.tag(), QByteArray("tag"));
+ QVERIFY(method1.access() == QMetaMethod::Private);
+ QCOMPARE(method1.attributes(), 42);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QCOMPARE(method2.returnType(), QByteArray("int"));
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Public);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Modify the attributes on method2.
+ method2.setReturnType("QString");
+ method2.setParameterNames(QList<QByteArray>() << "c");
+ method2.setTag("Q_FOO");
+ method2.setAccess(QMetaMethod::Protected);
+ method2.setAttributes(24);
+
+ // This time check that only method2 changed.
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Method);
+ QCOMPARE(method1.returnType(), QByteArray("int"));
+ QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(method1.tag(), QByteArray("tag"));
+ QVERIFY(method1.access() == QMetaMethod::Private);
+ QCOMPARE(method1.attributes(), 42);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QCOMPARE(method2.returnType(), QByteArray("QString"));
+ QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(method2.access() == QMetaMethod::Protected);
+ QCOMPARE(method2.attributes(), 24);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Remove method1 and check that method2 becomes index 0.
+ builder.removeMethod(0);
+ QCOMPARE(builder.methodCount(), 1);
+ method2 = builder.method(0);
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QCOMPARE(method2.returnType(), QByteArray("QString"));
+ QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(method2.access() == QMetaMethod::Protected);
+ QCOMPARE(method2.attributes(), 24);
+ QCOMPARE(method2.index(), 0);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfMethod("foo(const QString&, int)"), -1);
+ QCOMPARE(builder.indexOfMethod("bar(QString)"), 0);
+ QCOMPARE(builder.indexOfMethod("baz()"), -1);
+ QCOMPARE(builder.method(0).signature(), QByteArray("bar(QString)"));
+ QCOMPARE(builder.method(9).signature(), QByteArray());
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Methods));
+}
+
+void tst_QMetaObjectBuilder::slot()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a slot and check its attributes.
+ QMetaMethodBuilder method1 = builder.addSlot("foo(const QString&, int)");
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Slot);
+ QVERIFY(method1.returnType().isEmpty());
+ QVERIFY(method1.parameterNames().isEmpty());
+ QVERIFY(method1.tag().isEmpty());
+ QVERIFY(method1.access() == QMetaMethod::Public);
+ QCOMPARE(method1.attributes(), 0);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(builder.methodCount(), 1);
+
+ // Add another slot and check again.
+ QMetaMethodBuilder method2 = builder.addSlot("bar(QString)");
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Slot);
+ QVERIFY(method2.returnType().isEmpty());
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Public);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Perform index-based lookup
+ QCOMPARE(builder.indexOfSlot("foo(const QString &, int)"), 0);
+ QCOMPARE(builder.indexOfSlot("bar(QString)"), 1);
+ QCOMPARE(builder.indexOfSlot("baz()"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Methods));
+}
+
+void tst_QMetaObjectBuilder::signal()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a signal and check its attributes.
+ QMetaMethodBuilder method1 = builder.addSignal("foo(const QString&, int)");
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Signal);
+ QVERIFY(method1.returnType().isEmpty());
+ QVERIFY(method1.parameterNames().isEmpty());
+ QVERIFY(method1.tag().isEmpty());
+ QVERIFY(method1.access() == QMetaMethod::Protected);
+ QCOMPARE(method1.attributes(), 0);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(builder.methodCount(), 1);
+
+ // Add another signal and check again.
+ QMetaMethodBuilder method2 = builder.addSignal("bar(QString)");
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Signal);
+ QVERIFY(method2.returnType().isEmpty());
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Protected);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Perform index-based lookup
+ QCOMPARE(builder.indexOfSignal("foo(const QString &, int)"), 0);
+ QCOMPARE(builder.indexOfSignal("bar(QString)"), 1);
+ QCOMPARE(builder.indexOfSignal("baz()"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Methods));
+}
+
+void tst_QMetaObjectBuilder::constructor()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a constructor and check its attributes.
+ QMetaMethodBuilder ctor1 = builder.addConstructor("foo(const QString&, int)");
+ QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
+ QVERIFY(ctor1.returnType().isEmpty());
+ QVERIFY(ctor1.parameterNames().isEmpty());
+ QVERIFY(ctor1.tag().isEmpty());
+ QVERIFY(ctor1.access() == QMetaMethod::Public);
+ QCOMPARE(ctor1.attributes(), 0);
+ QCOMPARE(ctor1.index(), 0);
+ QCOMPARE(builder.constructorCount(), 1);
+
+ // Add another constructor and check again.
+ QMetaMethodBuilder ctor2 = builder.addConstructor("bar(QString)");
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QVERIFY(ctor2.returnType().isEmpty());
+ QVERIFY(ctor2.parameterNames().isEmpty());
+ QVERIFY(ctor2.tag().isEmpty());
+ QVERIFY(ctor2.access() == QMetaMethod::Public);
+ QCOMPARE(ctor2.attributes(), 0);
+ QCOMPARE(ctor2.index(), 1);
+ QCOMPARE(builder.constructorCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfConstructor("foo(const QString&, int)"), 0);
+ QCOMPARE(builder.indexOfConstructor("bar(QString)"), 1);
+ QCOMPARE(builder.indexOfConstructor("baz()"), -1);
+ QCOMPARE(builder.constructor(1).signature(), QByteArray("bar(QString)"));
+ QCOMPARE(builder.constructor(9).signature(), QByteArray());
+
+ // Modify the attributes on ctor1.
+ ctor1.setReturnType("int");
+ ctor1.setParameterNames(QList<QByteArray>() << "a" << "b");
+ ctor1.setTag("tag");
+ ctor1.setAccess(QMetaMethod::Private);
+ ctor1.setAttributes(42);
+
+ // Check that ctor1 is changed, but ctor2 is not.
+ QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor1.returnType(), QByteArray("int"));
+ QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(ctor1.tag(), QByteArray("tag"));
+ QVERIFY(ctor1.access() == QMetaMethod::Private);
+ QCOMPARE(ctor1.attributes(), 42);
+ QCOMPARE(ctor1.index(), 0);
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QVERIFY(ctor2.returnType().isEmpty());
+ QVERIFY(ctor2.parameterNames().isEmpty());
+ QVERIFY(ctor2.tag().isEmpty());
+ QVERIFY(ctor2.access() == QMetaMethod::Public);
+ QCOMPARE(ctor2.attributes(), 0);
+ QCOMPARE(ctor2.index(), 1);
+ QCOMPARE(builder.constructorCount(), 2);
+
+ // Modify the attributes on ctor2.
+ ctor2.setReturnType("QString");
+ ctor2.setParameterNames(QList<QByteArray>() << "c");
+ ctor2.setTag("Q_FOO");
+ ctor2.setAccess(QMetaMethod::Protected);
+ ctor2.setAttributes(24);
+
+ // This time check that only ctor2 changed.
+ QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor1.returnType(), QByteArray("int"));
+ QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(ctor1.tag(), QByteArray("tag"));
+ QVERIFY(ctor1.access() == QMetaMethod::Private);
+ QCOMPARE(ctor1.attributes(), 42);
+ QCOMPARE(ctor1.index(), 0);
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor2.returnType(), QByteArray("QString"));
+ QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(ctor2.access() == QMetaMethod::Protected);
+ QCOMPARE(ctor2.attributes(), 24);
+ QCOMPARE(ctor2.index(), 1);
+ QCOMPARE(builder.constructorCount(), 2);
+
+ // Remove ctor1 and check that ctor2 becomes index 0.
+ builder.removeConstructor(0);
+ QCOMPARE(builder.constructorCount(), 1);
+ ctor2 = builder.constructor(0);
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor2.returnType(), QByteArray("QString"));
+ QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(ctor2.access() == QMetaMethod::Protected);
+ QCOMPARE(ctor2.attributes(), 24);
+ QCOMPARE(ctor2.index(), 0);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfConstructor("foo(const QString&, int)"), -1);
+ QCOMPARE(builder.indexOfConstructor("bar(QString)"), 0);
+ QCOMPARE(builder.indexOfConstructor("baz()"), -1);
+
+ // Add constructor from prototype
+ QMetaMethod prototype = SomethingOfEverything::staticMetaObject.constructor(0);
+ QMetaMethodBuilder prototypeConstructor = builder.addMethod(prototype);
+ QCOMPARE(builder.constructorCount(), 2);
+
+ QCOMPARE(prototypeConstructor.signature(), QByteArray("SomethingOfEverything()"));
+ QVERIFY(prototypeConstructor.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(prototypeConstructor.returnType(), QByteArray());
+ QVERIFY(prototypeConstructor.access() == QMetaMethod::Public);
+ QCOMPARE(prototypeConstructor.index(), 1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Constructors));
+}
+
+void tst_QMetaObjectBuilder::property()
+{
+ QMetaObjectBuilder builder;
+
+ // Null property builder
+ QMetaPropertyBuilder nullProp;
+ QCOMPARE(nullProp.name(), QByteArray());
+ QCOMPARE(nullProp.type(), QByteArray());
+ QVERIFY(!nullProp.hasNotifySignal());
+ QVERIFY(!nullProp.isReadable());
+ QVERIFY(!nullProp.isWritable());
+ QVERIFY(!nullProp.isResettable());
+ QVERIFY(!nullProp.isDesignable());
+ QVERIFY(!nullProp.isScriptable());
+ QVERIFY(!nullProp.isStored());
+ QVERIFY(!nullProp.isEditable());
+ QVERIFY(!nullProp.isUser());
+ QVERIFY(!nullProp.hasStdCppSet());
+ QVERIFY(!nullProp.isEnumOrFlag());
+ QVERIFY(!nullProp.isDynamic());
+ QCOMPARE(nullProp.index(), 0);
+
+ // Add a property and check its attributes.
+ QMetaPropertyBuilder prop1 = builder.addProperty("foo", "const QString &");
+ QCOMPARE(prop1.name(), QByteArray("foo"));
+ QCOMPARE(prop1.type(), QByteArray("QString"));
+ QVERIFY(!prop1.hasNotifySignal());
+ QVERIFY(prop1.isReadable());
+ QVERIFY(prop1.isWritable());
+ QVERIFY(!prop1.isResettable());
+ QVERIFY(!prop1.isDesignable());
+ QVERIFY(!prop1.isScriptable());
+ QVERIFY(!prop1.isStored());
+ QVERIFY(!prop1.isEditable());
+ QVERIFY(!prop1.isUser());
+ QVERIFY(!prop1.hasStdCppSet());
+ QVERIFY(!prop1.isEnumOrFlag());
+ QVERIFY(!prop1.isDynamic());
+ QCOMPARE(prop1.index(), 0);
+ QCOMPARE(builder.propertyCount(), 1);
+
+ // Add another property and check again.
+ QMetaPropertyBuilder prop2 = builder.addProperty("bar", "int");
+ QCOMPARE(prop2.name(), QByteArray("bar"));
+ QCOMPARE(prop2.type(), QByteArray("int"));
+ QVERIFY(!prop2.hasNotifySignal());
+ QVERIFY(prop2.isReadable());
+ QVERIFY(prop2.isWritable());
+ QVERIFY(!prop2.isResettable());
+ QVERIFY(!prop2.isDesignable());
+ QVERIFY(!prop2.isScriptable());
+ QVERIFY(!prop2.isStored());
+ QVERIFY(!prop2.isEditable());
+ QVERIFY(!prop2.isUser());
+ QVERIFY(!prop2.hasStdCppSet());
+ QVERIFY(!prop2.isEnumOrFlag());
+ QVERIFY(!prop2.isDynamic());
+ QCOMPARE(prop2.index(), 1);
+ QCOMPARE(builder.propertyCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfProperty("foo"), 0);
+ QCOMPARE(builder.indexOfProperty("bar"), 1);
+ QCOMPARE(builder.indexOfProperty("baz"), -1);
+ QCOMPARE(builder.property(1).name(), QByteArray("bar"));
+ QCOMPARE(builder.property(9).name(), QByteArray());
+
+ // Modify the attributes on prop1.
+ prop1.setReadable(false);
+ prop1.setWritable(false);
+ prop1.setResettable(true);
+ prop1.setDesignable(true);
+ prop1.setScriptable(true);
+ prop1.setStored(true);
+ prop1.setEditable(true);
+ prop1.setUser(true);
+ prop1.setStdCppSet(true);
+ prop1.setEnumOrFlag(true);
+ prop1.setDynamic(true);
+
+ // Check that prop1 is changed, but prop2 is not.
+ QCOMPARE(prop1.name(), QByteArray("foo"));
+ QCOMPARE(prop1.type(), QByteArray("QString"));
+ QVERIFY(!prop1.isReadable());
+ QVERIFY(!prop1.isWritable());
+ QVERIFY(prop1.isResettable());
+ QVERIFY(prop1.isDesignable());
+ QVERIFY(prop1.isScriptable());
+ QVERIFY(prop1.isStored());
+ QVERIFY(prop1.isEditable());
+ QVERIFY(prop1.isUser());
+ QVERIFY(prop1.hasStdCppSet());
+ QVERIFY(prop1.isEnumOrFlag());
+ QVERIFY(prop1.isDynamic());
+ QVERIFY(prop2.isReadable());
+ QVERIFY(prop2.isWritable());
+ QCOMPARE(prop2.name(), QByteArray("bar"));
+ QCOMPARE(prop2.type(), QByteArray("int"));
+ QVERIFY(!prop2.isResettable());
+ QVERIFY(!prop2.isDesignable());
+ QVERIFY(!prop2.isScriptable());
+ QVERIFY(!prop2.isStored());
+ QVERIFY(!prop2.isEditable());
+ QVERIFY(!prop2.isUser());
+ QVERIFY(!prop2.hasStdCppSet());
+ QVERIFY(!prop2.isEnumOrFlag());
+ QVERIFY(!prop2.isDynamic());
+
+ // Remove prop1 and check that prop2 becomes index 0.
+ builder.removeProperty(0);
+ QCOMPARE(builder.propertyCount(), 1);
+ prop2 = builder.property(0);
+ QCOMPARE(prop2.name(), QByteArray("bar"));
+ QCOMPARE(prop2.type(), QByteArray("int"));
+ QVERIFY(!prop2.isResettable());
+ QVERIFY(!prop2.isDesignable());
+ QVERIFY(!prop2.isScriptable());
+ QVERIFY(!prop2.isStored());
+ QVERIFY(!prop2.isEditable());
+ QVERIFY(!prop2.isUser());
+ QVERIFY(!prop2.hasStdCppSet());
+ QVERIFY(!prop2.isEnumOrFlag());
+ QVERIFY(!prop2.isDynamic());
+ QCOMPARE(prop2.index(), 0);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfProperty("foo"), -1);
+ QCOMPARE(builder.indexOfProperty("bar"), 0);
+ QCOMPARE(builder.indexOfProperty("baz"), -1);
+
+ // Check for side-effects between the flags on prop2.
+ // Setting a flag to true shouldn't set any of the others to true.
+ // This checks for cut-and-paste bugs in the implementation where
+ // the flag code was pasted but the flag name was not changed.
+#define CLEAR_FLAGS() \
+ do { \
+ prop2.setReadable(false); \
+ prop2.setWritable(false); \
+ prop2.setResettable(false); \
+ prop2.setDesignable(false); \
+ prop2.setScriptable(false); \
+ prop2.setStored(false); \
+ prop2.setEditable(false); \
+ prop2.setUser(false); \
+ prop2.setStdCppSet(false); \
+ prop2.setEnumOrFlag(false); \
+ prop2.setDynamic(false); \
+ } while (0)
+#define COUNT_FLAGS() \
+ ((prop2.isReadable() ? 1 : 0) + \
+ (prop2.isWritable() ? 1 : 0) + \
+ (prop2.isResettable() ? 1 : 0) + \
+ (prop2.isDesignable() ? 1 : 0) + \
+ (prop2.isScriptable() ? 1 : 0) + \
+ (prop2.isStored() ? 1 : 0) + \
+ (prop2.isEditable() ? 1 : 0) + \
+ (prop2.isUser() ? 1 : 0) + \
+ (prop2.hasStdCppSet() ? 1 : 0) + \
+ (prop2.isEnumOrFlag() ? 1 : 0) + \
+ (prop2.isDynamic() ? 1 : 0))
+#define CHECK_FLAG(setFunc,isFunc) \
+ do { \
+ CLEAR_FLAGS(); \
+ QCOMPARE(COUNT_FLAGS(), 0); \
+ prop2.setFunc(true); \
+ QVERIFY(prop2.isFunc()); \
+ QCOMPARE(COUNT_FLAGS(), 1); \
+ } while (0)
+ CHECK_FLAG(setReadable, isReadable);
+ CHECK_FLAG(setWritable, isWritable);
+ CHECK_FLAG(setResettable, isResettable);
+ CHECK_FLAG(setDesignable, isDesignable);
+ CHECK_FLAG(setScriptable, isScriptable);
+ CHECK_FLAG(setStored, isStored);
+ CHECK_FLAG(setEditable, isEditable);
+ CHECK_FLAG(setUser, isUser);
+ CHECK_FLAG(setStdCppSet, hasStdCppSet);
+ CHECK_FLAG(setEnumOrFlag, isEnumOrFlag);
+ CHECK_FLAG(setDynamic, isDynamic);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Properties));
+
+ // Add property from prototype
+ QMetaProperty prototype = SomethingOfEverything::staticMetaObject.property(1);
+ QVERIFY(prototype.name() == QByteArray("prop"));
+ QMetaPropertyBuilder prototypeProp = builder.addProperty(prototype);
+ QCOMPARE(prototypeProp.name(), QByteArray("prop"));
+ QVERIFY(prototypeProp.hasNotifySignal());
+ QCOMPARE(prototypeProp.notifySignal().signature(), QByteArray("propChanged(QString)"));
+ QCOMPARE(builder.methodCount(), 1);
+ QCOMPARE(builder.method(0).signature(), QByteArray("propChanged(QString)"));
+}
+
+void tst_QMetaObjectBuilder::notifySignal()
+{
+ QMetaObjectBuilder builder;
+
+ QMetaPropertyBuilder prop = builder.addProperty("foo", "const QString &");
+ builder.addSlot("setFoo(QString)");
+ QMetaMethodBuilder notify = builder.addSignal("fooChanged(QString)");
+
+ QVERIFY(!prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 0);
+
+ prop.setNotifySignal(notify);
+ QVERIFY(prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 1);
+
+ prop.setNotifySignal(QMetaMethodBuilder());
+ QVERIFY(!prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 0);
+
+ prop.setNotifySignal(notify);
+ prop.removeNotifySignal();
+ QVERIFY(!prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 0);
+
+ QCOMPARE(builder.methodCount(), 2);
+ QCOMPARE(builder.propertyCount(), 1);
+
+ // Check that nothing else changed except methods and properties.
+ QVERIFY(checkForSideEffects
+ (builder, QMetaObjectBuilder::Methods | QMetaObjectBuilder::Properties));
+}
+
+void tst_QMetaObjectBuilder::enumerator()
+{
+ QMetaObjectBuilder builder;
+
+ // Add an enumerator and check its attributes.
+ QMetaEnumBuilder enum1 = builder.addEnumerator("foo");
+ QCOMPARE(enum1.name(), QByteArray("foo"));
+ QVERIFY(!enum1.isFlag());
+ QCOMPARE(enum1.keyCount(), 0);
+ QCOMPARE(enum1.index(), 0);
+ QCOMPARE(builder.enumeratorCount(), 1);
+
+ // Add another enumerator and check again.
+ QMetaEnumBuilder enum2 = builder.addEnumerator("bar");
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(!enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 0);
+ QCOMPARE(enum2.index(), 1);
+ QCOMPARE(builder.enumeratorCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfEnumerator("foo"), 0);
+ QCOMPARE(builder.indexOfEnumerator("bar"), 1);
+ QCOMPARE(builder.indexOfEnumerator("baz"), -1);
+ QCOMPARE(builder.enumerator(1).name(), QByteArray("bar"));
+ QCOMPARE(builder.enumerator(9).name(), QByteArray());
+
+ // Modify the attributes on enum1.
+ enum1.setIsFlag(true);
+ QCOMPARE(enum1.addKey("ABC", 0), 0);
+ QCOMPARE(enum1.addKey("DEF", 1), 1);
+ QCOMPARE(enum1.addKey("GHI", -1), 2);
+
+ // Check that enum1 is changed, but enum2 is not.
+ QCOMPARE(enum1.name(), QByteArray("foo"));
+ QVERIFY(enum1.isFlag());
+ QCOMPARE(enum1.keyCount(), 3);
+ QCOMPARE(enum1.index(), 0);
+ QCOMPARE(enum1.key(0), QByteArray("ABC"));
+ QCOMPARE(enum1.key(1), QByteArray("DEF"));
+ QCOMPARE(enum1.key(2), QByteArray("GHI"));
+ QCOMPARE(enum1.key(3), QByteArray());
+ QCOMPARE(enum1.value(0), 0);
+ QCOMPARE(enum1.value(1), 1);
+ QCOMPARE(enum1.value(2), -1);
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(!enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 0);
+ QCOMPARE(enum2.index(), 1);
+
+ // Modify the attributes on enum2.
+ enum2.setIsFlag(true);
+ QCOMPARE(enum2.addKey("XYZ", 10), 0);
+ QCOMPARE(enum2.addKey("UVW", 19), 1);
+
+ // This time check that only method2 changed.
+ QCOMPARE(enum1.name(), QByteArray("foo"));
+ QVERIFY(enum1.isFlag());
+ QCOMPARE(enum1.keyCount(), 3);
+ QCOMPARE(enum1.index(), 0);
+ QCOMPARE(enum1.key(0), QByteArray("ABC"));
+ QCOMPARE(enum1.key(1), QByteArray("DEF"));
+ QCOMPARE(enum1.key(2), QByteArray("GHI"));
+ QCOMPARE(enum1.key(3), QByteArray());
+ QCOMPARE(enum1.value(0), 0);
+ QCOMPARE(enum1.value(1), 1);
+ QCOMPARE(enum1.value(2), -1);
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 2);
+ QCOMPARE(enum2.index(), 1);
+ QCOMPARE(enum2.key(0), QByteArray("XYZ"));
+ QCOMPARE(enum2.key(1), QByteArray("UVW"));
+ QCOMPARE(enum2.key(2), QByteArray());
+ QCOMPARE(enum2.value(0), 10);
+ QCOMPARE(enum2.value(1), 19);
+
+ // Remove enum1 key
+ enum1.removeKey(2);
+ QCOMPARE(enum1.name(), QByteArray("foo"));
+ QVERIFY(enum1.isFlag());
+ QCOMPARE(enum1.keyCount(), 2);
+ QCOMPARE(enum1.index(), 0);
+ QCOMPARE(enum1.key(0), QByteArray("ABC"));
+ QCOMPARE(enum1.key(1), QByteArray("DEF"));
+ QCOMPARE(enum1.key(2), QByteArray());
+ QCOMPARE(enum1.value(0), 0);
+ QCOMPARE(enum1.value(1), 1);
+ QCOMPARE(enum1.value(2), -1);
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 2);
+ QCOMPARE(enum2.index(), 1);
+ QCOMPARE(enum2.key(0), QByteArray("XYZ"));
+ QCOMPARE(enum2.key(1), QByteArray("UVW"));
+ QCOMPARE(enum2.key(2), QByteArray());
+ QCOMPARE(enum2.value(0), 10);
+ QCOMPARE(enum2.value(1), 19);
+
+ // Remove enum1 and check that enum2 becomes index 0.
+ builder.removeEnumerator(0);
+ QCOMPARE(builder.enumeratorCount(), 1);
+ enum2 = builder.enumerator(0);
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 2);
+ QCOMPARE(enum2.index(), 0);
+ QCOMPARE(enum2.key(0), QByteArray("XYZ"));
+ QCOMPARE(enum2.key(1), QByteArray("UVW"));
+ QCOMPARE(enum2.key(2), QByteArray());
+ QCOMPARE(enum2.value(0), 10);
+ QCOMPARE(enum2.value(1), 19);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfEnumerator("foo"), -1);
+ QCOMPARE(builder.indexOfEnumerator("bar"), 0);
+ QCOMPARE(builder.indexOfEnumerator("baz"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Enumerators));
+}
+
+void tst_QMetaObjectBuilder::classInfo()
+{
+ QMetaObjectBuilder builder;
+
+ // Add two items of class information and check their attributes.
+ QCOMPARE(builder.addClassInfo("foo", "value1"), 0);
+ QCOMPARE(builder.addClassInfo("bar", "value2"), 1);
+ QCOMPARE(builder.classInfoName(0), QByteArray("foo"));
+ QCOMPARE(builder.classInfoValue(0), QByteArray("value1"));
+ QCOMPARE(builder.classInfoName(1), QByteArray("bar"));
+ QCOMPARE(builder.classInfoValue(1), QByteArray("value2"));
+ QCOMPARE(builder.classInfoName(9), QByteArray());
+ QCOMPARE(builder.classInfoValue(9), QByteArray());
+ QCOMPARE(builder.classInfoCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfClassInfo("foo"), 0);
+ QCOMPARE(builder.indexOfClassInfo("bar"), 1);
+ QCOMPARE(builder.indexOfClassInfo("baz"), -1);
+
+ // Remove the first one and check again.
+ builder.removeClassInfo(0);
+ QCOMPARE(builder.classInfoName(0), QByteArray("bar"));
+ QCOMPARE(builder.classInfoValue(0), QByteArray("value2"));
+ QCOMPARE(builder.classInfoCount(), 1);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfClassInfo("foo"), -1);
+ QCOMPARE(builder.indexOfClassInfo("bar"), 0);
+ QCOMPARE(builder.indexOfClassInfo("baz"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::ClassInfos));
+}
+
+void tst_QMetaObjectBuilder::relatedMetaObject()
+{
+ QMetaObjectBuilder builder;
+
+ // Add two related meta objects and check their attributes.
+ QCOMPARE(builder.addRelatedMetaObject(&QObject::staticMetaObject), 0);
+ QCOMPARE(builder.addRelatedMetaObject(&staticMetaObject), 1);
+ QVERIFY(builder.relatedMetaObject(0) == &QObject::staticMetaObject);
+ QVERIFY(builder.relatedMetaObject(1) == &staticMetaObject);
+ QCOMPARE(builder.relatedMetaObjectCount(), 2);
+
+ // Remove the first one and check again.
+ builder.removeRelatedMetaObject(0);
+ QVERIFY(builder.relatedMetaObject(0) == &staticMetaObject);
+ QCOMPARE(builder.relatedMetaObjectCount(), 1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::RelatedMetaObjects));
+}
+
+static int smetacall(QMetaObject::Call, int, void **)
+{
+ return 0;
+}
+
+void tst_QMetaObjectBuilder::staticMetacall()
+{
+ QMetaObjectBuilder builder;
+ QVERIFY(!builder.staticMetacallFunction());
+ builder.setStaticMetacallFunction(smetacall);
+ QVERIFY(builder.staticMetacallFunction() == smetacall);
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::StaticMetacall));
+}
+
+// Copy the entire contents of a static QMetaObject and then check
+// that QMetaObjectBuilder will produce an exact copy as output.
+void tst_QMetaObjectBuilder::copyMetaObject()
+{
+ QMetaObjectBuilder builder(&QObject::staticMetaObject);
+ QMetaObject *meta = builder.toMetaObject();
+ QVERIFY(sameMetaObject(meta, &QObject::staticMetaObject));
+ qFree(meta);
+
+ QMetaObjectBuilder builder2(&staticMetaObject);
+ meta = builder2.toMetaObject();
+ QVERIFY(sameMetaObject(meta, &staticMetaObject));
+ qFree(meta);
+
+ QMetaObjectBuilder builder3(&SomethingOfEverything::staticMetaObject);
+ meta = builder3.toMetaObject();
+ QVERIFY(sameMetaObject(meta, &SomethingOfEverything::staticMetaObject));
+ qFree(meta);
+}
+
+// Serialize and deserialize a meta object and check that
+// it round-trips to the exact same value.
+void tst_QMetaObjectBuilder::serialize()
+{
+ // Full QMetaObjectBuilder
+ {
+ QMetaObjectBuilder builder(&SomethingOfEverything::staticMetaObject);
+ QMetaObject *meta = builder.toMetaObject();
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly | QIODevice::Append);
+ builder.serialize(stream);
+
+ QMetaObjectBuilder builder2;
+ QDataStream stream2(data);
+ QMap<QByteArray, const QMetaObject *> references;
+ references.insert(QByteArray("QLocale"), &QLocale::staticMetaObject);
+ builder2.deserialize(stream2, references);
+ builder2.setStaticMetacallFunction(builder.staticMetacallFunction());
+ QMetaObject *meta2 = builder2.toMetaObject();
+
+ QVERIFY(sameMetaObject(meta, meta2));
+ qFree(meta);
+ qFree(meta2);
+ }
+
+ // Partial QMetaObjectBuilder
+ {
+ QMetaObjectBuilder builder;
+ builder.setClassName("Test");
+ builder.addProperty("foo", "int");
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly | QIODevice::Append);
+ builder.serialize(stream);
+
+ QMetaObjectBuilder builder2;
+ QDataStream stream2(data);
+ builder2.deserialize(stream2, QMap<QByteArray, const QMetaObject *>());
+
+ QCOMPARE(builder.superClass(), builder2.superClass());
+ QCOMPARE(builder.className(), builder2.className());
+ QCOMPARE(builder.propertyCount(), builder2.propertyCount());
+ QCOMPARE(builder.property(0).name(), builder2.property(0).name());
+ QCOMPARE(builder.property(0).type(), builder2.property(0).type());
+ }
+}
+
+// Check that removing a method updates notify signals appropriately
+void tst_QMetaObjectBuilder::removeNotifySignal()
+{
+ QMetaObjectBuilder builder;
+
+ QMetaMethodBuilder method1 = builder.addSignal("foo(const QString&, int)");
+ QMetaMethodBuilder method2 = builder.addSignal("bar(QString)");
+
+ // Setup property
+ QMetaPropertyBuilder prop = builder.addProperty("prop", "const QString &");
+ prop.setNotifySignal(method2);
+ QVERIFY(prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 1);
+
+ // Remove non-notify signal
+ builder.removeMethod(0);
+ QVERIFY(prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 0);
+
+ // Remove notify signal
+ builder.removeMethod(0);
+ QVERIFY(!prop.hasNotifySignal());
+}
+
+// Check that the only changes to a "builder" relative to the default
+// state is specified by "members".
+bool tst_QMetaObjectBuilder::checkForSideEffects
+ (const QMetaObjectBuilder& builder,
+ QMetaObjectBuilder::AddMembers members)
+{
+ if ((members & QMetaObjectBuilder::ClassName) == 0) {
+ if (!builder.className().isEmpty())
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::SuperClass) == 0) {
+ if (builder.superClass() != &QObject::staticMetaObject)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Methods) == 0) {
+ if (builder.methodCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Constructors) == 0) {
+ if (builder.constructorCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Properties) == 0) {
+ if (builder.propertyCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Enumerators) == 0) {
+ if (builder.enumeratorCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::ClassInfos) == 0) {
+ if (builder.classInfoCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::RelatedMetaObjects) == 0) {
+ if (builder.relatedMetaObjectCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::StaticMetacall) == 0) {
+ if (builder.staticMetacallFunction() != 0)
+ return false;
+ }
+
+ return true;
+}
+
+static bool sameMethod(const QMetaMethod& method1, const QMetaMethod& method2)
+{
+ if (QByteArray(method1.signature()) != QByteArray(method2.signature()))
+ return false;
+
+ if (QByteArray(method1.typeName()) != QByteArray(method2.typeName()))
+ return false;
+
+ if (method1.parameterNames() != method2.parameterNames())
+ return false;
+
+ if (QByteArray(method1.tag()) != QByteArray(method2.tag()))
+ return false;
+
+ if (method1.access() != method2.access())
+ return false;
+
+ if (method1.methodType() != method2.methodType())
+ return false;
+
+ if (method1.attributes() != method2.attributes())
+ return false;
+
+ return true;
+}
+
+static bool sameProperty(const QMetaProperty& prop1, const QMetaProperty& prop2)
+{
+ if (QByteArray(prop1.name()) != QByteArray(prop2.name()))
+ return false;
+
+ if (QByteArray(prop1.typeName()) != QByteArray(prop2.typeName()))
+ return false;
+
+ if (prop1.isReadable() != prop2.isReadable() ||
+ prop1.isWritable() != prop2.isWritable() ||
+ prop1.isResettable() != prop2.isResettable() ||
+ prop1.isDesignable() != prop2.isDesignable() ||
+ prop1.isScriptable() != prop2.isScriptable() ||
+ prop1.isStored() != prop2.isStored() ||
+ prop1.isEditable() != prop2.isEditable() ||
+ prop1.isUser() != prop2.isUser() ||
+ prop1.isFlagType() != prop2.isFlagType() ||
+ prop1.isEnumType() != prop2.isEnumType() ||
+ prop1.hasNotifySignal() != prop2.hasNotifySignal() ||
+ prop1.hasStdCppSet() != prop2.hasStdCppSet())
+ return false;
+
+ if (prop1.hasNotifySignal()) {
+ if (prop1.notifySignalIndex() != prop2.notifySignalIndex())
+ return false;
+ }
+
+ return true;
+}
+
+static bool sameEnumerator(const QMetaEnum& enum1, const QMetaEnum& enum2)
+{
+ if (QByteArray(enum1.name()) != QByteArray(enum2.name()))
+ return false;
+
+ if (enum1.isFlag() != enum2.isFlag())
+ return false;
+
+ if (enum1.keyCount() != enum2.keyCount())
+ return false;
+
+ for (int index = 0; index < enum1.keyCount(); ++index) {
+ if (QByteArray(enum1.key(index)) != QByteArray(enum2.key(index)))
+ return false;
+ if (enum1.value(index) != enum2.value(index))
+ return false;
+ }
+
+ if (QByteArray(enum1.scope()) != QByteArray(enum2.scope()))
+ return false;
+
+ return true;
+}
+
+// Determine if two meta objects are identical.
+bool tst_QMetaObjectBuilder::sameMetaObject
+ (const QMetaObject *meta1, const QMetaObject *meta2)
+{
+ int index;
+
+ if (strcmp(meta1->className(), meta2->className()) != 0)
+ return false;
+
+ if (meta1->superClass() != meta2->superClass())
+ return false;
+
+ if (meta1->constructorCount() != meta2->constructorCount() ||
+ meta1->methodCount() != meta2->methodCount() ||
+ meta1->enumeratorCount() != meta2->enumeratorCount() ||
+ meta1->propertyCount() != meta2->propertyCount() ||
+ meta1->classInfoCount() != meta2->classInfoCount())
+ return false;
+
+ for (index = 0; index < meta1->constructorCount(); ++index) {
+ if (!sameMethod(meta1->constructor(index), meta2->constructor(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->methodCount(); ++index) {
+ if (!sameMethod(meta1->method(index), meta2->method(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->propertyCount(); ++index) {
+ if (!sameProperty(meta1->property(index), meta2->property(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->enumeratorCount(); ++index) {
+ if (!sameEnumerator(meta1->enumerator(index), meta2->enumerator(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->classInfoCount(); ++index) {
+ if (QByteArray(meta1->classInfo(index).name()) !=
+ QByteArray(meta2->classInfo(index).name()))
+ return false;
+ if (QByteArray(meta1->classInfo(index).value()) !=
+ QByteArray(meta2->classInfo(index).value()))
+ return false;
+ }
+
+ const QMetaObject **objects1 = 0;
+ const QMetaObject **objects2 = 0;
+ if (meta1->d.data[0] == meta2->d.data[0] && meta1->d.data[0] >= 2) {
+ QMetaObjectExtraData *extra1 = (QMetaObjectExtraData *)(meta1->d.extradata);
+ QMetaObjectExtraData *extra2 = (QMetaObjectExtraData *)(meta2->d.extradata);
+ if (extra1 && !extra2)
+ return false;
+ if (extra2 && !extra1)
+ return false;
+ if (extra1 && extra2) {
+ if (extra1->static_metacall != extra2->static_metacall)
+ return false;
+ objects1 = extra1->objects;
+ objects2 = extra1->objects;
+ }
+ } else if (meta1->d.data[0] == meta2->d.data[0] && meta1->d.data[0] == 1) {
+ objects1 = (const QMetaObject **)(meta1->d.extradata);
+ objects2 = (const QMetaObject **)(meta2->d.extradata);
+ }
+ if (objects1 && !objects2)
+ return false;
+ if (objects2 && !objects1)
+ return false;
+ if (objects1 && objects2) {
+ while (*objects1 != 0 && *objects2 != 0) {
+ if (*objects1 != *objects2)
+ return false;
+ ++objects1;
+ ++objects2;
+ }
+ }
+
+ return true;
+}
+
+QTEST_MAIN(tst_QMetaObjectBuilder)
+
+#include "tst_qmetaobjectbuilder.moc"
diff --git a/tests/auto/declarative/qmlanimations/data/attached.qml b/tests/auto/declarative/qmlanimations/data/attached.qml
new file mode 100644
index 0000000..0fb6f8c
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/attached.qml
@@ -0,0 +1,34 @@
+import Qt 4.6
+
+Rectangle {
+ width: 180; height: 200;
+
+ Component {
+ id: delegate
+ Rectangle {
+ id: wrapper
+ width: 180; height: 200
+ color: "blue"
+
+ states: State {
+ name: "otherState"
+ PropertyChanges { target: wrapper; color: "green" }
+ }
+
+ transitions: Transition {
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true }
+ ScriptAction { script: console.log(ListView.delayRemove ? "on" : "off") }
+ }
+
+ Component.onCompleted: {
+ console.log(ListView.delayRemove ? "on" : "off");
+ wrapper.state = "otherState"
+ }
+ }
+ }
+
+ ListView {
+ model: 1
+ delegate: delegate
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/badproperty1.qml b/tests/auto/declarative/qmlanimations/data/badproperty1.qml
new file mode 100644
index 0000000..d31cae9
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/badproperty1.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Rectangle {
+ id: wrapper
+ width: 240
+ height: 320
+ Rectangle {
+ id: myRect
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+ states: State {
+ name: "state1"
+ PropertyChanges { target: myRect; border.color: "blue" }
+ }
+ transitions: Transition {
+ ColorAnimation { target: myRect; to: "red"; property: "border.colr"; duration: 1000 }
+ }
+ Component.onCompleted: if (wrapper.state == "state1") wrapper.state = ""; else wrapper.state = "state1";
+}
diff --git a/tests/auto/declarative/qmlanimations/data/badproperty2.qml b/tests/auto/declarative/qmlanimations/data/badproperty2.qml
new file mode 100644
index 0000000..3b8b111
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/badproperty2.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Rectangle {
+ id: wrapper
+ width: 240
+ height: 320
+ Rectangle {
+ id: myRect
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+ states: State {
+ name: "state1"
+ PropertyChanges { target: myRect; border.color: "blue" }
+ }
+ transitions: Transition {
+ ColorAnimation { target: myRect; to: "red"; property: "border"; duration: 1000 }
+ }
+ Component.onCompleted: if (wrapper.state == "state1") wrapper.state = ""; else wrapper.state = "state1";
+}
diff --git a/tests/auto/declarative/qmlanimations/data/badtype1.qml b/tests/auto/declarative/qmlanimations/data/badtype1.qml
new file mode 100644
index 0000000..6381df3
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/badtype1.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ Rectangle {
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: PropertyAnimation { from: "blue"; to: "green"; }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/badtype2.qml b/tests/auto/declarative/qmlanimations/data/badtype2.qml
new file mode 100644
index 0000000..8d57e41
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/badtype2.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ Rectangle {
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { from: "blue"; to: "green"; }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/badtype3.qml b/tests/auto/declarative/qmlanimations/data/badtype3.qml
new file mode 100644
index 0000000..c4867c3
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/badtype3.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ Rectangle {
+ color: "red"
+ color: ColorAnimation { from: 10; to: 15; }
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/badtype4.qml b/tests/auto/declarative/qmlanimations/data/badtype4.qml
new file mode 100644
index 0000000..a4cf265
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/badtype4.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+Rectangle {
+ id: wrapper
+ width: 240
+ height: 320
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: if (wrapper.state == "state1") wrapper.state = ""; else wrapper.state = "state1";
+ }
+ }
+ states: State {
+ name: "state1"
+ PropertyChanges { target: myRect; x: 200; color: "blue" }
+ }
+ transitions: Transition {
+ //comment out each in turn to make sure each only animates the relevant property
+ ColorAnimation { matchProperties: "x,color"; duration: 1000 } //x is real, color is color
+ NumberAnimation { matchProperties: "x,color"; duration: 1000 } //x is real, color is color
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/dotproperty.qml b/tests/auto/declarative/qmlanimations/data/dotproperty.qml
new file mode 100644
index 0000000..369491f
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/dotproperty.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+Rectangle {
+ id: wrapper
+ width: 240
+ height: 320
+ Rectangle {
+ id: myRect
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: if (wrapper.state == "state1") wrapper.state = ""; else wrapper.state = "state1";
+ }
+ }
+ states: State {
+ name: "state1"
+ PropertyChanges { target: myRect; border.color: "blue" }
+ }
+ transitions: Transition {
+ ColorAnimation { matchProperties: "border.color"; duration: 1000 }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/mixedtype1.qml b/tests/auto/declarative/qmlanimations/data/mixedtype1.qml
new file mode 100644
index 0000000..87f4f16
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/mixedtype1.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Rectangle {
+ id: wrapper
+ width: 240
+ height: 320
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: if (wrapper.state == "state1") wrapper.state = ""; else wrapper.state = "state1";
+ }
+ }
+ states: State {
+ name: "state1"
+ PropertyChanges { target: myRect; x: 200; border.width: 10 }
+ }
+ transitions: Transition {
+ PropertyAnimation { matchProperties: "x,border.width"; duration: 1000 } //x is real, border.width is int
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/mixedtype2.qml b/tests/auto/declarative/qmlanimations/data/mixedtype2.qml
new file mode 100644
index 0000000..d555abd
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/mixedtype2.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+Rectangle {
+ id: wrapper
+ width: 240
+ height: 320
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: if (wrapper.state == "state1") wrapper.state = ""; else wrapper.state = "state1";
+ }
+ }
+ states: State {
+ name: "state1"
+ PropertyChanges { target: myRect; x: 200; color: "blue" }
+ }
+ transitions: Transition {
+ PropertyAnimation { matchProperties: "x,color"; duration: 1000 } //x is real, color is color
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/properties.qml b/tests/auto/declarative/qmlanimations/data/properties.qml
new file mode 100644
index 0000000..7e73f57
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/properties.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { to: 200 }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/properties2.qml b/tests/auto/declarative/qmlanimations/data/properties2.qml
new file mode 100644
index 0000000..86568ca
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/properties2.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { matchTargets: theRect; matchProperties: "x"; to: 200; }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/properties3.qml b/tests/auto/declarative/qmlanimations/data/properties3.qml
new file mode 100644
index 0000000..ff08885
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/properties3.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { target: theRect; property: "x"; to: 300; }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/properties4.qml b/tests/auto/declarative/qmlanimations/data/properties4.qml
new file mode 100644
index 0000000..dab7e5f
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/properties4.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { target: theRect; property: "y"; to: 200; }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/properties5.qml b/tests/auto/declarative/qmlanimations/data/properties5.qml
new file mode 100644
index 0000000..56e0be8
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/properties5.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { matchTargets: theRect; matchProperties: "y"; to: 200; }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/propertiesTransition.qml b/tests/auto/declarative/qmlanimations/data/propertiesTransition.qml
new file mode 100644
index 0000000..75603b9
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/propertiesTransition.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: theRect
+ x: 200
+ }
+ }
+ transitions: Transition {
+ NumberAnimation { matchTargets: theRect; matchProperties: "x" }
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.state = "moved"
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/propertiesTransition2.qml b/tests/auto/declarative/qmlanimations/data/propertiesTransition2.qml
new file mode 100644
index 0000000..ae59157
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/propertiesTransition2.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: theRect
+ x: 200
+ }
+ }
+ transitions: Transition {
+ NumberAnimation { target: theRect; property: "y"; to: 200 }
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.state = "moved"
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/propertiesTransition3.qml b/tests/auto/declarative/qmlanimations/data/propertiesTransition3.qml
new file mode 100644
index 0000000..eedba7b
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/propertiesTransition3.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: theRect
+ x: 200
+ }
+ }
+ transitions: Transition {
+ NumberAnimation { matchTargets: theRect; matchProperties: "y" }
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.state = "moved"
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/propertiesTransition4.qml b/tests/auto/declarative/qmlanimations/data/propertiesTransition4.qml
new file mode 100644
index 0000000..301f796
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/propertiesTransition4.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: theRect
+ x: 200
+ }
+ }
+ transitions: Transition {
+ NumberAnimation { target: theRect; matchProperties: "x" }
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.state = "moved"
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/propertiesTransition5.qml b/tests/auto/declarative/qmlanimations/data/propertiesTransition5.qml
new file mode 100644
index 0000000..565c519
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/propertiesTransition5.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: theRect
+ x: 200
+ }
+ }
+ transitions: Transition {
+ NumberAnimation { matchTargets: theRect; property: "x" }
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.state = "moved"
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/propertiesTransition6.qml b/tests/auto/declarative/qmlanimations/data/propertiesTransition6.qml
new file mode 100644
index 0000000..b541dab
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/propertiesTransition6.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: theRect
+ objectName: "TheRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ }
+
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: theRect
+ x: 200
+ }
+ }
+ transitions: Transition {
+ NumberAnimation { matchTargets: theItem; matchProperties: "x" }
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.state = "moved"
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/valuesource.qml b/tests/auto/declarative/qmlanimations/data/valuesource.qml
new file mode 100644
index 0000000..c35063d
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/valuesource.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { id: anim; objectName: "MyAnim"; to: 200 }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/data/valuesource2.qml b/tests/auto/declarative/qmlanimations/data/valuesource2.qml
new file mode 100644
index 0000000..1a60542
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/data/valuesource2.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ color: "red"
+ width: 50; height: 50
+ x: 100; y: 100
+ x: NumberAnimation { id: anim; objectName: "MyAnim"; running: false; to: 200 }
+ }
+}
diff --git a/tests/auto/declarative/qmlanimations/qmlanimations.pro b/tests/auto/declarative/qmlanimations/qmlanimations.pro
new file mode 100644
index 0000000..447fb0f
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/qmlanimations.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlanimations.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlanimations/tst_qmlanimations.cpp b/tests/auto/declarative/qmlanimations/tst_qmlanimations.cpp
new file mode 100644
index 0000000..17a1453
--- /dev/null
+++ b/tests/auto/declarative/qmlanimations/tst_qmlanimations.cpp
@@ -0,0 +1,611 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlview.h>
+#include <private/qmlgraphicsrectangle_p.h>
+#include <private/qmlanimation_p.h>
+#include <QVariantAnimation>
+
+class tst_animations : public QObject
+{
+ Q_OBJECT
+public:
+ tst_animations() {}
+
+private slots:
+ void simpleProperty();
+ void simpleNumber();
+ void simpleColor();
+ void alwaysRunToEnd();
+ void complete();
+ void resume();
+ void dotProperty();
+ void badTypes();
+ void badProperties();
+ void mixedTypes();
+ void properties();
+ void propertiesTransition();
+ void easingStringConversion();
+ void invalidDuration();
+ void attached();
+ void propertyValueSourceDefaultStart();
+};
+
+#define QTIMED_COMPARE(lhs, rhs) do { \
+ for (int ii = 0; ii < 5; ++ii) { \
+ if (lhs == rhs) \
+ break; \
+ QTest::qWait(50); \
+ } \
+ QCOMPARE(lhs, rhs); \
+} while (false)
+
+void tst_animations::simpleProperty()
+{
+ QmlGraphicsRectangle rect;
+ QmlPropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("pos");
+ animation.setTo(QPointF(200,200));
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "pos");
+ QVERIFY(animation.to().toPointF() == QPointF(200,200));
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTIMED_COMPARE(rect.pos(), QPointF(200,200));
+
+ rect.setPos(0,0);
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.pos(), QPointF(100,100));
+}
+
+void tst_animations::simpleNumber()
+{
+ QmlGraphicsRectangle rect;
+ QmlNumberAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setTo(200);
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "x");
+ QVERIFY(animation.to() == 200);
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTIMED_COMPARE(rect.x(), qreal(200));
+
+ rect.setX(0);
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.x(), qreal(100));
+}
+
+void tst_animations::simpleColor()
+{
+ QmlGraphicsRectangle rect;
+ QmlColorAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("color");
+ animation.setTo(QColor("red"));
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "color");
+ QVERIFY(animation.to() == QColor("red"));
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTIMED_COMPARE(rect.color(), QColor("red"));
+
+ rect.setColor(QColor("blue"));
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
+
+ rect.setColor(QColor("green"));
+ animation.setFrom(QColor("blue"));
+ QVERIFY(animation.from() == QColor("blue"));
+ animation.restart();
+ QCOMPARE(rect.color(), QColor("blue"));
+ QVERIFY(animation.isRunning());
+ animation.setCurrentTime(125);
+ QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
+}
+
+void tst_animations::alwaysRunToEnd()
+{
+ QmlGraphicsRectangle rect;
+ QmlPropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setTo(200);
+ animation.setDuration(1000);
+ animation.setRepeat(true);
+ animation.setAlwaysRunToEnd(true);
+ QVERIFY(animation.repeat() == true);
+ QVERIFY(animation.alwaysRunToEnd() == true);
+ animation.start();
+ QTest::qWait(1500);
+ animation.stop();
+ QVERIFY(rect.x() != qreal(200));
+ QTest::qWait(500);
+ QTIMED_COMPARE(rect.x(), qreal(200));
+}
+
+void tst_animations::complete()
+{
+ QmlGraphicsRectangle rect;
+ QmlPropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setFrom(1);
+ animation.setTo(200);
+ animation.setDuration(500);
+ QVERIFY(animation.from() == 1);
+ animation.start();
+ QTest::qWait(50);
+ animation.stop();
+ QVERIFY(rect.x() != qreal(200));
+ animation.start();
+ QTest::qWait(50);
+ QVERIFY(animation.isRunning());
+ animation.complete();
+ QCOMPARE(rect.x(), qreal(200));
+}
+
+void tst_animations::resume()
+{
+ QmlGraphicsRectangle rect;
+ QmlPropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setFrom(10);
+ animation.setTo(200);
+ animation.setDuration(500);
+ QVERIFY(animation.from() == 10);
+
+ animation.start();
+ QTest::qWait(50);
+ animation.pause();
+ qreal x = rect.x();
+ QVERIFY(x != qreal(200));
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+
+ animation.resume();
+ QVERIFY(animation.isRunning());
+ QVERIFY(!animation.isPaused());
+ QTest::qWait(50);
+ animation.stop();
+ QVERIFY(rect.x() > x);
+}
+
+void tst_animations::dotProperty()
+{
+ QmlGraphicsRectangle rect;
+ QmlNumberAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("border.width");
+ animation.setTo(10);
+ animation.start();
+ QTest::qWait(animation.duration()+50);
+ QTIMED_COMPARE(rect.border()->width(), 10);
+
+ rect.border()->setWidth(0);
+ animation.start();
+ animation.pause();
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.border()->width(), 5);
+}
+
+void tst_animations::badTypes()
+{
+ //don't crash
+ {
+ QmlView *view = new QmlView;
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/badtype1.qml"));
+
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+
+ //make sure we get a compiler error
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/badtype2.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "QmlComponent: Component is not ready");
+ c.create();
+
+ QVERIFY(c.errors().count() == 1);
+ QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: double expected"));
+ }
+
+ //make sure we get a compiler error
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/badtype3.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "QmlComponent: Component is not ready");
+ c.create();
+
+ QVERIFY(c.errors().count() == 1);
+ QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected"));
+ }
+
+ //don't crash
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/badtype4.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("state1");
+ QTest::qWait(1000 + 50);
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("MyRect");
+ QVERIFY(myRect);
+ QCOMPARE(myRect->x(),qreal(200));
+ }
+}
+
+void tst_animations::badProperties()
+{
+ //make sure we get a runtime error
+ {
+ QmlEngine engine;
+
+ QmlComponent c1(&engine, QUrl::fromLocalFile(SRCDIR "/data/badproperty1.qml"));
+ QByteArray message = "QML ColorAnimation (" + QUrl::fromLocalFile(SRCDIR "/data/badproperty1.qml").toString().toUtf8() + ":18:9) Cannot animate non-existant property \"border.colr\"";
+ QTest::ignoreMessage(QtWarningMsg, message);
+ QTest::ignoreMessage(QtWarningMsg, message); // why twice?
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c1.create());
+ QVERIFY(rect);
+
+ QmlComponent c2(&engine, QUrl::fromLocalFile(SRCDIR "/data/badproperty2.qml"));
+ message = "QML ColorAnimation (" + QUrl::fromLocalFile(SRCDIR "/data/badproperty2.qml").toString().toUtf8() + ":18:9) Cannot animate read-only property \"border\"";
+ QTest::ignoreMessage(QtWarningMsg, message);
+ QTest::ignoreMessage(QtWarningMsg, message); // why twice?
+ rect = qobject_cast<QmlGraphicsRectangle*>(c2.create());
+ QVERIFY(rect);
+
+ //### should we warn here are well?
+ //rect->setState("state1");
+ }
+}
+
+//test animating mixed types with property animation in a transition
+//for example, int + real; color + real; etc
+void tst_animations::mixedTypes()
+{
+ //assumes border.width stats a real -- not real robust
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/mixedtype1.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("state1");
+ QTest::qWait(500);
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("MyRect");
+ QVERIFY(myRect);
+
+ //rather inexact -- is there a better way?
+ QVERIFY(myRect->x() > 100 && myRect->x() < 200);
+ QVERIFY(myRect->border()->width() > 1 && myRect->border()->width() < 10);
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/mixedtype2.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("state1");
+ QTest::qWait(500);
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("MyRect");
+ QVERIFY(myRect);
+
+ //rather inexact -- is there a better way?
+ QVERIFY(myRect->x() > 100 && myRect->x() < 200);
+ QVERIFY(myRect->color() != QColor("red") && myRect->color() != QColor("blue"));
+ }
+}
+
+void tst_animations::properties()
+{
+ const int waitDuration = 300;
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/properties.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/properties2.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/properties3.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(300));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/properties4.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->y(),qreal(200));
+ QTIMED_COMPARE(myRect->x(),qreal(100));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/properties5.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QEXPECT_FAIL("", "QTBUG-8072", Continue);
+ QTIMED_COMPARE(myRect->x(),qreal(100));
+ QTIMED_COMPARE(myRect->y(),qreal(100));
+ }
+}
+
+void tst_animations::propertiesTransition()
+{
+ const int waitDuration = 300;
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertiesTransition.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertiesTransition2.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ rect->setState("moved");
+ QCOMPARE(myRect->x(),qreal(200));
+ QCOMPARE(myRect->y(),qreal(100));
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->y(),qreal(200));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertiesTransition3.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (" + QUrl::fromLocalFile(SRCDIR "/data/propertiesTransition4.qml").toString().toUtf8() + ":22:9) matchTargets/matchProperties/exclude and target/property are mutually exclusive.");
+ rect->setState("moved");
+ QCOMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertiesTransition4.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (" + QUrl::fromLocalFile(SRCDIR "/data/propertiesTransition5.qml").toString().toUtf8() + ":22:9) matchTargets/matchProperties/exclude and target/property are mutually exclusive.");
+ rect->setState("moved");
+ QCOMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertiesTransition5.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ //### should output warning at some point -- theItem doesn't exist
+ QmlGraphicsRectangle *myRect = rect->findChild<QmlGraphicsRectangle*>("TheRect");
+ QVERIFY(myRect);
+ rect->setState("moved");
+ QCOMPARE(myRect->x(),qreal(200));
+ }
+}
+
+void tst_animations::easingStringConversion()
+{
+ QmlNumberAnimation *animation = new QmlNumberAnimation;
+ animation->setEasing("easeInOutQuad");
+ QCOMPARE(animation->easing(),QLatin1String("easeInOutQuad"));
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve(), QEasingCurve(QEasingCurve::InOutQuad));
+
+ animation->setEasing("OutQuad");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve(), QEasingCurve(QEasingCurve::OutQuad));
+
+ animation->setEasing("easeOutBounce(amplitude: 5)");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::OutBounce);
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().amplitude(), qreal(5));
+
+ animation->setEasing("easeOutElastic(amplitude: 5, period: 3)");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::OutElastic);
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().amplitude(), qreal(5));
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().period(), qreal(3));
+
+ animation->setEasing("easeInOutBack(overshoot: 2)");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::InOutBack);
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().overshoot(), qreal(2));
+
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (unknown location) Unmatched parenthesis in easing function \"easeInOutBack(overshoot: 2\"");
+ animation->setEasing("easeInOutBack(overshoot: 2");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::Linear);
+
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (unknown location) Easing function \"InOutBack(overshoot: 2)\" must start with \"ease\"");
+ animation->setEasing("InOutBack(overshoot: 2)");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::Linear);
+
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (unknown location) Unknown easing curve \"NonExistantEase\"");
+ animation->setEasing("NonExistantEase");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::Linear);
+
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (unknown location) Improperly specified parameter in easing function \"easeInOutElastic(amplitude 5)\"");
+ animation->setEasing("easeInOutElastic(amplitude 5)");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::InOutElastic);
+
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (unknown location) Improperly specified parameter in easing function \"easeInOutElastic(amplitude: yes)\"");
+ animation->setEasing("easeInOutElastic(amplitude: yes)");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::InOutElastic);
+ QVERIFY(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().amplitude() != qreal(5));
+
+ QTest::ignoreMessage(QtWarningMsg, "QML NumberAnimation (unknown location) Unknown easing parameter \"nonexistantproperty\"");
+ animation->setEasing("easeOutQuad(nonexistantproperty: 12)");
+ QCOMPARE(static_cast<QVariantAnimation*>(((QmlAbstractAnimation*)animation)->qtAnimation())->easingCurve().type(), QEasingCurve::OutQuad);
+
+ delete animation;
+}
+
+void tst_animations::invalidDuration()
+{
+ QmlPropertyAnimation *animation = new QmlPropertyAnimation;
+ QTest::ignoreMessage(QtWarningMsg, "QML PropertyAnimation (unknown location) Cannot set a duration of < 0");
+ animation->setDuration(-1);
+ QCOMPARE(animation->duration(), 250);
+
+ QmlPauseAnimation *pauseAnimation = new QmlPauseAnimation;
+ QTest::ignoreMessage(QtWarningMsg, "QML PauseAnimation (unknown location) Cannot set a duration of < 0");
+ pauseAnimation->setDuration(-1);
+ QCOMPARE(pauseAnimation->duration(), 250);
+}
+
+void tst_animations::attached()
+{
+ QmlEngine engine;
+
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/attached.qml"));
+ QTest::ignoreMessage(QtDebugMsg, "off");
+ QTest::ignoreMessage(QtDebugMsg, "on");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+}
+
+void tst_animations::propertyValueSourceDefaultStart()
+{
+ {
+ QmlEngine engine;
+
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/valuesource.qml"));
+
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlAbstractAnimation *myAnim = rect->findChild<QmlAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim);
+ QVERIFY(myAnim->isRunning());
+ }
+
+ {
+ QmlEngine engine;
+
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/valuesource2.qml"));
+
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlAbstractAnimation *myAnim = rect->findChild<QmlAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim);
+ QVERIFY(myAnim->isRunning() == false);
+ }
+}
+
+QTEST_MAIN(tst_animations)
+
+#include "tst_qmlanimations.moc"
diff --git a/tests/auto/declarative/qmlbehaviors/data/binding.qml b/tests/auto/declarative/qmlbehaviors/data/binding.qml
new file mode 100644
index 0000000..e0c3321
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/binding.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ property real basex : 0
+ property real movedx: 200
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: basex
+ x: Behavior { NumberAnimation { duration: 200; } }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ x: movedx
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/color.qml b/tests/auto/declarative/qmlbehaviors/data/color.qml
new file mode 100644
index 0000000..6598703
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/color.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100;
+ color: "green"
+ color: Behavior { ColorAnimation { duration: 200; } }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "red"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ color: "red"
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/cpptrigger.qml b/tests/auto/declarative/qmlbehaviors/data/cpptrigger.qml
new file mode 100644
index 0000000..ba507c4
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/cpptrigger.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior { NumberAnimation { duration: 200; } }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/disabled.qml b/tests/auto/declarative/qmlbehaviors/data/disabled.qml
new file mode 100644
index 0000000..e7b8d51
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/disabled.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior {
+ objectName: "MyBehavior";
+ enabled: false
+ NumberAnimation { duration: 200; }
+ }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/empty.qml b/tests/auto/declarative/qmlbehaviors/data/empty.qml
new file mode 100644
index 0000000..412e26c
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/empty.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior {}
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/groupProperty.qml b/tests/auto/declarative/qmlbehaviors/data/groupProperty.qml
new file mode 100644
index 0000000..4f127c1
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/groupProperty.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ pos: Behavior { PropertyAnimation { duration: 200; } }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ pos: Qt.point(200,0);
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/groupProperty2.qml b/tests/auto/declarative/qmlbehaviors/data/groupProperty2.qml
new file mode 100644
index 0000000..19d70b6
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/groupProperty2.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ pos.x: Behavior { NumberAnimation { duration: 200; } }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ pos.x: 200;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/loop.qml b/tests/auto/declarative/qmlbehaviors/data/loop.qml
new file mode 100644
index 0000000..5f2c057
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/loop.qml
@@ -0,0 +1,19 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior { NumberAnimation { duration: 200; } }
+ onXChanged: x = 100;
+ }
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: rect
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/nonSelecting.qml b/tests/auto/declarative/qmlbehaviors/data/nonSelecting.qml
new file mode 100644
index 0000000..ba36d93
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/nonSelecting.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior {
+ objectName: "MyBehavior";
+ NumberAnimation { target: rect; property: "x"; duration: 200; }
+ }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/nonSelecting2.qml b/tests/auto/declarative/qmlbehaviors/data/nonSelecting2.qml
new file mode 100644
index 0000000..e9849eb
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/nonSelecting2.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior {
+ objectName: "MyBehavior";
+ NumberAnimation { matchTargets: rect; matchProperties: "y"; duration: 200; }
+ }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/parent.qml b/tests/auto/declarative/qmlbehaviors/data/parent.qml
new file mode 100644
index 0000000..4f4911b
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/parent.qml
@@ -0,0 +1,28 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ parent: Behavior {
+ SequentialAnimation {
+ PauseAnimation { duration: 200 }
+ PropertyAction {}
+ }
+ }
+ }
+ Item {
+ id: newParent
+ objectName: "NewParent"
+ x: 100
+ }
+ states: State {
+ name: "reparented"
+ PropertyChanges {
+ target: rect
+ parent: newParent
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/reassignedAnimation.qml b/tests/auto/declarative/qmlbehaviors/data/reassignedAnimation.qml
new file mode 100644
index 0000000..693a595
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/reassignedAnimation.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior {
+ objectName: "MyBehavior"
+ NumberAnimation { duration: 200 }
+ NumberAnimation { duration: 1000 }
+ }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/scripttrigger.qml b/tests/auto/declarative/qmlbehaviors/data/scripttrigger.qml
new file mode 100644
index 0000000..4383a0b
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/scripttrigger.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+
+ onColorChanged: {
+ rect.x = 200
+ }
+
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior { NumberAnimation { duration: 200; } }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/data/simple.qml b/tests/auto/declarative/qmlbehaviors/data/simple.qml
new file mode 100644
index 0000000..37c3915
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/data/simple.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ x: Behavior {
+ objectName: "MyBehavior";
+ NumberAnimation { duration: 200; }
+ }
+ }
+ MouseRegion {
+ id: clicker
+ anchors.fill: parent
+ }
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: rect
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlbehaviors/qmlbehaviors.pro b/tests/auto/declarative/qmlbehaviors/qmlbehaviors.pro
new file mode 100644
index 0000000..1e685ee
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/qmlbehaviors.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlbehaviors.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlbehaviors/tst_qmlbehaviors.cpp b/tests/auto/declarative/qmlbehaviors/tst_qmlbehaviors.cpp
new file mode 100644
index 0000000..61023a2
--- /dev/null
+++ b/tests/auto/declarative/qmlbehaviors/tst_qmlbehaviors.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlview.h>
+#include <private/qmlgraphicsrectangle_p.h>
+#include <private/qmlbehavior_p.h>
+#include <private/qmlanimation_p.h>
+
+class tst_behaviors : public QObject
+{
+ Q_OBJECT
+public:
+ tst_behaviors() {}
+
+private slots:
+ void simpleBehavior();
+ void scriptTriggered();
+ void cppTriggered();
+ void loop();
+ void colorBehavior();
+ void parentBehavior();
+ void replaceBinding();
+ //void transitionOverrides();
+ void group();
+ void emptyBehavior();
+ void nonSelectingBehavior();
+ void reassignedAnimation();
+ void disabled();
+};
+
+void tst_behaviors::simpleBehavior()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/simple.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+ QVERIFY(qobject_cast<QmlBehavior*>(rect->findChild<QmlBehavior*>("MyBehavior"))->animation());
+
+ rect->setState("moved");
+ QTest::qWait(100);
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered
+}
+
+void tst_behaviors::scriptTriggered()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/scripttrigger.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setColor(QColor("red"));
+ QTest::qWait(100);
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered
+}
+
+void tst_behaviors::cppTriggered()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/cpptrigger.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect);
+
+ innerRect->setProperty("x", 200);
+ QTest::qWait(100);
+ qreal x = innerRect->x();
+ QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered
+}
+
+void tst_behaviors::loop()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/loop.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ //don't crash
+ rect->setState("moved");
+}
+
+void tst_behaviors::colorBehavior()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/color.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("red");
+ QTest::qWait(100);
+ QColor color = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->color();
+ QVERIFY(color != QColor("red") && color != QColor("green")); //i.e. the behavior has been triggered
+}
+
+void tst_behaviors::parentBehavior()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/parent.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("reparented");
+ QTest::qWait(100);
+ QmlGraphicsItem *newParent = rect->findChild<QmlGraphicsItem*>("NewParent");
+ QmlGraphicsItem *parent = rect->findChild<QmlGraphicsRectangle*>("MyRect")->parentItem();
+ QVERIFY(parent != newParent);
+ QTest::qWait(300);
+ parent = rect->findChild<QmlGraphicsRectangle*>("MyRect")->parentItem();
+ QVERIFY(parent == newParent);
+}
+
+void tst_behaviors::replaceBinding()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/binding.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ QTest::qWait(100);
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect);
+ qreal x = innerRect->x();
+ QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered
+ QTest::qWait(300);
+ QCOMPARE(innerRect->x(), (qreal)200);
+ rect->setProperty("basex", 10);
+ QCOMPARE(innerRect->x(), (qreal)200);
+ rect->setProperty("movedx", 210);
+ QTest::qWait(300);
+ QCOMPARE(innerRect->x(), (qreal)210);
+
+ rect->setState("");
+ QTest::qWait(100);
+ x = innerRect->x();
+ QVERIFY(x > 10 && x < 210); //i.e. the behavior has been triggered
+ QTest::qWait(300);
+ QCOMPARE(innerRect->x(), (qreal)10);
+ rect->setProperty("movedx", 200);
+ QCOMPARE(innerRect->x(), (qreal)10);
+ rect->setProperty("basex", 20);
+ QTest::qWait(300);
+ QCOMPARE(innerRect->x(), (qreal)20);
+}
+
+void tst_behaviors::group()
+{
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/groupProperty.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ QTest::qWait(100);
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/groupProperty2.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ QTest::qWait(100);
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered
+ }
+}
+
+void tst_behaviors::emptyBehavior()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/empty.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+}
+
+void tst_behaviors::nonSelectingBehavior()
+{
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/nonSelecting.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+ }
+
+ {
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/nonSelecting2.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+ }
+}
+
+void tst_behaviors::reassignedAnimation()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/reassignedAnimation.qml"));
+ QTest::ignoreMessage(QtWarningMsg, QString("QML Behavior (" + QUrl::fromLocalFile(SRCDIR "/data/reassignedAnimation.qml").toString() + ":9:12) Can't change the animation assigned to a Behavior.").toUtf8().constData());
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+ QCOMPARE(qobject_cast<QmlNumberAnimation*>(
+ qobject_cast<QmlBehavior*>(
+ rect->findChild<QmlBehavior*>("MyBehavior"))->animation())->duration(), 200);
+}
+
+void tst_behaviors::disabled()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/disabled.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+ QCOMPARE(rect->findChild<QmlBehavior*>("MyBehavior")->enabled(), false);
+
+ rect->setState("moved");
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+
+}
+
+QTEST_MAIN(tst_behaviors)
+
+#include "tst_qmlbehaviors.moc"
diff --git a/tests/auto/declarative/qmlbinding/data/test-binding.qml b/tests/auto/declarative/qmlbinding/data/test-binding.qml
new file mode 100644
index 0000000..e9101e4
--- /dev/null
+++ b/tests/auto/declarative/qmlbinding/data/test-binding.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen
+ width: 320; height: 240
+ property string text
+ property bool changeColor: false
+
+ Text { id: s1; text: "Hello" }
+ Rectangle { id: r1; width: 1; height: 1; color: "yellow" }
+ Rectangle { id: r2; width: 1; height: 1; color: "red" }
+
+ Binding { target: screen; property: "text"; value: s1.text; objectName: "binding1" }
+ Binding { target: screen; property: "color"; value: r1.color }
+ Binding { target: screen; property: "color"; when: screen.changeColor == true; value: r2.color }
+}
diff --git a/tests/auto/declarative/qmlbinding/data/test-binding2.qml b/tests/auto/declarative/qmlbinding/data/test-binding2.qml
new file mode 100644
index 0000000..ea20c16
--- /dev/null
+++ b/tests/auto/declarative/qmlbinding/data/test-binding2.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen
+ width: 320; height: 240
+ property string text
+ property bool changeColor: false
+
+ Text { id: s1; text: "Hello" }
+ Rectangle { id: r1; width: 1; height: 1; color: "yellow" }
+ Rectangle { id: r2; width: 1; height: 1; color: "red" }
+
+ Binding { target: screen; property: "text"; value: s1.text }
+ Binding { target: screen; property: "color"; value: r1.color }
+ Binding { target: screen; property: "color"; value: r2.color; when: screen.changeColor == true }
+}
diff --git a/tests/auto/declarative/qmlbinding/qmlbinding.pro b/tests/auto/declarative/qmlbinding/qmlbinding.pro
new file mode 100644
index 0000000..dfaca91
--- /dev/null
+++ b/tests/auto/declarative/qmlbinding/qmlbinding.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlbinding.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlbinding/tst_qmlbinding.cpp b/tests/auto/declarative/qmlbinding/tst_qmlbinding.cpp
new file mode 100644
index 0000000..19f4d77
--- /dev/null
+++ b/tests/auto/declarative/qmlbinding/tst_qmlbinding.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlbind_p.h>
+#include <private/qmlgraphicsrectangle_p.h>
+#include "../../../shared/util.h"
+
+class tst_qmlbinding : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlbinding();
+
+private slots:
+ void binding();
+ void whenAfterValue();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlbinding::tst_qmlbinding()
+{
+}
+
+void tst_qmlbinding::binding()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-binding.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+
+ QVERIFY(rect != 0);
+ QCOMPARE(rect->color(), QColor("yellow"));
+ QCOMPARE(rect->property("text").toString(), QString("Hello"));
+
+ rect->setProperty("changeColor", true);
+ QCOMPARE(rect->color(), QColor("red"));
+
+ QmlBind *binding = qobject_cast<QmlBind*>(rect->findChild<QmlBind*>("binding1"));
+ QVERIFY(binding != 0);
+ QCOMPARE(binding->object(), rect);
+ QCOMPARE(binding->property(), QLatin1String("text"));
+ QCOMPARE(binding->value().toString(), QLatin1String("Hello"));
+
+ delete rect;
+}
+
+void tst_qmlbinding::whenAfterValue()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-binding2.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+
+ QVERIFY(rect != 0);
+ QCOMPARE(rect->color(), QColor("yellow"));
+ QCOMPARE(rect->property("text").toString(), QString("Hello"));
+
+ rect->setProperty("changeColor", true);
+ QCOMPARE(rect->color(), QColor("red"));
+
+ delete rect;
+}
+
+QTEST_MAIN(tst_qmlbinding)
+
+#include "tst_qmlbinding.moc"
diff --git a/tests/auto/declarative/qmlconnection/data/test-connection.qml b/tests/auto/declarative/qmlconnection/data/test-connection.qml
new file mode 100644
index 0000000..9534621
--- /dev/null
+++ b/tests/auto/declarative/qmlconnection/data/test-connection.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+Item {
+ id: screen; width: 50
+
+ property bool tested: false
+ signal testMe
+
+ Connection { sender: screen; signal: "widthChanged()"; script: screen.tested = true }
+}
diff --git a/tests/auto/declarative/qmlconnection/data/test-connection2.qml b/tests/auto/declarative/qmlconnection/data/test-connection2.qml
new file mode 100644
index 0000000..65fe23a
--- /dev/null
+++ b/tests/auto/declarative/qmlconnection/data/test-connection2.qml
@@ -0,0 +1,3 @@
+import Qt 4.6
+
+Connection { id: connection; sender: connection; signal: "widthChanged()"; script: 1 == 1 }
diff --git a/tests/auto/declarative/qmlconnection/data/test-connection3.qml b/tests/auto/declarative/qmlconnection/data/test-connection3.qml
new file mode 100644
index 0000000..32133f9
--- /dev/null
+++ b/tests/auto/declarative/qmlconnection/data/test-connection3.qml
@@ -0,0 +1,3 @@
+import Qt 4.6
+
+Connection {}
diff --git a/tests/auto/declarative/qmlconnection/data/trimming.qml b/tests/auto/declarative/qmlconnection/data/trimming.qml
new file mode 100644
index 0000000..c27dc46
--- /dev/null
+++ b/tests/auto/declarative/qmlconnection/data/trimming.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+Item {
+ id: screen; width: 50
+
+ property string tested
+ signal testMe(int param1, string param2)
+
+ Connection { sender: screen; signal: "testMe(param1, param2)"; script: screen.tested = param2 + param1 }
+}
diff --git a/tests/auto/declarative/qmlconnection/qmlconnection.pro b/tests/auto/declarative/qmlconnection/qmlconnection.pro
new file mode 100644
index 0000000..3d46fa6
--- /dev/null
+++ b/tests/auto/declarative/qmlconnection/qmlconnection.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlconnection.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlconnection/tst_qmlconnection.cpp b/tests/auto/declarative/qmlconnection/tst_qmlconnection.cpp
new file mode 100644
index 0000000..b3c04f1
--- /dev/null
+++ b/tests/auto/declarative/qmlconnection/tst_qmlconnection.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlconnection_p.h>
+#include <private/qmlgraphicsitem_p.h>
+#include "../../../shared/util.h"
+#include <QtDeclarative/qmlscriptstring.h>
+
+class tst_qmlconnection : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlconnection();
+
+private slots:
+ void defaultValues();
+ void properties();
+ void connection();
+ void trimming();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlconnection::tst_qmlconnection()
+{
+}
+
+void tst_qmlconnection::defaultValues()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-connection3.qml"));
+ QmlConnection *item = qobject_cast<QmlConnection*>(c.create());
+
+ QVERIFY(item != 0);
+ QVERIFY(item->signalSender() == 0);
+ QCOMPARE(item->script().script(), QString());
+ QCOMPARE(item->signal(), QString());
+
+ delete item;
+}
+
+void tst_qmlconnection::properties()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-connection2.qml"));
+ QmlConnection *item = qobject_cast<QmlConnection*>(c.create());
+
+ QVERIFY(item != 0);
+
+ QVERIFY(item != 0);
+ QVERIFY(item->signalSender() == item);
+ QCOMPARE(item->script().script(), QString("1 == 1"));
+ QCOMPARE(item->signal(), QString("widthChanged()"));
+
+ delete item;
+}
+
+void tst_qmlconnection::connection()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-connection.qml"));
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(c.create());
+
+ QVERIFY(item != 0);
+
+ QCOMPARE(item->property("tested").toBool(), false);
+ QCOMPARE(item->width(), 50.);
+ emit item->setWidth(100.);
+ QCOMPARE(item->width(), 100.);
+ QCOMPARE(item->property("tested").toBool(), true);
+
+ delete item;
+}
+
+void tst_qmlconnection::trimming()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/trimming.qml"));
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(c.create());
+
+ QVERIFY(item != 0);
+
+ QCOMPARE(item->property("tested").toString(), QString(""));
+ int index = item->metaObject()->indexOfSignal("testMe(int,QString)");
+ QMetaMethod method = item->metaObject()->method(index);
+ method.invoke(item,
+ Qt::DirectConnection,
+ Q_ARG(int, 5),
+ Q_ARG(QString, "worked"));
+ QCOMPARE(item->property("tested").toString(), QString("worked5"));
+
+ delete item;
+}
+
+QTEST_MAIN(tst_qmlconnection)
+
+#include "tst_qmlconnection.moc"
diff --git a/tests/auto/declarative/qmlcontext/qmlcontext.pro b/tests/auto/declarative/qmlcontext/qmlcontext.pro
new file mode 100644
index 0000000..9e66429
--- /dev/null
+++ b/tests/auto/declarative/qmlcontext/qmlcontext.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlcontext.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp b/tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp
new file mode 100644
index 0000000..f82f202
--- /dev/null
+++ b/tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp
@@ -0,0 +1,434 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QDebug>
+#include <QmlEngine>
+#include <QmlContext>
+#include <QmlComponent>
+#include <QmlExpression>
+
+class tst_qmlcontext : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlcontext() {}
+
+private slots:
+ void baseUrl();
+ void resolvedUrl();
+ void engineMethod();
+ void parentContext();
+ void setContextProperty();
+ void addDefaultObject();
+ void destruction();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_qmlcontext::baseUrl()
+{
+ QmlContext ctxt(&engine);
+
+ QCOMPARE(ctxt.baseUrl(), QUrl());
+
+ ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
+
+ QCOMPARE(ctxt.baseUrl(), QUrl("http://www.nokia.com/"));
+}
+
+void tst_qmlcontext::resolvedUrl()
+{
+ // Relative to the component
+ {
+ QmlContext ctxt(&engine);
+ ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
+
+ QCOMPARE(ctxt.resolvedUrl(QUrl("main.qml")), QUrl("http://www.nokia.com/main.qml"));
+ }
+
+ // Relative to a parent
+ {
+ QmlContext ctxt(&engine);
+ ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
+
+ QmlContext ctxt2(&ctxt);
+ QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
+ }
+
+ // Relative to the engine
+ {
+ QmlContext ctxt(&engine);
+ QCOMPARE(ctxt.resolvedUrl(QUrl("main.qml")), engine.baseUrl().resolved(QUrl("main.qml")));
+ }
+
+ // Relative to a deleted parent
+ {
+ QmlContext *ctxt = new QmlContext(&engine);
+ ctxt->setBaseUrl(QUrl("http://www.nokia.com/"));
+
+ QmlContext ctxt2(ctxt);
+ QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
+
+ delete ctxt; ctxt = 0;
+
+ QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl());
+ }
+
+ // Absolute
+ {
+ QmlContext ctxt(&engine);
+
+ QCOMPARE(ctxt.resolvedUrl(QUrl("http://www.nokia.com/main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
+ QCOMPARE(ctxt.resolvedUrl(QUrl("file:///main2.qml")), QUrl("file:///main2.qml"));
+ }
+}
+
+void tst_qmlcontext::engineMethod()
+{
+ QmlEngine *engine = new QmlEngine;
+
+ QmlContext ctxt(engine);
+ QmlContext ctxt2(&ctxt);
+ QmlContext ctxt3(&ctxt2);
+ QmlContext ctxt4(&ctxt2);
+
+ QCOMPARE(ctxt.engine(), engine);
+ QCOMPARE(ctxt2.engine(), engine);
+ QCOMPARE(ctxt3.engine(), engine);
+ QCOMPARE(ctxt4.engine(), engine);
+
+ delete engine; engine = 0;
+
+ QCOMPARE(ctxt.engine(), engine);
+ QCOMPARE(ctxt2.engine(), engine);
+ QCOMPARE(ctxt3.engine(), engine);
+ QCOMPARE(ctxt4.engine(), engine);
+}
+
+void tst_qmlcontext::parentContext()
+{
+ QmlEngine *engine = new QmlEngine;
+
+ QCOMPARE(engine->rootContext()->parentContext(), (QmlContext *)0);
+
+ QmlContext *ctxt = new QmlContext(engine);
+ QmlContext *ctxt2 = new QmlContext(ctxt);
+ QmlContext *ctxt3 = new QmlContext(ctxt2);
+ QmlContext *ctxt4 = new QmlContext(ctxt2);
+ QmlContext *ctxt5 = new QmlContext(ctxt);
+ QmlContext *ctxt6 = new QmlContext(engine);
+ QmlContext *ctxt7 = new QmlContext(engine->rootContext());
+
+ QCOMPARE(ctxt->parentContext(), engine->rootContext());
+ QCOMPARE(ctxt2->parentContext(), ctxt);
+ QCOMPARE(ctxt3->parentContext(), ctxt2);
+ QCOMPARE(ctxt4->parentContext(), ctxt2);
+ QCOMPARE(ctxt5->parentContext(), ctxt);
+ QCOMPARE(ctxt6->parentContext(), engine->rootContext());
+ QCOMPARE(ctxt7->parentContext(), engine->rootContext());
+
+ delete ctxt2; ctxt2 = 0;
+
+ QCOMPARE(ctxt->parentContext(), engine->rootContext());
+ QCOMPARE(ctxt3->parentContext(), ctxt2);
+ QCOMPARE(ctxt4->parentContext(), ctxt2);
+ QCOMPARE(ctxt5->parentContext(), ctxt);
+ QCOMPARE(ctxt6->parentContext(), engine->rootContext());
+ QCOMPARE(ctxt7->parentContext(), engine->rootContext());
+
+ delete engine; engine = 0;
+
+ QCOMPARE(ctxt->parentContext(), (QmlContext *)0);
+ QCOMPARE(ctxt3->parentContext(), ctxt2);
+ QCOMPARE(ctxt4->parentContext(), ctxt2);
+ QCOMPARE(ctxt5->parentContext(), ctxt);
+ QCOMPARE(ctxt6->parentContext(), (QmlContext *)0);
+ QCOMPARE(ctxt7->parentContext(), (QmlContext *)0);
+
+ delete ctxt7;
+ delete ctxt6;
+ delete ctxt5;
+ delete ctxt4;
+ delete ctxt3;
+ delete ctxt;
+}
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int a READ a NOTIFY aChanged)
+ Q_PROPERTY(int b READ b NOTIFY bChanged)
+ Q_PROPERTY(int c READ c NOTIFY cChanged)
+
+public:
+ TestObject() : _a(10), _b(10), _c(10) {}
+
+ int a() const { return _a; }
+ void setA(int a) { _a = a; emit aChanged(); }
+
+ int b() const { return _b; }
+ void setB(int b) { _b = b; emit bChanged(); }
+
+ int c() const { return _c; }
+ void setC(int c) { _c = c; emit cChanged(); }
+
+signals:
+ void aChanged();
+ void bChanged();
+ void cChanged();
+
+private:
+ int _a;
+ int _b;
+ int _c;
+};
+
+class TestObject2 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int b READ b NOTIFY bChanged)
+
+public:
+ TestObject2() : _b(10) {}
+
+ int b() const { return _b; }
+ void setB(int b) { _b = b; emit bChanged(); }
+
+signals:
+ void bChanged();
+
+private:
+ int _b;
+};
+
+#define TEST_CONTEXT_PROPERTY(ctxt, name, value) \
+{ \
+ QmlComponent component(&engine); \
+ component.setData("import Qt 4.6; QtObject { property var test: " #name " }", QUrl()); \
+\
+ QObject *obj = component.create(ctxt); \
+\
+ QCOMPARE(obj->property("test"), value); \
+\
+ delete obj; \
+}
+
+void tst_qmlcontext::setContextProperty()
+{
+ QmlContext ctxt(&engine);
+ QmlContext ctxt2(&ctxt);
+
+ TestObject obj1;
+ obj1.setA(3345);
+ TestObject obj2;
+ obj2.setA(-19);
+
+ // Static context properties
+ ctxt.setContextProperty("a", QVariant(10));
+ ctxt.setContextProperty("b", QVariant(9));
+ ctxt2.setContextProperty("d", &obj2);
+ ctxt2.setContextProperty("b", QVariant(19));
+ ctxt2.setContextProperty("c", QVariant(QString("Hello World!")));
+ ctxt.setContextProperty("d", &obj1);
+ ctxt.setContextProperty("e", &obj1);
+
+ TEST_CONTEXT_PROPERTY(&ctxt2, a, QVariant(10));
+ TEST_CONTEXT_PROPERTY(&ctxt2, b, QVariant(19));
+ TEST_CONTEXT_PROPERTY(&ctxt2, c, QVariant(QString("Hello World!")));
+ TEST_CONTEXT_PROPERTY(&ctxt2, d.a, QVariant(-19));
+ TEST_CONTEXT_PROPERTY(&ctxt2, e.a, QVariant(3345));
+
+ ctxt.setContextProperty("a", QVariant(13));
+ ctxt.setContextProperty("b", QVariant(4));
+ ctxt2.setContextProperty("b", QVariant(8));
+ ctxt2.setContextProperty("c", QVariant(QString("Hi World!")));
+ ctxt2.setContextProperty("d", &obj1);
+ obj1.setA(12);
+
+ TEST_CONTEXT_PROPERTY(&ctxt2, a, QVariant(13));
+ TEST_CONTEXT_PROPERTY(&ctxt2, b, QVariant(8));
+ TEST_CONTEXT_PROPERTY(&ctxt2, c, QVariant(QString("Hi World!")));
+ TEST_CONTEXT_PROPERTY(&ctxt2, d.a, QVariant(12));
+ TEST_CONTEXT_PROPERTY(&ctxt2, e.a, QVariant(12));
+
+ // Changes in context properties
+ {
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6; QtObject { property var test: a }", QUrl());
+
+ QObject *obj = component.create(&ctxt2);
+
+ QCOMPARE(obj->property("test"), QVariant(13));
+ ctxt.setContextProperty("a", QVariant(19));
+ QCOMPARE(obj->property("test"), QVariant(19));
+
+ delete obj;
+ }
+ {
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6; QtObject { property var test: b }", QUrl());
+
+ QObject *obj = component.create(&ctxt2);
+
+ QCOMPARE(obj->property("test"), QVariant(8));
+ ctxt.setContextProperty("b", QVariant(5));
+ QCOMPARE(obj->property("test"), QVariant(8));
+ ctxt2.setContextProperty("b", QVariant(1912));
+ QCOMPARE(obj->property("test"), QVariant(1912));
+
+ delete obj;
+ }
+ {
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6; QtObject { property var test: e.a }", QUrl());
+
+ QObject *obj = component.create(&ctxt2);
+
+ QCOMPARE(obj->property("test"), QVariant(12));
+ obj1.setA(13);
+ QCOMPARE(obj->property("test"), QVariant(13));
+
+ delete obj;
+ }
+
+ // New context properties
+ {
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6; QtObject { property var test: a }", QUrl());
+
+ QObject *obj = component.create(&ctxt2);
+
+ QCOMPARE(obj->property("test"), QVariant(19));
+ ctxt2.setContextProperty("a", QVariant(1945));
+ QCOMPARE(obj->property("test"), QVariant(1945));
+
+ delete obj;
+ }
+
+ // Setting an object-variant context property
+ {
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6; QtObject { id: root; property int a: 10; property int test: ctxtProp.a; property var obj: root; }", QUrl());
+
+ QmlContext ctxt(engine.rootContext());
+ ctxt.setContextProperty("ctxtProp", QVariant());
+
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Result of expression 'ctxtProp' [undefined] is not an object.");
+ QObject *obj = component.create(&ctxt);
+
+ QVariant v = obj->property("obj");
+
+ ctxt.setContextProperty("ctxtProp", v);
+
+ QCOMPARE(obj->property("test"), QVariant(10));
+
+ delete obj;
+ }
+}
+
+void tst_qmlcontext::addDefaultObject()
+{
+ QmlContext ctxt(&engine);
+
+ TestObject to;
+ TestObject2 to2;
+
+ to.setA(2);
+ to.setB(192);
+ to.setC(18);
+ to2.setB(111999);
+
+ ctxt.addDefaultObject(&to2);
+ ctxt.addDefaultObject(&to);
+ ctxt.setContextProperty("c", QVariant(9));
+
+ // Static context properties
+ TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(2));
+ TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(111999));
+ TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(9));
+
+ to.setA(12);
+ to.setB(100);
+ to.setC(7);
+ to2.setB(1612);
+ ctxt.setContextProperty("c", QVariant(3));
+
+ TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(12));
+ TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(1612));
+ TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(3));
+
+ // Changes in context properties
+ {
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6; QtObject { property var test: a }", QUrl());
+
+ QObject *obj = component.create(&ctxt);
+
+ QCOMPARE(obj->property("test"), QVariant(12));
+ to.setA(14);
+ QCOMPARE(obj->property("test"), QVariant(14));
+
+ delete obj;
+ }
+}
+
+void tst_qmlcontext::destruction()
+{
+ QmlContext *ctxt = new QmlContext(&engine);
+
+ QObject obj;
+ QmlEngine::setContextForObject(&obj, ctxt);
+ QmlExpression expr(ctxt, "a", 0);
+
+ QCOMPARE(ctxt, QmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt, expr.context());
+
+ delete ctxt; ctxt = 0;
+
+ QCOMPARE(ctxt, QmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt, expr.context());
+}
+
+QTEST_MAIN(tst_qmlcontext)
+
+#include "tst_qmlcontext.moc"
diff --git a/tests/auto/declarative/qmldatetimeformatter/qmldatetimeformatter.pro b/tests/auto/declarative/qmldatetimeformatter/qmldatetimeformatter.pro
new file mode 100644
index 0000000..2b1947d
--- /dev/null
+++ b/tests/auto/declarative/qmldatetimeformatter/qmldatetimeformatter.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmldatetimeformatter.cpp
diff --git a/tests/auto/declarative/qmldatetimeformatter/tst_qmldatetimeformatter.cpp b/tests/auto/declarative/qmldatetimeformatter/tst_qmldatetimeformatter.cpp
new file mode 100644
index 0000000..2ce6186
--- /dev/null
+++ b/tests/auto/declarative/qmldatetimeformatter/tst_qmldatetimeformatter.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmldatetimeformatter_p.h>
+#include <QDebug>
+
+class tst_datetimeformatter : public QObject
+{
+ Q_OBJECT
+public:
+ tst_datetimeformatter() {}
+
+private slots:
+ void date();
+ void time();
+ void dateTime();
+};
+
+void tst_datetimeformatter::date()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine);
+ formatterComponent.setData(QByteArray("import Qt 4.6\n DateTimeFormatter { date: \"2008-12-24\" }"),
+ QUrl::fromLocalFile(""));
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ if(formatterComponent.isError())
+ qDebug() << formatterComponent.errors();
+ QVERIFY(formatter != 0);
+
+ QDate date(2008,12,24);
+ QCOMPARE(formatter->date(), date);
+ QCOMPARE(formatter->dateTime().date(), date);
+ QCOMPARE(formatter->dateText(),date.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QVERIFY(formatter->longStyle());
+ QCOMPARE(formatter->dateText(),date.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setDateFormat("ddd MMMM d yy");
+ QCOMPARE(formatter->dateFormat(), QLatin1String("ddd MMMM d yy"));
+ QCOMPARE(formatter->dateText(),date.toString("ddd MMMM d yy"));
+
+ QVERIFY(formatter->timeText().isEmpty());
+ QVERIFY(formatter->dateTimeText().isEmpty());
+
+ delete formatter;
+}
+
+void tst_datetimeformatter::time()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine);
+ formatterComponent.setData("import Qt 4.6\n DateTimeFormatter { time: \"14:15:38.200\" }", QUrl::fromLocalFile(""));
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ if(formatterComponent.isError())
+ qDebug() << formatterComponent.errors();
+ QVERIFY(formatter != 0);
+
+ QTime time(14,15,38,200);
+
+ QCOMPARE(formatter->time(),time);
+ QCOMPARE(formatter->dateTime().time(),time);
+
+ QCOMPARE(formatter->timeText(),time.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->timeText(),time.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setTimeFormat("H:m:s a");
+ QCOMPARE(formatter->timeFormat(), QLatin1String("H:m:s a"));
+ QCOMPARE(formatter->timeText(),time.toString("H:m:s a"));
+
+ formatter->setTimeFormat("hh:mm:ss.zzz");
+ QCOMPARE(formatter->timeText(),time.toString("hh:mm:ss.zzz"));
+
+ QVERIFY(formatter->dateText().isEmpty());
+ QVERIFY(formatter->dateTimeText().isEmpty());
+
+ delete formatter;
+}
+
+void tst_datetimeformatter::dateTime()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine);
+ formatterComponent.setData("import Qt 4.6\n DateTimeFormatter { dateTime: \"1978-03-04T09:13:54\" }", QUrl::fromLocalFile(""));
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ if(formatterComponent.isError())
+ qDebug() << formatterComponent.errors();
+ QVERIFY(formatter != 0);
+
+ QDateTime dateTime(QDate(1978,03,04),QTime(9,13,54));
+ QCOMPARE(formatter->dateTime(),dateTime);
+ QCOMPARE(formatter->date(),dateTime.date());
+ QCOMPARE(formatter->time(),dateTime.time());
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setDateTimeFormat("M/d/yy H:m:s a");
+ QCOMPARE(formatter->dateTimeFormat(), QLatin1String("M/d/yy H:m:s a"));
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString("M/d/yy H:m:s a"));
+
+ delete formatter;
+}
+
+QTEST_MAIN(tst_datetimeformatter)
+
+#include "tst_qmldatetimeformatter.moc"
diff --git a/tests/auto/declarative/qmldebug/qmldebug.pro b/tests/auto/declarative/qmldebug/qmldebug.pro
new file mode 100644
index 0000000..f79829d
--- /dev/null
+++ b/tests/auto/declarative/qmldebug/qmldebug.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += network declarative
+macx:CONFIG -= app_bundle
+
+HEADERS += ../shared/debugutil_p.h
+SOURCES += tst_qmldebug.cpp \
+ ../shared/debugutil.cpp
diff --git a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp
new file mode 100644
index 0000000..82e74ce
--- /dev/null
+++ b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp
@@ -0,0 +1,833 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QSignalSpy>
+#include <QTimer>
+#include <QHostAddress>
+#include <QDebug>
+#include <QThread>
+
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtDeclarative/qmlbinding.h>
+
+#include <private/qmldebug_p.h>
+#include <private/qmlenginedebug_p.h>
+#include <private/qmldebugclient_p.h>
+#include <private/qmldebugservice_p.h>
+#include <private/qmlgraphicsrectangle_p.h>
+
+#include "../shared/debugutil_p.h"
+
+Q_DECLARE_METATYPE(QmlDebugWatch::State)
+
+
+class tst_QmlDebug : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QmlDebug(QmlDebugTestData *data)
+ {
+ m_conn = data->conn;
+ m_engine = data->engine;
+ m_rootItem = data->items[0];
+ }
+
+private:
+ QmlDebugObjectReference findRootObject();
+ QmlDebugPropertyReference findProperty(const QList<QmlDebugPropertyReference> &props, const QString &name) const;
+ void waitForQuery(QmlDebugQuery *query);
+
+ void recursiveObjectTest(QObject *o, const QmlDebugObjectReference &oref, bool recursive) const;
+
+ void recursiveCompareObjects(const QmlDebugObjectReference &a, const QmlDebugObjectReference &b) const;
+ void recursiveCompareContexts(const QmlDebugContextReference &a, const QmlDebugContextReference &b) const;
+ void compareProperties(const QmlDebugPropertyReference &a, const QmlDebugPropertyReference &b) const;
+
+ QmlDebugConnection *m_conn;
+ QmlEngineDebug *m_dbg;
+ QmlEngine *m_engine;
+ QmlGraphicsItem *m_rootItem;
+
+private slots:
+ void initTestCase();
+
+ void watch_property();
+ void watch_object();
+ void watch_expression();
+ void watch_expression_data();
+ void watch_context();
+ void watch_file();
+
+ void queryAvailableEngines();
+ void queryRootContexts();
+ void queryObject();
+ void queryObject_data();
+ void queryExpressionResult();
+ void queryExpressionResult_data();
+
+ void tst_QmlDebugFileReference();
+ void tst_QmlDebugEngineReference();
+ void tst_QmlDebugObjectReference();
+ void tst_QmlDebugContextReference();
+ void tst_QmlDebugPropertyReference();
+};
+
+QmlDebugObjectReference tst_QmlDebug::findRootObject()
+{
+ QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
+ waitForQuery(q_engines);
+
+ if (q_engines->engines().count() == 0)
+ return QmlDebugObjectReference();
+ QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
+ waitForQuery(q_context);
+
+ if (q_context->rootContext().objects().count() == 0)
+ return QmlDebugObjectReference();
+ QmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this);
+ waitForQuery(q_obj);
+
+ QmlDebugObjectReference result = q_obj->object();
+
+ delete q_engines;
+ delete q_context;
+ delete q_obj;
+
+ return result;
+}
+
+QmlDebugPropertyReference tst_QmlDebug::findProperty(const QList<QmlDebugPropertyReference> &props, const QString &name) const
+{
+ foreach(const QmlDebugPropertyReference &p, props) {
+ if (p.name() == name)
+ return p;
+ }
+ return QmlDebugPropertyReference();
+}
+
+void tst_QmlDebug::waitForQuery(QmlDebugQuery *query)
+{
+ QVERIFY(query);
+ QCOMPARE(query->parent(), this);
+ QVERIFY(query->state() == QmlDebugQuery::Waiting);
+ if (!QmlDebugTest::waitForSignal(query, SIGNAL(stateChanged(QmlDebugQuery::State))))
+ QFAIL("query timed out");
+}
+
+void tst_QmlDebug::recursiveObjectTest(QObject *o, const QmlDebugObjectReference &oref, bool recursive) const
+{
+ const QMetaObject *meta = o->metaObject();
+
+ QmlType *type = QmlMetaType::qmlType(o->metaObject());
+ QString className = type ? type->qmlTypeName() : QString();
+ className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1);
+
+ QCOMPARE(oref.debugId(), QmlDebugService::idForObject(o));
+ QCOMPARE(oref.name(), o->objectName());
+ QCOMPARE(oref.className(), className);
+ QCOMPARE(oref.contextDebugId(), QmlDebugService::idForObject(qmlContext(o)));
+
+ const QObjectList &children = o->children();
+ for (int i=0; i<children.count(); i++) {
+ QObject *child = children[i];
+ if (!qmlContext(child))
+ continue;
+ int debugId = QmlDebugService::idForObject(child);
+ QVERIFY(debugId >= 0);
+
+ QmlDebugObjectReference cref;
+ foreach (const QmlDebugObjectReference &ref, oref.children()) {
+ if (ref.debugId() == debugId) {
+ cref = ref;
+ break;
+ }
+ }
+ QVERIFY(cref.debugId() >= 0);
+
+ if (recursive)
+ recursiveObjectTest(child, cref, true);
+ }
+
+ foreach (const QmlDebugPropertyReference &p, oref.properties()) {
+ QCOMPARE(p.objectDebugId(), QmlDebugService::idForObject(o));
+
+ // signal properties are fake - they are generated from QmlBoundSignal children
+ if (p.name().startsWith("on") && p.name().length() > 2 && p.name()[2].isUpper()) {
+ QVERIFY(p.value().toString().startsWith('{') && p.value().toString().endsWith('}'));
+ QVERIFY(p.valueTypeName().isEmpty());
+ QVERIFY(p.binding().isEmpty());
+ QVERIFY(!p.hasNotifySignal());
+ continue;
+ }
+
+ QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name().toUtf8().constData()));
+
+ QCOMPARE(p.name(), QString::fromUtf8(pmeta.name()));
+
+ if (pmeta.type() < QVariant::UserType) // TODO test complex types
+ QCOMPARE(p.value(), pmeta.read(o));
+
+ if (p.name() == "parent")
+ QVERIFY(p.valueTypeName() == "QGraphicsObject*" || p.valueTypeName() == "QmlGraphicsItem*");
+ else
+ QCOMPARE(p.valueTypeName(), QString::fromUtf8(pmeta.typeName()));
+
+ QmlAbstractBinding *binding = QmlMetaProperty(o, p.name()).binding();
+ if (binding)
+ QCOMPARE(binding->expression(), p.binding());
+
+ QCOMPARE(p.hasNotifySignal(), pmeta.hasNotifySignal());
+
+ QVERIFY(pmeta.isValid());
+ }
+}
+
+void tst_QmlDebug::recursiveCompareObjects(const QmlDebugObjectReference &a, const QmlDebugObjectReference &b) const
+{
+ QCOMPARE(a.debugId(), b.debugId());
+ QCOMPARE(a.className(), b.className());
+ QCOMPARE(a.name(), b.name());
+ QCOMPARE(a.contextDebugId(), b.contextDebugId());
+
+ QCOMPARE(a.source().url(), b.source().url());
+ QCOMPARE(a.source().lineNumber(), b.source().lineNumber());
+ QCOMPARE(a.source().columnNumber(), b.source().columnNumber());
+
+ QCOMPARE(a.properties().count(), b.properties().count());
+ QCOMPARE(a.children().count(), b.children().count());
+
+ QList<QmlDebugPropertyReference> aprops = a.properties();
+ QList<QmlDebugPropertyReference> bprops = b.properties();
+
+ for (int i=0; i<aprops.count(); i++)
+ compareProperties(aprops[i], bprops[i]);
+
+ for (int i=0; i<a.children().count(); i++)
+ recursiveCompareObjects(a.children()[i], b.children()[i]);
+}
+
+void tst_QmlDebug::recursiveCompareContexts(const QmlDebugContextReference &a, const QmlDebugContextReference &b) const
+{
+ QCOMPARE(a.debugId(), b.debugId());
+ QCOMPARE(a.name(), b.name());
+ QCOMPARE(a.objects().count(), b.objects().count());
+ QCOMPARE(a.contexts().count(), b.contexts().count());
+
+ for (int i=0; i<a.objects().count(); i++)
+ recursiveCompareObjects(a.objects()[i], b.objects()[i]);
+
+ for (int i=0; i<a.contexts().count(); i++)
+ recursiveCompareContexts(a.contexts()[i], b.contexts()[i]);
+}
+
+void tst_QmlDebug::compareProperties(const QmlDebugPropertyReference &a, const QmlDebugPropertyReference &b) const
+{
+ QCOMPARE(a.objectDebugId(), b.objectDebugId());
+ QCOMPARE(a.name(), b.name());
+ QCOMPARE(a.value(), b.value());
+ QCOMPARE(a.valueTypeName(), b.valueTypeName());
+ QCOMPARE(a.binding(), b.binding());
+ QCOMPARE(a.hasNotifySignal(), b.hasNotifySignal());
+}
+
+void tst_QmlDebug::initTestCase()
+{
+ m_dbg = new QmlEngineDebug(m_conn, this);
+
+ qRegisterMetaType<QmlDebugWatch::State>();
+}
+
+void tst_QmlDebug::watch_property()
+{
+ QmlDebugObjectReference obj = findRootObject();
+ QmlDebugPropertyReference prop = findProperty(obj.properties(), "width");
+
+ QmlDebugPropertyWatch *watch;
+
+ QmlEngineDebug unconnected(0);
+ watch = unconnected.addWatch(prop, this);
+ QCOMPARE(watch->state(), QmlDebugWatch::Dead);
+ delete watch;
+
+ watch = m_dbg->addWatch(QmlDebugPropertyReference(), this);
+ QVERIFY(QmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QmlDebugWatch::State))));
+ QCOMPARE(watch->state(), QmlDebugWatch::Inactive);
+ delete watch;
+
+ watch = m_dbg->addWatch(prop, this);
+ QCOMPARE(watch->state(), QmlDebugWatch::Waiting);
+ QCOMPARE(watch->objectDebugId(), obj.debugId());
+ QCOMPARE(watch->name(), prop.name());
+
+ QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));
+
+ int origWidth = m_rootItem->property("width").toInt();
+ m_rootItem->setProperty("width", origWidth*2);
+
+ // stateChanged() is received before valueChanged()
+ QVERIFY(QmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QmlDebugWatch::State))));
+ QCOMPARE(watch->state(), QmlDebugWatch::Active);
+ QCOMPARE(spy.count(), 1);
+
+ m_dbg->removeWatch(watch);
+ delete watch;
+
+ // restore original value and verify spy doesn't get additional signal since watch has been removed
+ m_rootItem->setProperty("width", origWidth);
+ QTest::qWait(100);
+ QCOMPARE(spy.count(), 1);
+
+ QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name().toUtf8());
+ QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2));
+}
+
+void tst_QmlDebug::watch_object()
+{
+ QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
+ waitForQuery(q_engines);
+
+ Q_ASSERT(q_engines->engines().count() > 0);
+ QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
+ waitForQuery(q_context);
+
+ Q_ASSERT(q_context->rootContext().objects().count() > 0);
+ QmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this);
+ waitForQuery(q_obj);
+
+ QmlDebugObjectReference obj = q_obj->object();
+
+ delete q_engines;
+ delete q_context;
+ delete q_obj;
+
+ QmlDebugWatch *watch;
+
+ QmlEngineDebug unconnected(0);
+ watch = unconnected.addWatch(obj, this);
+ QCOMPARE(watch->state(), QmlDebugWatch::Dead);
+ delete watch;
+
+ watch = m_dbg->addWatch(QmlDebugObjectReference(), this);
+ QVERIFY(QmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QmlDebugWatch::State))));
+ QCOMPARE(watch->state(), QmlDebugWatch::Inactive);
+ delete watch;
+
+ watch = m_dbg->addWatch(obj, this);
+ QCOMPARE(watch->state(), QmlDebugWatch::Waiting);
+ QCOMPARE(watch->objectDebugId(), obj.debugId());
+
+ QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));
+
+ int origWidth = m_rootItem->property("width").toInt();
+ int origHeight = m_rootItem->property("height").toInt();
+ m_rootItem->setProperty("width", origWidth*2);
+ m_rootItem->setProperty("height", origHeight*2);
+
+ // stateChanged() is received before any valueChanged() signals
+ QVERIFY(QmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QmlDebugWatch::State))));
+ QCOMPARE(watch->state(), QmlDebugWatch::Active);
+ QVERIFY(spy.count() > 0);
+
+ int newWidth = -1;
+ int newHeight = -1;
+ for (int i=0; i<spy.count(); i++) {
+ const QVariantList &values = spy[i];
+ if (values[0].value<QByteArray>() == "width")
+ newWidth = values[1].value<QVariant>().toInt();
+ else if (values[0].value<QByteArray>() == "height")
+ newHeight = values[1].value<QVariant>().toInt();
+
+ }
+
+ m_dbg->removeWatch(watch);
+ delete watch;
+
+ // since watch has been removed, restoring the original values should not trigger a valueChanged()
+ spy.clear();
+ m_rootItem->setProperty("width", origWidth);
+ m_rootItem->setProperty("height", origHeight);
+ QTest::qWait(100);
+ QCOMPARE(spy.count(), 0);
+
+ QCOMPARE(newWidth, origWidth * 2);
+ QCOMPARE(newHeight, origHeight * 2);
+}
+
+void tst_QmlDebug::watch_expression()
+{
+ QFETCH(QString, expr);
+ QFETCH(int, increment);
+ QFETCH(int, incrementCount);
+
+ int origWidth = m_rootItem->property("width").toInt();
+
+ QmlDebugObjectReference obj = findRootObject();
+
+ QmlDebugObjectExpressionWatch *watch;
+
+ QmlEngineDebug unconnected(0);
+ watch = unconnected.addWatch(obj, expr, this);
+ QCOMPARE(watch->state(), QmlDebugWatch::Dead);
+ delete watch;
+
+ watch = m_dbg->addWatch(QmlDebugObjectReference(), expr, this);
+ QVERIFY(QmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QmlDebugWatch::State))));
+ QCOMPARE(watch->state(), QmlDebugWatch::Inactive);
+ delete watch;
+
+ watch = m_dbg->addWatch(obj, expr, this);
+ QCOMPARE(watch->state(), QmlDebugWatch::Waiting);
+ QCOMPARE(watch->objectDebugId(), obj.debugId());
+ QCOMPARE(watch->expression(), expr);
+
+ QSignalSpy spyState(watch, SIGNAL(stateChanged(QmlDebugWatch::State)));
+
+ QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));
+ int expectedSpyCount = incrementCount + 1; // should also get signal with expression's initial value
+
+ int width = origWidth;
+ for (int i=0; i<incrementCount+1; i++) {
+ if (i > 0) {
+ width += increment;
+ m_rootItem->setProperty("width", width);
+ }
+ if (!QmlDebugTest::waitForSignal(watch, SIGNAL(valueChanged(QByteArray,QVariant))))
+ QFAIL("Did not receive valueChanged() for expression");
+ }
+
+ if (spyState.count() == 0)
+ QVERIFY(QmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QmlDebugWatch::State))));
+ QCOMPARE(spyState.count(), 1);
+ QCOMPARE(watch->state(), QmlDebugWatch::Active);
+
+ m_dbg->removeWatch(watch);
+ delete watch;
+
+ // restore original value and verify spy doesn't get a signal since watch has been removed
+ m_rootItem->setProperty("width", origWidth);
+ QTest::qWait(100);
+ QCOMPARE(spy.count(), expectedSpyCount);
+
+ width = origWidth + increment;
+ for (int i=0; i<spy.count(); i++) {
+ QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width);
+ width += increment;
+ }
+}
+
+void tst_QmlDebug::watch_expression_data()
+{
+ QTest::addColumn<QString>("expr");
+ QTest::addColumn<int>("increment");
+ QTest::addColumn<int>("incrementCount");
+
+ QTest::newRow("width") << "width" << 0 << 0;
+ QTest::newRow("width+10") << "width + 10" << 10 << 5;
+}
+
+void tst_QmlDebug::watch_context()
+{
+ QmlDebugContextReference c;
+ QTest::ignoreMessage(QtWarningMsg, "QmlEngineDebug::addWatch(): Not implemented");
+ QVERIFY(!m_dbg->addWatch(c, QString(), this));
+}
+
+void tst_QmlDebug::watch_file()
+{
+ QmlDebugFileReference f;
+ QTest::ignoreMessage(QtWarningMsg, "QmlEngineDebug::addWatch(): Not implemented");
+ QVERIFY(!m_dbg->addWatch(f, this));
+}
+
+void tst_QmlDebug::queryAvailableEngines()
+{
+ QmlDebugEnginesQuery *q_engines;
+
+ QmlEngineDebug unconnected(0);
+ q_engines = unconnected.queryAvailableEngines(0);
+ QCOMPARE(q_engines->state(), QmlDebugQuery::Error);
+ delete q_engines;
+
+ q_engines = m_dbg->queryAvailableEngines(this);
+ delete q_engines;
+
+ q_engines = m_dbg->queryAvailableEngines(this);
+ QVERIFY(q_engines->engines().isEmpty());
+ waitForQuery(q_engines);
+
+ // TODO test multiple engines
+ QList<QmlDebugEngineReference> engines = q_engines->engines();
+ QCOMPARE(engines.count(), 1);
+
+ foreach(const QmlDebugEngineReference &e, engines) {
+ QCOMPARE(e.debugId(), QmlDebugService::idForObject(m_engine));
+ QCOMPARE(e.name(), m_engine->objectName());
+ }
+
+ delete q_engines;
+}
+
+void tst_QmlDebug::queryRootContexts()
+{
+ QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
+ waitForQuery(q_engines);
+ int engineId = q_engines->engines()[0].debugId();
+
+ QmlDebugRootContextQuery *q_context;
+
+ QmlEngineDebug unconnected(0);
+ q_context = unconnected.queryRootContexts(engineId, this);
+ QCOMPARE(q_context->state(), QmlDebugQuery::Error);
+ delete q_context;
+
+ q_context = m_dbg->queryRootContexts(engineId, this);
+ delete q_context;
+
+ q_context = m_dbg->queryRootContexts(engineId, this);
+ waitForQuery(q_context);
+
+ QmlContext *actualContext = m_engine->rootContext();
+ QmlDebugContextReference context = q_context->rootContext();
+ QCOMPARE(context.debugId(), QmlDebugService::idForObject(actualContext));
+ QCOMPARE(context.name(), actualContext->objectName());
+
+ QCOMPARE(context.objects().count(), 2); // 2 qml component objects created for context in main()
+
+ // root context query sends only root object data - it doesn't fill in
+ // the children or property info
+ QCOMPARE(context.objects()[0].properties().count(), 0);
+ QCOMPARE(context.objects()[0].children().count(), 0);
+
+ QCOMPARE(context.contexts().count(), 1);
+ QVERIFY(context.contexts()[0].debugId() >= 0);
+ QCOMPARE(context.contexts()[0].name(), QString("tst_QmlDebug_childContext"));
+
+ delete q_engines;
+ delete q_context;
+}
+
+void tst_QmlDebug::queryObject()
+{
+ QFETCH(bool, recursive);
+
+ QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
+ waitForQuery(q_engines);
+
+ QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
+ waitForQuery(q_context);
+ QmlDebugObjectReference rootObject = q_context->rootContext().objects()[0];
+
+ QmlDebugObjectQuery *q_obj = 0;
+
+ QmlEngineDebug unconnected(0);
+ q_obj = recursive ? unconnected.queryObjectRecursive(rootObject, this) : unconnected.queryObject(rootObject, this);
+ QCOMPARE(q_obj->state(), QmlDebugQuery::Error);
+ delete q_obj;
+
+ q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this);
+ delete q_obj;
+
+ q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this);
+ waitForQuery(q_obj);
+
+ QmlDebugObjectReference obj = q_obj->object();
+
+ delete q_engines;
+ delete q_context;
+ delete q_obj;
+
+ // check source as defined in main()
+ QmlDebugFileReference source = obj.source();
+ QCOMPARE(source.url(), QUrl::fromLocalFile(""));
+ QCOMPARE(source.lineNumber(), 2);
+ QCOMPARE(source.columnNumber(), 1);
+
+ // generically test all properties, children and childrens' properties
+ recursiveObjectTest(m_rootItem, obj, recursive);
+
+ if (recursive) {
+ foreach(const QmlDebugObjectReference &child, obj.children())
+ QVERIFY(child.properties().count() > 0);
+
+ QmlDebugObjectReference rect;
+ QmlDebugObjectReference text;
+ foreach (const QmlDebugObjectReference &child, obj.children()) {
+ if (child.className() == "Rectangle")
+ rect = child;
+ else if (child.className() == "Text")
+ text = child;
+ }
+
+ // test specific property values
+ QCOMPARE(findProperty(rect.properties(), "width").value(), qVariantFromValue(500));
+ QCOMPARE(findProperty(rect.properties(), "height").value(), qVariantFromValue(600));
+ QCOMPARE(findProperty(rect.properties(), "color").value(), qVariantFromValue(QColor("blue")));
+
+ QCOMPARE(findProperty(text.properties(), "color").value(), qVariantFromValue(QColor("blue")));
+
+ } else {
+ foreach(const QmlDebugObjectReference &child, obj.children())
+ QCOMPARE(child.properties().count(), 0);
+ }
+}
+
+void tst_QmlDebug::queryObject_data()
+{
+ QTest::addColumn<bool>("recursive");
+
+ QTest::newRow("non-recursive") << false;
+ QTest::newRow("recursive") << true;
+}
+
+void tst_QmlDebug::queryExpressionResult()
+{
+ QFETCH(QString, expr);
+ QFETCH(QVariant, result);
+
+ QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
+ waitForQuery(q_engines); // check immediate deletion is ok
+
+ QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
+ waitForQuery(q_context);
+ int objectId = q_context->rootContext().objects()[0].debugId();
+
+ QmlDebugExpressionQuery *q_expr;
+
+ QmlEngineDebug unconnected(0);
+ q_expr = unconnected.queryExpressionResult(objectId, expr, this);
+ QCOMPARE(q_expr->state(), QmlDebugQuery::Error);
+ delete q_expr;
+
+ q_expr = m_dbg->queryExpressionResult(objectId, expr, this);
+ delete q_expr;
+
+ q_expr = m_dbg->queryExpressionResult(objectId, expr, this);
+ QCOMPARE(q_expr->expression(), expr);
+ waitForQuery(q_expr);
+
+ QCOMPARE(q_expr->result(), result);
+
+ delete q_engines;
+ delete q_context;
+ delete q_expr;
+}
+
+void tst_QmlDebug::queryExpressionResult_data()
+{
+ QTest::addColumn<QString>("expr");
+ QTest::addColumn<QVariant>("result");
+
+ QTest::newRow("width + 50") << "width + 50" << qVariantFromValue(60);
+ QTest::newRow("blueRect.width") << "blueRect.width" << qVariantFromValue(500);
+ QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("<undefined>"));
+}
+
+void tst_QmlDebug::tst_QmlDebugFileReference()
+{
+ QmlDebugFileReference ref;
+ QVERIFY(ref.url().isEmpty());
+ QCOMPARE(ref.lineNumber(), -1);
+ QCOMPARE(ref.columnNumber(), -1);
+
+ ref.setUrl(QUrl("http://test"));
+ QCOMPARE(ref.url(), QUrl("http://test"));
+ ref.setLineNumber(1);
+ QCOMPARE(ref.lineNumber(), 1);
+ ref.setColumnNumber(1);
+ QCOMPARE(ref.columnNumber(), 1);
+
+ QmlDebugFileReference copy(ref);
+ QmlDebugFileReference copyAssign;
+ copyAssign = ref;
+ foreach (const QmlDebugFileReference &r, (QList<QmlDebugFileReference>() << copy << copyAssign)) {
+ QCOMPARE(r.url(), ref.url());
+ QCOMPARE(r.lineNumber(), ref.lineNumber());
+ QCOMPARE(r.columnNumber(), ref.columnNumber());
+ }
+}
+
+void tst_QmlDebug::tst_QmlDebugEngineReference()
+{
+ QmlDebugEngineReference ref;
+ QCOMPARE(ref.debugId(), -1);
+ QVERIFY(ref.name().isEmpty());
+
+ ref = QmlDebugEngineReference(1);
+ QCOMPARE(ref.debugId(), 1);
+ QVERIFY(ref.name().isEmpty());
+
+ QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
+ waitForQuery(q_engines);
+ ref = q_engines->engines()[0];
+ delete q_engines;
+
+ QmlDebugEngineReference copy(ref);
+ QmlDebugEngineReference copyAssign;
+ copyAssign = ref;
+ foreach (const QmlDebugEngineReference &r, (QList<QmlDebugEngineReference>() << copy << copyAssign)) {
+ QCOMPARE(r.debugId(), ref.debugId());
+ QCOMPARE(r.name(), ref.name());
+ }
+}
+
+void tst_QmlDebug::tst_QmlDebugObjectReference()
+{
+ QmlDebugObjectReference ref;
+ QCOMPARE(ref.debugId(), -1);
+ QCOMPARE(ref.className(), QString());
+ QCOMPARE(ref.name(), QString());
+ QCOMPARE(ref.contextDebugId(), -1);
+ QVERIFY(ref.properties().isEmpty());
+ QVERIFY(ref.children().isEmpty());
+
+ QmlDebugFileReference source = ref.source();
+ QVERIFY(source.url().isEmpty());
+ QVERIFY(source.lineNumber() < 0);
+ QVERIFY(source.columnNumber() < 0);
+
+ ref = QmlDebugObjectReference(1);
+ QCOMPARE(ref.debugId(), 1);
+
+ QmlDebugObjectReference rootObject = findRootObject();
+ QmlDebugObjectQuery *query = m_dbg->queryObjectRecursive(rootObject, this);
+ waitForQuery(query);
+ ref = query->object();
+ delete query;
+
+ QVERIFY(ref.debugId() >= 0);
+
+ QmlDebugObjectReference copy(ref);
+ QmlDebugObjectReference copyAssign;
+ copyAssign = ref;
+ foreach (const QmlDebugObjectReference &r, (QList<QmlDebugObjectReference>() << copy << copyAssign))
+ recursiveCompareObjects(r, ref);
+}
+
+void tst_QmlDebug::tst_QmlDebugContextReference()
+{
+ QmlDebugContextReference ref;
+ QCOMPARE(ref.debugId(), -1);
+ QVERIFY(ref.name().isEmpty());
+ QVERIFY(ref.objects().isEmpty());
+ QVERIFY(ref.contexts().isEmpty());
+
+ QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
+ waitForQuery(q_engines);
+ QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
+ waitForQuery(q_context);
+
+ ref = q_context->rootContext();
+ delete q_engines;
+ delete q_context;
+ QVERIFY(ref.debugId() >= 0);
+
+ QmlDebugContextReference copy(ref);
+ QmlDebugContextReference copyAssign;
+ copyAssign = ref;
+ foreach (const QmlDebugContextReference &r, (QList<QmlDebugContextReference>() << copy << copyAssign))
+ recursiveCompareContexts(r, ref);
+}
+
+void tst_QmlDebug::tst_QmlDebugPropertyReference()
+{
+ QmlDebugObjectReference rootObject = findRootObject();
+ QmlDebugObjectQuery *query = m_dbg->queryObject(rootObject, this);
+ waitForQuery(query);
+ QmlDebugObjectReference obj = query->object();
+ delete query;
+
+ QmlDebugPropertyReference ref = findProperty(obj.properties(), "scale");
+ QVERIFY(ref.objectDebugId() > 0);
+ QVERIFY(!ref.name().isEmpty());
+ QVERIFY(!ref.value().isNull());
+ QVERIFY(!ref.valueTypeName().isEmpty());
+ QVERIFY(!ref.binding().isEmpty());
+ QVERIFY(ref.hasNotifySignal());
+
+ QmlDebugPropertyReference copy(ref);
+ QmlDebugPropertyReference copyAssign;
+ copyAssign = ref;
+ foreach (const QmlDebugPropertyReference &r, (QList<QmlDebugPropertyReference>() << copy << copyAssign))
+ compareProperties(r, ref);
+}
+
+
+class tst_QmlDebug_Factory : public QmlTestFactory
+{
+public:
+ QObject *createTest(QmlDebugTestData *data)
+ {
+ QmlContext *c = new QmlContext(data->engine->rootContext());
+ c->setObjectName("tst_QmlDebug_childContext");
+ return new tst_QmlDebug(data);
+ }
+};
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ QList<QByteArray> qml;
+ qml << "import Qt 4.6\n"
+ "Item {"
+ "width: 10; height: 20; scale: blueRect.scale;"
+ "Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }"
+ "Text { color: blueRect.color; }"
+ "MouseRegion {"
+ "onEntered: { console.log('hello') }"
+ "}"
+ "}";
+ // add second component to test multiple root contexts
+ qml << "import Qt 4.6\n"
+ "Item {}";
+ tst_QmlDebug_Factory factory;
+ return QmlDebugTest::runTests(&factory, qml);
+}
+
+//QTEST_MAIN(tst_QmlDebug)
+
+#include "tst_qmldebug.moc"
diff --git a/tests/auto/declarative/qmldebugclient/qmldebugclient.pro b/tests/auto/declarative/qmldebugclient/qmldebugclient.pro
new file mode 100644
index 0000000..36aa818
--- /dev/null
+++ b/tests/auto/declarative/qmldebugclient/qmldebugclient.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += network declarative
+macx:CONFIG -= app_bundle
+
+HEADERS += ../shared/debugutil_p.h
+SOURCES += tst_qmldebugclient.cpp \
+ ../shared/debugutil.cpp
diff --git a/tests/auto/declarative/qmldebugclient/tst_qmldebugclient.cpp b/tests/auto/declarative/qmldebugclient/tst_qmldebugclient.cpp
new file mode 100644
index 0000000..4ee0837
--- /dev/null
+++ b/tests/auto/declarative/qmldebugclient/tst_qmldebugclient.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QSignalSpy>
+#include <QTimer>
+#include <QHostAddress>
+#include <QDebug>
+#include <QThread>
+
+#include <QtDeclarative/qmlengine.h>
+
+#include <private/qmldebug_p.h>
+#include <private/qmlenginedebug_p.h>
+#include <private/qmldebugclient_p.h>
+#include <private/qmldebugservice_p.h>
+
+#include "../shared/debugutil_p.h"
+
+class tst_QmlDebugClient : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QmlDebugClient(QmlDebugTestData *data)
+ {
+ m_conn = data->conn;
+ }
+
+ QmlDebugConnection *m_conn;
+
+private slots:
+ void name();
+ void isEnabled();
+ void setEnabled();
+ void isConnected();
+ void sendMessage();
+};
+
+void tst_QmlDebugClient::name()
+{
+ QString name = "tst_QmlDebugClient::name()";
+
+ QmlDebugClient client(name, m_conn);
+ QCOMPARE(client.name(), name);
+}
+
+void tst_QmlDebugClient::isEnabled()
+{
+ QmlDebugClient client("tst_QmlDebugClient::isEnabled()", m_conn);
+ QCOMPARE(client.isEnabled(), false);
+}
+
+void tst_QmlDebugClient::setEnabled()
+{
+ QmlDebugTestService service("tst_QmlDebugClient::setEnabled()");
+ QmlDebugTestClient client("tst_QmlDebugClient::setEnabled()", m_conn);
+
+ QCOMPARE(service.isEnabled(), false);
+
+ client.setEnabled(true);
+ QCOMPARE(client.isEnabled(), true);
+ QmlDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged()));
+ QCOMPARE(service.isEnabled(), true);
+
+ client.setEnabled(false);
+ QCOMPARE(client.isEnabled(), false);
+ QmlDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged()));
+ QCOMPARE(service.isEnabled(), false);
+}
+
+void tst_QmlDebugClient::isConnected()
+{
+ QmlDebugClient client1("tst_QmlDebugClient::isConnected() A", m_conn);
+ QCOMPARE(client1.isConnected(), true);
+
+ QmlDebugConnection conn;
+ QmlDebugClient client2("tst_QmlDebugClient::isConnected() B", &conn);
+ QCOMPARE(client2.isConnected(), false);
+
+ QmlDebugClient client3("tst_QmlDebugClient::isConnected() C", 0);
+ QCOMPARE(client3.isConnected(), false);
+
+ // duplicate plugin name
+ QTest::ignoreMessage(QtWarningMsg, "QmlDebugClient: Conflicting plugin name \"tst_QmlDebugClient::isConnected() A\" ");
+ QmlDebugClient client4("tst_QmlDebugClient::isConnected() A", m_conn);
+ QCOMPARE(client4.isConnected(), false);
+}
+
+void tst_QmlDebugClient::sendMessage()
+{
+ QmlDebugTestService service("tst_QmlDebugClient::sendMessage()");
+ QmlDebugTestClient client("tst_QmlDebugClient::sendMessage()", m_conn);
+
+ QByteArray msg = "hello!";
+
+ client.sendMessage(msg);
+ QByteArray resp = client.waitForResponse();
+ QCOMPARE(resp, msg);
+}
+
+
+class tst_QmlDebugClient_Factory : public QmlTestFactory
+{
+public:
+ QObject *createTest(QmlDebugTestData *data) { return new tst_QmlDebugClient(data); }
+};
+
+
+// This does not use QTEST_MAIN because the test has to be created and run
+// in a separate thread.
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ tst_QmlDebugClient_Factory factory;
+ return QmlDebugTest::runTests(&factory);
+}
+
+#include "tst_qmldebugclient.moc"
diff --git a/tests/auto/declarative/qmldebugservice/qmldebugservice.pro b/tests/auto/declarative/qmldebugservice/qmldebugservice.pro
new file mode 100644
index 0000000..9995f1f
--- /dev/null
+++ b/tests/auto/declarative/qmldebugservice/qmldebugservice.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += network declarative
+macx:CONFIG -= app_bundle
+
+HEADERS += ../shared/debugutil_p.h
+SOURCES += tst_qmldebugservice.cpp \
+ ../shared/debugutil.cpp
diff --git a/tests/auto/declarative/qmldebugservice/tst_qmldebugservice.cpp b/tests/auto/declarative/qmldebugservice/tst_qmldebugservice.cpp
new file mode 100644
index 0000000..4e7bc27
--- /dev/null
+++ b/tests/auto/declarative/qmldebugservice/tst_qmldebugservice.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QSignalSpy>
+#include <QTimer>
+#include <QHostAddress>
+#include <QDebug>
+#include <QThread>
+
+#include <QtDeclarative/qmlengine.h>
+
+#include <private/qmldebug_p.h>
+#include <private/qmlenginedebug_p.h>
+#include <private/qmldebugclient_p.h>
+#include <private/qmldebugservice_p.h>
+
+#include "../shared/debugutil_p.h"
+
+class tst_QmlDebugService : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QmlDebugService(QmlDebugTestData *data)
+ {
+ m_conn = data->conn;
+ }
+
+ QmlDebugConnection *m_conn;
+
+private slots:
+ void name();
+ void isEnabled();
+ void enabledChanged();
+ void sendMessage();
+ void idForObject();
+ void objectForId();
+ void objectToString();
+};
+
+void tst_QmlDebugService::name()
+{
+ QString name = "tst_QmlDebugService::name()";
+
+ QmlDebugService service(name);
+ QCOMPARE(service.name(), name);
+}
+
+void tst_QmlDebugService::isEnabled()
+{
+ QmlDebugTestService service("tst_QmlDebugService::isEnabled()", m_conn);
+ QCOMPARE(service.isEnabled(), false);
+
+ QmlDebugTestClient client("tst_QmlDebugService::isEnabled()", m_conn);
+ client.setEnabled(true);
+ QmlDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged()));
+ QCOMPARE(service.isEnabled(), true);
+
+ QTest::ignoreMessage(QtWarningMsg, "QmlDebugService: Conflicting plugin name \"tst_QmlDebugService::isEnabled()\" ");
+ QmlDebugService duplicate("tst_QmlDebugService::isEnabled()", m_conn);
+ QCOMPARE(duplicate.isEnabled(), false);
+}
+
+void tst_QmlDebugService::enabledChanged()
+{
+ QmlDebugTestService service("tst_QmlDebugService::enabledChanged()");
+ QmlDebugTestClient client("tst_QmlDebugService::enabledChanged()", m_conn);
+
+ QCOMPARE(service.enabled, false);
+
+ client.setEnabled(true);
+ QmlDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged()));
+ QCOMPARE(service.enabled, true);
+}
+
+void tst_QmlDebugService::sendMessage()
+{
+ QmlDebugTestService service("tst_QmlDebugService::sendMessage()");
+ QmlDebugTestClient client("tst_QmlDebugService::sendMessage()", m_conn);
+
+ QByteArray msg = "hello!";
+
+ client.sendMessage(msg);
+ QByteArray resp = client.waitForResponse();
+ QCOMPARE(resp, msg);
+}
+
+void tst_QmlDebugService::idForObject()
+{
+ QCOMPARE(QmlDebugService::idForObject(0), -1);
+
+ QObject *objA = new QObject;
+
+ int idA = QmlDebugService::idForObject(objA);
+ QVERIFY(idA >= 0);
+ QCOMPARE(QmlDebugService::objectForId(idA), objA);
+
+ int idAA = QmlDebugService::idForObject(objA);
+ QCOMPARE(idAA, idA);
+
+ QObject *objB = new QObject;
+ int idB = QmlDebugService::idForObject(objB);
+ QVERIFY(idB != idA);
+ QCOMPARE(QmlDebugService::objectForId(idB), objB);
+
+ delete objA;
+ delete objB;
+}
+
+void tst_QmlDebugService::objectForId()
+{
+ QCOMPARE(QmlDebugService::objectForId(-1), static_cast<QObject*>(0));
+ QCOMPARE(QmlDebugService::objectForId(1), static_cast<QObject*>(0));
+
+ QObject *obj = new QObject;
+ int id = QmlDebugService::idForObject(obj);
+ QCOMPARE(QmlDebugService::objectForId(id), obj);
+
+ delete obj;
+ QCOMPARE(QmlDebugService::objectForId(id), static_cast<QObject*>(0));
+}
+
+void tst_QmlDebugService::objectToString()
+{
+ QCOMPARE(QmlDebugService::objectToString(0), QString("NULL"));
+
+ QObject *obj = new QObject;
+ QCOMPARE(QmlDebugService::objectToString(obj), QString("QObject: <unnamed>"));
+
+ obj->setObjectName("Hello");
+ QCOMPARE(QmlDebugService::objectToString(obj), QString("QObject: Hello"));
+}
+
+
+class tst_QmlDebugService_Factory : public QmlTestFactory
+{
+public:
+ QObject *createTest(QmlDebugTestData *data) { return new tst_QmlDebugService(data); }
+};
+
+// This does not use QTEST_MAIN because the test has to be created and run
+// in a separate thread.
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ tst_QmlDebugService_Factory factory;
+ return QmlDebugTest::runTests(&factory);
+}
+
+#include "tst_qmldebugservice.moc"
diff --git a/tests/auto/declarative/qmldom/data/MyComponent.qml b/tests/auto/declarative/qmldom/data/MyComponent.qml
new file mode 100644
index 0000000..1472f01
--- /dev/null
+++ b/tests/auto/declarative/qmldom/data/MyComponent.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+Item {
+}
diff --git a/tests/auto/declarative/qmldom/data/MyItem.qml b/tests/auto/declarative/qmldom/data/MyItem.qml
new file mode 100644
index 0000000..1472f01
--- /dev/null
+++ b/tests/auto/declarative/qmldom/data/MyItem.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+Item {
+}
diff --git a/tests/auto/declarative/qmldom/data/importdir/Bar.qml b/tests/auto/declarative/qmldom/data/importdir/Bar.qml
new file mode 100644
index 0000000..2d1a4a3
--- /dev/null
+++ b/tests/auto/declarative/qmldom/data/importdir/Bar.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+
diff --git a/tests/auto/declarative/qmldom/data/importlib/sublib/qmldir/Foo.qml b/tests/auto/declarative/qmldom/data/importlib/sublib/qmldir/Foo.qml
new file mode 100644
index 0000000..2d1a4a3
--- /dev/null
+++ b/tests/auto/declarative/qmldom/data/importlib/sublib/qmldir/Foo.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+
diff --git a/tests/auto/declarative/qmldom/data/top.qml b/tests/auto/declarative/qmldom/data/top.qml
new file mode 100644
index 0000000..2681993
--- /dev/null
+++ b/tests/auto/declarative/qmldom/data/top.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+MyComponent {
+ width: 100
+ height: 100
+}
diff --git a/tests/auto/declarative/qmldom/qmldom.pro b/tests/auto/declarative/qmldom/qmldom.pro
new file mode 100644
index 0000000..7ff317d
--- /dev/null
+++ b/tests/auto/declarative/qmldom/qmldom.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmldom.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmldom/tst_qmldom.cpp b/tests/auto/declarative/qmldom/tst_qmldom.cpp
new file mode 100644
index 0000000..ce35130
--- /dev/null
+++ b/tests/auto/declarative/qmldom/tst_qmldom.cpp
@@ -0,0 +1,1313 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmldom.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+
+class tst_qmldom : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmldom() {}
+
+private slots:
+ void loadSimple();
+ void loadProperties();
+ void loadGroupedProperties();
+ void loadChildObject();
+ void loadComposite();
+ void loadImports();
+ void loadErrors();
+ void loadSyntaxErrors();
+ void loadRemoteErrors();
+ void loadDynamicProperty();
+ void loadComponent();
+
+ void testValueSource();
+ void testValueInterceptor();
+
+ void object_dynamicProperty();
+ void object_property();
+ void object_url();
+
+ void copy();
+ void position();
+private:
+ QmlEngine engine;
+};
+
+
+void tst_qmldom::loadSimple()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+ QVERIFY(document.errors().isEmpty());
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+ QVERIFY(!rootObject.isComponent());
+ QVERIFY(!rootObject.isCustomType());
+ QVERIFY(rootObject.objectType() == "Qt/Item");
+ QVERIFY(rootObject.objectTypeMajorVersion() == 4);
+ QVERIFY(rootObject.objectTypeMinorVersion() == 6);
+}
+
+// Test regular properties
+void tst_qmldom::loadProperties()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "Item { id : item; x : 300; visible : true }";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+ QVERIFY(rootObject.objectId() == "item");
+ QCOMPARE(rootObject.properties().size(), 3);
+
+ QmlDomProperty xProperty = rootObject.property("x");
+ QVERIFY(xProperty.propertyName() == "x");
+ QCOMPARE(xProperty.propertyNameParts().count(), 1);
+ QVERIFY(xProperty.propertyNameParts().at(0) == "x");
+ QCOMPARE(xProperty.position(), 32);
+ QCOMPARE(xProperty.length(), 1);
+ QVERIFY(xProperty.value().isLiteral());
+ QVERIFY(xProperty.value().toLiteral().literal() == "300");
+
+ QmlDomProperty visibleProperty = rootObject.property("visible");
+ QVERIFY(visibleProperty.propertyName() == "visible");
+ QCOMPARE(visibleProperty.propertyNameParts().count(), 1);
+ QVERIFY(visibleProperty.propertyNameParts().at(0) == "visible");
+ QCOMPARE(visibleProperty.position(), 41);
+ QCOMPARE(visibleProperty.length(), 7);
+ QVERIFY(visibleProperty.value().isLiteral());
+ QVERIFY(visibleProperty.value().toLiteral().literal() == "true");
+}
+
+// Test grouped properties
+void tst_qmldom::loadGroupedProperties()
+{
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item { anchors.left: parent.left; anchors.right: parent.right }";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QVERIFY(rootItem.properties().size() == 2);
+
+ // Order is not deterministic
+ QmlDomProperty p0 = rootItem.properties().at(0);
+ QmlDomProperty p1 = rootItem.properties().at(1);
+ QmlDomProperty leftProperty;
+ QmlDomProperty rightProperty;
+ if (p0.propertyName() == "anchors.left") {
+ leftProperty = p0;
+ rightProperty = p1;
+ } else {
+ leftProperty = p1;
+ rightProperty = p0;
+ }
+
+ QVERIFY(leftProperty.propertyName() == "anchors.left");
+ QCOMPARE(leftProperty.propertyNameParts().count(), 2);
+ QVERIFY(leftProperty.propertyNameParts().at(0) == "anchors");
+ QVERIFY(leftProperty.propertyNameParts().at(1) == "left");
+ QCOMPARE(leftProperty.position(), 21);
+ QCOMPARE(leftProperty.length(), 12);
+ QVERIFY(leftProperty.value().isBinding());
+ QVERIFY(leftProperty.value().toBinding().binding() == "parent.left");
+
+ QVERIFY(rightProperty.propertyName() == "anchors.right");
+ QCOMPARE(rightProperty.propertyNameParts().count(), 2);
+ QVERIFY(rightProperty.propertyNameParts().at(0) == "anchors");
+ QVERIFY(rightProperty.propertyNameParts().at(1) == "right");
+ QCOMPARE(rightProperty.position(), 48);
+ QCOMPARE(rightProperty.length(), 13);
+ QVERIFY(rightProperty.value().isBinding());
+ QVERIFY(rightProperty.value().toBinding().binding() == "parent.right");
+ }
+
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item { \n"
+ " anchors {\n"
+ " left: parent.left\n"
+ " right: parent.right\n"
+ " }\n"
+ "}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QVERIFY(rootItem.properties().size() == 2);
+
+ // Order is not deterministic
+ QmlDomProperty p0 = rootItem.properties().at(0);
+ QmlDomProperty p1 = rootItem.properties().at(1);
+ QmlDomProperty leftProperty;
+ QmlDomProperty rightProperty;
+ if (p0.propertyName() == "anchors.left") {
+ leftProperty = p0;
+ rightProperty = p1;
+ } else {
+ leftProperty = p1;
+ rightProperty = p0;
+ }
+
+ QVERIFY(leftProperty.propertyName() == "anchors.left");
+ QCOMPARE(leftProperty.propertyNameParts().count(), 2);
+ QVERIFY(leftProperty.propertyNameParts().at(0) == "anchors");
+ QVERIFY(leftProperty.propertyNameParts().at(1) == "left");
+ QCOMPARE(leftProperty.position(), 44);
+ QCOMPARE(leftProperty.length(), 4);
+ QVERIFY(leftProperty.value().isBinding());
+ QVERIFY(leftProperty.value().toBinding().binding() == "parent.left");
+
+ QVERIFY(rightProperty.propertyName() == "anchors.right");
+ QCOMPARE(rightProperty.propertyNameParts().count(), 2);
+ QVERIFY(rightProperty.propertyNameParts().at(0) == "anchors");
+ QVERIFY(rightProperty.propertyNameParts().at(1) == "right");
+ QCOMPARE(rightProperty.position(), 70);
+ QCOMPARE(rightProperty.length(), 5);
+ QVERIFY(rightProperty.value().isBinding());
+ QVERIFY(rightProperty.value().toBinding().binding() == "parent.right");
+ }
+
+}
+
+void tst_qmldom::loadChildObject()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "Item { Item {} }";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QVERIFY(rootItem.properties().size() == 1);
+
+ QmlDomProperty listProperty = rootItem.properties().at(0);
+ QVERIFY(listProperty.isDefaultProperty());
+ QVERIFY(listProperty.value().isList());
+
+ QmlDomList list = listProperty.value().toList();
+ QVERIFY(list.values().size() == 1);
+
+ QmlDomObject childItem = list.values().first().toObject();
+ QVERIFY(childItem.isValid());
+ QVERIFY(childItem.objectType() == "Qt/Item");
+}
+
+void tst_qmldom::loadComposite()
+{
+ QFile file(SRCDIR "/data/top.qml");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, file.readAll(), QUrl::fromLocalFile(file.fileName())));
+ QVERIFY(document.errors().isEmpty());
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QCOMPARE(rootItem.objectType(), QByteArray("MyComponent"));
+ QCOMPARE(rootItem.properties().size(), 2);
+
+ QmlDomProperty widthProperty = rootItem.property("width");
+ QVERIFY(widthProperty.value().isLiteral());
+
+ QmlDomProperty heightProperty = rootItem.property("height");
+ QVERIFY(heightProperty.value().isLiteral());
+}
+
+void tst_qmldom::testValueSource()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "Rectangle { height: SpringFollow { spring: 1.4; damping: .15; source: Math.min(Math.max(-130, value*2.2 - 130), 133); }}";
+
+ QmlEngine freshEngine;
+ QmlDomDocument document;
+ QVERIFY(document.load(&freshEngine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QmlDomProperty heightProperty = rootItem.properties().at(0);
+ QVERIFY(heightProperty.propertyName() == "height");
+ QVERIFY(heightProperty.value().isValueSource());
+
+ const QmlDomValueValueSource valueSource = heightProperty.value().toValueSource();
+ QmlDomObject valueSourceObject = valueSource.object();
+ QVERIFY(valueSourceObject.isValid());
+
+ QVERIFY(valueSourceObject.objectType() == "Qt/SpringFollow");
+
+ const QmlDomValue springValue = valueSourceObject.property("spring").value();
+ QVERIFY(!springValue.isInvalid());
+ QVERIFY(springValue.isLiteral());
+ QVERIFY(springValue.toLiteral().literal() == "1.4");
+
+ const QmlDomValue sourceValue = valueSourceObject.property("source").value();
+ QVERIFY(!sourceValue.isInvalid());
+ QVERIFY(sourceValue.isBinding());
+ QVERIFY(sourceValue.toBinding().binding() == "Math.min(Math.max(-130, value*2.2 - 130), 133)");
+}
+
+void tst_qmldom::testValueInterceptor()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "Rectangle { height: Behavior { NumberAnimation { duration: 100 } } }";
+
+ QmlEngine freshEngine;
+ QmlDomDocument document;
+ QVERIFY(document.load(&freshEngine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QmlDomProperty heightProperty = rootItem.properties().at(0);
+ QVERIFY(heightProperty.propertyName() == "height");
+ QVERIFY(heightProperty.value().isValueInterceptor());
+
+ const QmlDomValueValueInterceptor valueInterceptor = heightProperty.value().toValueInterceptor();
+ QmlDomObject valueInterceptorObject = valueInterceptor.object();
+ QVERIFY(valueInterceptorObject.isValid());
+
+ QVERIFY(valueInterceptorObject.objectType() == "Qt/Behavior");
+
+ const QmlDomValue animationValue = valueInterceptorObject.property("animation").value();
+ QVERIFY(!animationValue.isInvalid());
+ QVERIFY(animationValue.isObject());
+}
+
+// Test QmlDomDocument::imports()
+void tst_qmldom::loadImports()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "import importlib.sublib 4.7\n"
+ "import importlib.sublib 4.6 as NewFoo\n"
+ "import 'import'\n"
+ "import 'import' as X\n"
+ "Item {}";
+
+ QmlEngine engine;
+ engine.addImportPath(SRCDIR "/data");
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QCOMPARE(document.imports().size(), 5);
+
+ QmlDomImport import = document.imports().at(0);
+ QCOMPARE(import.type(), QmlDomImport::Library);
+ QCOMPARE(import.uri(), QLatin1String("Qt"));
+ QCOMPARE(import.qualifier(), QString());
+ QCOMPARE(import.version(), QLatin1String("4.6"));
+
+ import = document.imports().at(1);
+ QCOMPARE(import.type(), QmlDomImport::Library);
+ QCOMPARE(import.uri(), QLatin1String("importlib.sublib"));
+ QCOMPARE(import.qualifier(), QString());
+ QCOMPARE(import.version(), QLatin1String("4.7"));
+
+ import = document.imports().at(2);
+ QCOMPARE(import.type(), QmlDomImport::Library);
+ QCOMPARE(import.uri(), QLatin1String("importlib.sublib"));
+ QCOMPARE(import.qualifier(), QLatin1String("NewFoo"));
+ QCOMPARE(import.version(), QLatin1String("4.6"));
+
+ import = document.imports().at(3);
+ QCOMPARE(import.type(), QmlDomImport::File);
+ QCOMPARE(import.uri(), QLatin1String("import"));
+ QCOMPARE(import.qualifier(), QLatin1String(""));
+ QCOMPARE(import.version(), QLatin1String(""));
+
+ import = document.imports().at(4);
+ QCOMPARE(import.type(), QmlDomImport::File);
+ QCOMPARE(import.uri(), QLatin1String("import"));
+ QCOMPARE(import.qualifier(), QLatin1String("X"));
+ QCOMPARE(import.version(), QLatin1String(""));
+}
+
+// Test loading a file with errors
+void tst_qmldom::loadErrors()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " foo: 12\n"
+ "}";
+
+ QmlDomDocument document;
+ QVERIFY(false == document.load(&engine, qml));
+
+ QCOMPARE(document.errors().count(), 1);
+ QmlError error = document.errors().first();
+
+ QCOMPARE(error.url(), QUrl());
+ QCOMPARE(error.line(), 3);
+ QCOMPARE(error.column(), 3);
+ QCOMPARE(error.description(), QString("Cannot assign to non-existant property \"foo\""));
+}
+
+// Test loading a file with syntax errors
+void tst_qmldom::loadSyntaxErrors()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "asdf";
+
+ QmlDomDocument document;
+ QVERIFY(false == document.load(&engine, qml));
+
+ QCOMPARE(document.errors().count(), 1);
+ QmlError error = document.errors().first();
+
+ QCOMPARE(error.url(), QUrl());
+ QCOMPARE(error.line(), 2);
+ QCOMPARE(error.column(), 1);
+ QCOMPARE(error.description(), QString("Syntax error"));
+}
+
+// Test attempting to load a file with remote references
+void tst_qmldom::loadRemoteErrors()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " Script {\n"
+ " source: \"http://localhost/exampleQmlScript.js\""
+ " }\n"
+ "}";
+ QmlDomDocument document;
+ QVERIFY(false == document.load(&engine, qml));
+
+ QCOMPARE(document.errors().count(), 1);
+ QmlError error = document.errors().first();
+
+ QCOMPARE(error.url(), QUrl());
+ QCOMPARE(error.line(), -1);
+ QCOMPARE(error.column(), -1);
+ QCOMPARE(error.description(), QString("QmlDomDocument supports local types only"));
+}
+
+// Test dynamic property declarations
+void tst_qmldom::loadDynamicProperty()
+{
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " property int a\n"
+ " property bool b\n"
+ " property double c\n"
+ " property real d\n"
+ " property string e\n"
+ " property url f\n"
+ " property color g\n"
+ " property date h\n"
+ " property var i\n"
+ " property variant j\n"
+ " property QtObject k\n"
+ "}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+
+ QCOMPARE(rootObject.dynamicProperties().count(), 11);
+
+#define DP_TEST(index, name, type, test_position, test_length, propTypeName) \
+ { \
+ QmlDomDynamicProperty d = rootObject.dynamicProperties().at(index); \
+ QVERIFY(d.isValid()); \
+ QVERIFY(d.propertyName() == # name ); \
+ QVERIFY(d.propertyType() == type); \
+ QVERIFY(d.propertyTypeName() == propTypeName); \
+ QVERIFY(d.isDefaultProperty() == false); \
+ QVERIFY(d.defaultValue().isValid() == false); \
+ QCOMPARE(d.position(), test_position); \
+ QCOMPARE(d.length(), test_length); \
+ } \
+
+ DP_TEST(0, a, QVariant::Int, 25, 14, "int");
+ DP_TEST(1, b, QVariant::Bool, 44, 15, "bool");
+ DP_TEST(2, c, QVariant::Double, 64, 17, "double");
+ DP_TEST(3, d, QMetaType::QReal, 86, 15, "real");
+ DP_TEST(4, e, QVariant::String, 106, 17, "string");
+ DP_TEST(5, f, QVariant::Url, 128, 14, "url");
+ DP_TEST(6, g, QVariant::Color, 147, 16, "color");
+ DP_TEST(7, h, QVariant::Date, 168, 15, "date");
+ DP_TEST(8, i, qMetaTypeId<QVariant>(), 188, 14, "var");
+ DP_TEST(9, j, qMetaTypeId<QVariant>(), 207, 18, "variant");
+ DP_TEST(10, k, -1, 230, 19, "QtObject");
+ }
+
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " property int a: 12\n"
+ " property int b: a + 6\n"
+ " default property QtObject c\n"
+ "}\n";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+
+ QCOMPARE(rootObject.dynamicProperties().count(), 3);
+
+ {
+ QmlDomDynamicProperty d = rootObject.dynamicProperties().at(0);
+ QVERIFY(d.isDefaultProperty() == false);
+ QVERIFY(d.defaultValue().isValid());
+ QVERIFY(d.defaultValue().propertyName() == "a");
+ QVERIFY(d.defaultValue().value().isLiteral());
+ }
+
+ {
+ QmlDomDynamicProperty d = rootObject.dynamicProperties().at(1);
+ QVERIFY(d.isDefaultProperty() == false);
+ QVERIFY(d.defaultValue().isValid());
+ QVERIFY(d.defaultValue().propertyName() == "b");
+ QVERIFY(d.defaultValue().value().isBinding());
+ }
+
+ {
+ QmlDomDynamicProperty d = rootObject.dynamicProperties().at(2);
+ QVERIFY(d.isDefaultProperty() == true);
+ QVERIFY(d.defaultValue().isValid() == false);
+ }
+ }
+}
+
+// Test inline components
+void tst_qmldom::loadComponent()
+{
+ // Explicit component
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " Component {\n"
+ " id: myComponent\n"
+ " Item {}\n"
+ " }\n"
+ "}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QVERIFY(rootItem.properties().size() == 1);
+
+ QmlDomProperty listProperty = rootItem.properties().at(0);
+ QVERIFY(listProperty.isDefaultProperty());
+ QVERIFY(listProperty.value().isList());
+
+ QmlDomList list = listProperty.value().toList();
+ QVERIFY(list.values().size() == 1);
+
+ QmlDomObject componentObject = list.values().first().toObject();
+ QVERIFY(componentObject.isValid());
+ QVERIFY(componentObject.objectClassName() == "Component");
+ QVERIFY(componentObject.isComponent());
+
+ QmlDomComponent component = componentObject.toComponent();
+ QVERIFY(component.isValid());
+ QVERIFY(component.objectType() == "Qt/Component");
+ QVERIFY(component.objectTypeMajorVersion() == 4);
+ QVERIFY(component.objectTypeMinorVersion() == 6);
+ QVERIFY(component.objectClassName() == "Component");
+ QVERIFY(component.objectId() == "myComponent");
+ QVERIFY(component.properties().isEmpty());
+ QVERIFY(component.dynamicProperties().isEmpty());
+ QVERIFY(component.isCustomType() == false);
+ QVERIFY(component.customTypeData() == "");
+ QVERIFY(component.isComponent());
+ QCOMPARE(component.position(), 25);
+ QCOMPARE(component.length(), 57);
+
+ QVERIFY(component.componentRoot().isValid());
+ QVERIFY(component.componentRoot().objectClassName() == "Item");
+ }
+
+ // Implicit component
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "ListView {\n"
+ " delegate: Item {}\n"
+ "}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootItem = document.rootObject();
+ QVERIFY(rootItem.isValid());
+ QVERIFY(rootItem.properties().size() == 1);
+
+ QmlDomProperty delegate = rootItem.property("delegate");
+
+ QmlDomObject componentObject = delegate.value().toObject();
+ QVERIFY(componentObject.isValid());
+ QVERIFY(componentObject.objectClassName() == "Component");
+ QVERIFY(componentObject.isComponent());
+
+ QmlDomComponent component = componentObject.toComponent();
+ QVERIFY(component.isValid());
+ QVERIFY(component.objectType() == "Qt/Component");
+ QVERIFY(component.objectClassName() == "Component");
+ QVERIFY(component.objectId() == "");
+ QVERIFY(component.properties().isEmpty());
+ QVERIFY(component.dynamicProperties().isEmpty());
+ QVERIFY(component.isCustomType() == false);
+ QVERIFY(component.customTypeData() == "");
+ QVERIFY(component.isComponent());
+ QCOMPARE(component.position(), 39);
+ QCOMPARE(component.length(), 7);
+
+ QVERIFY(component.componentRoot().isValid());
+ QVERIFY(component.componentRoot().objectClassName() == "Item");
+ }
+}
+
+// Test QmlDomObject::dynamicProperty() method
+void tst_qmldom::object_dynamicProperty()
+{
+ // Invalid object
+ {
+ QmlDomObject object;
+ QVERIFY(object.dynamicProperty("").isValid() == false);
+ QVERIFY(object.dynamicProperty("foo").isValid() == false);
+ }
+
+
+ // Valid object, no dynamic properties
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+
+ QVERIFY(rootObject.dynamicProperty("").isValid() == false);
+ QVERIFY(rootObject.dynamicProperty("foo").isValid() == false);
+ }
+
+ // Valid object, dynamic properties
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " property int a\n"
+ "}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+
+ QVERIFY(rootObject.dynamicProperty("").isValid() == false);
+ QVERIFY(rootObject.dynamicProperty("foo").isValid() == false);
+
+ QmlDomDynamicProperty p = rootObject.dynamicProperty("a");
+ QVERIFY(p.isValid());
+ QVERIFY(p.propertyName() == "a");
+ QVERIFY(p.propertyType() == QVariant::Int);
+ QVERIFY(p.propertyTypeName() == "int");
+ QVERIFY(p.isDefaultProperty() == false);
+ QCOMPARE(p.position(), 25);
+ QCOMPARE(p.length(), 14);
+ }
+
+}
+
+// Test QmlObject::property() method
+void tst_qmldom::object_property()
+{
+ // Invalid object
+ {
+ QmlDomObject object;
+ QVERIFY(object.property("").isValid() == false);
+ QVERIFY(object.property("foo").isValid() == false);
+ }
+
+ // Valid object - no default
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " x: 10\n"
+ " y: 12\n"
+ "}\n";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+
+ QVERIFY(rootObject.property("").isValid() == false);
+ QVERIFY(rootObject.property("foo").isValid() == false);
+
+ QmlDomProperty x = rootObject.property("x");
+ QVERIFY(x.isValid());
+ QVERIFY(x.propertyName() == "x");
+ QVERIFY(x.propertyNameParts().count() == 1);
+ QVERIFY(x.propertyNameParts().at(0) == "x");
+ QVERIFY(x.isDefaultProperty() == false);
+ QVERIFY(x.value().isLiteral());
+ QVERIFY(x.value().toLiteral().literal() == "10");
+ QCOMPARE(x.position(), 25);
+ QCOMPARE(x.length(), 1);
+
+ QmlDomProperty y = rootObject.property("y");
+ QVERIFY(y.isValid());
+ QVERIFY(y.propertyName() == "y");
+ QVERIFY(y.propertyNameParts().count() == 1);
+ QVERIFY(y.propertyNameParts().at(0) == "y");
+ QVERIFY(y.isDefaultProperty() == false);
+ QVERIFY(y.value().isLiteral());
+ QVERIFY(y.value().toLiteral().literal() == "12");
+ QCOMPARE(y.position(), 35);
+ QCOMPARE(y.length(), 1);
+ }
+
+ // Valid object - with default
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {\n"
+ " x: 10\n"
+ " y: 12\n"
+ " Item {}\n"
+ "}\n";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+
+ QVERIFY(rootObject.property("").isValid() == false);
+ QVERIFY(rootObject.property("foo").isValid() == false);
+
+ QmlDomProperty x = rootObject.property("x");
+ QVERIFY(x.isValid());
+ QVERIFY(x.propertyName() == "x");
+ QVERIFY(x.propertyNameParts().count() == 1);
+ QVERIFY(x.propertyNameParts().at(0) == "x");
+ QVERIFY(x.isDefaultProperty() == false);
+ QVERIFY(x.value().isLiteral());
+ QVERIFY(x.value().toLiteral().literal() == "10");
+ QCOMPARE(x.position(), 25);
+ QCOMPARE(x.length(), 1);
+
+ QmlDomProperty y = rootObject.property("y");
+ QVERIFY(y.isValid());
+ QVERIFY(y.propertyName() == "y");
+ QVERIFY(y.propertyNameParts().count() == 1);
+ QVERIFY(y.propertyNameParts().at(0) == "y");
+ QVERIFY(y.isDefaultProperty() == false);
+ QVERIFY(y.value().isLiteral());
+ QVERIFY(y.value().toLiteral().literal() == "12");
+ QCOMPARE(y.position(), 35);
+ QCOMPARE(y.length(), 1);
+
+ QmlDomProperty data = rootObject.property("data");
+ QVERIFY(data.isValid());
+ QVERIFY(data.propertyName() == "data");
+ QVERIFY(data.propertyNameParts().count() == 1);
+ QVERIFY(data.propertyNameParts().at(0) == "data");
+ QVERIFY(data.isDefaultProperty() == true);
+ QVERIFY(data.value().isList());
+ QCOMPARE(data.position(), 45);
+ QCOMPARE(data.length(), 0);
+ }
+}
+
+// Tests the QmlDomObject::url() method
+void tst_qmldom::object_url()
+{
+ // Invalid object
+ {
+ QmlDomObject object;
+ QCOMPARE(object.url(), QUrl());
+ }
+
+ // Valid builtin object
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "Item {}";
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+ QCOMPARE(rootObject.url(), QUrl());
+ }
+
+ // Valid composite object
+ {
+ QByteArray qml = "import Qt 4.6\n"
+ "MyItem {}";
+
+ QUrl myUrl = QUrl::fromLocalFile(SRCDIR "/data/main.qml");
+ QUrl subUrl = QUrl::fromLocalFile(SRCDIR "/data/MyItem.qml");
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml, myUrl));
+
+ QmlDomObject rootObject = document.rootObject();
+ QVERIFY(rootObject.isValid());
+ QCOMPARE(rootObject.url(), subUrl);
+ }
+}
+
+// Test copy constructors and operators
+void tst_qmldom::copy()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ "MyItem {\n"
+ " id: myItem\n"
+ " property int a: 10\n"
+ " x: 10\n"
+ " y: x + 10\n"
+ " z: NumberAnimation {}\n"
+ " opacity: Behavior {}\n"
+ " Component {\n"
+ " Item{}\n"
+ " }\n"
+ " children: [ Item{}, Item{} ]\n"
+ "}\n";
+
+ QUrl myUrl = QUrl::fromLocalFile(SRCDIR "/data/main.qml");
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml, myUrl));
+
+ // QmlDomDocument
+ {
+ QmlDomDocument document2(document);
+ QmlDomDocument document3;
+ document3 = document;
+
+ QCOMPARE(document.imports().count(), document2.imports().count());
+ QCOMPARE(document.errors().count(), document2.errors().count());
+ QCOMPARE(document.rootObject().objectClassName(), document2.rootObject().objectClassName());
+
+ QCOMPARE(document.imports().count(), document3.imports().count());
+ QCOMPARE(document.errors().count(), document3.errors().count());
+ QCOMPARE(document.rootObject().objectClassName(), document3.rootObject().objectClassName());
+ }
+
+ // QmlDomImport
+ {
+ QCOMPARE(document.imports().count(), 1);
+ QmlDomImport import = document.imports().at(0);
+
+ QmlDomImport import2(import);
+ QmlDomImport import3;
+ import3 = import2;
+
+ QCOMPARE(import.type(), import2.type());
+ QCOMPARE(import.uri(), import2.uri());
+ QCOMPARE(import.version(), import2.version());
+ QCOMPARE(import.qualifier(), import2.qualifier());
+
+ QCOMPARE(import.type(), import3.type());
+ QCOMPARE(import.uri(), import3.uri());
+ QCOMPARE(import.version(), import3.version());
+ QCOMPARE(import.qualifier(), import3.qualifier());
+ }
+
+ // QmlDomObject
+ {
+ QmlDomObject object = document.rootObject();
+ QVERIFY(object.isValid());
+
+ QmlDomObject object2(object);
+ QmlDomObject object3;
+ object3 = object;
+
+ QCOMPARE(object.isValid(), object2.isValid());
+ QCOMPARE(object.objectType(), object2.objectType());
+ QCOMPARE(object.objectClassName(), object2.objectClassName());
+ QCOMPARE(object.objectTypeMajorVersion(), object2.objectTypeMajorVersion());
+ QCOMPARE(object.objectTypeMinorVersion(), object2.objectTypeMinorVersion());
+ QCOMPARE(object.objectId(), object2.objectId());
+ QCOMPARE(object.properties().count(), object2.properties().count());
+ QCOMPARE(object.dynamicProperties().count(), object2.dynamicProperties().count());
+ QCOMPARE(object.isCustomType(), object2.isCustomType());
+ QCOMPARE(object.customTypeData(), object2.customTypeData());
+ QCOMPARE(object.isComponent(), object2.isComponent());
+ QCOMPARE(object.position(), object2.position());
+ QCOMPARE(object.length(), object2.length());
+ QCOMPARE(object.url(), object2.url());
+
+ QCOMPARE(object.isValid(), object3.isValid());
+ QCOMPARE(object.objectType(), object3.objectType());
+ QCOMPARE(object.objectClassName(), object3.objectClassName());
+ QCOMPARE(object.objectTypeMajorVersion(), object3.objectTypeMajorVersion());
+ QCOMPARE(object.objectTypeMinorVersion(), object3.objectTypeMinorVersion());
+ QCOMPARE(object.objectId(), object3.objectId());
+ QCOMPARE(object.properties().count(), object3.properties().count());
+ QCOMPARE(object.dynamicProperties().count(), object3.dynamicProperties().count());
+ QCOMPARE(object.isCustomType(), object3.isCustomType());
+ QCOMPARE(object.customTypeData(), object3.customTypeData());
+ QCOMPARE(object.isComponent(), object3.isComponent());
+ QCOMPARE(object.position(), object3.position());
+ QCOMPARE(object.length(), object3.length());
+ QCOMPARE(object.url(), object3.url());
+ }
+
+ // QmlDomDynamicProperty
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomDynamicProperty property = object.dynamicProperty("a");
+
+ QmlDomDynamicProperty property2(property);
+ QmlDomDynamicProperty property3;
+ property3 = property;
+
+ QCOMPARE(property.isValid(), property2.isValid());
+ QCOMPARE(property.propertyName(), property2.propertyName());
+ QCOMPARE(property.propertyType(), property2.propertyType());
+ QCOMPARE(property.propertyTypeName(), property2.propertyTypeName());
+ QCOMPARE(property.isDefaultProperty(), property2.isDefaultProperty());
+ QCOMPARE(property.defaultValue().propertyName(), property2.defaultValue().propertyName());
+ QCOMPARE(property.position(), property2.position());
+ QCOMPARE(property.length(), property2.length());
+
+ QCOMPARE(property.isValid(), property3.isValid());
+ QCOMPARE(property.propertyName(), property3.propertyName());
+ QCOMPARE(property.propertyType(), property3.propertyType());
+ QCOMPARE(property.propertyTypeName(), property3.propertyTypeName());
+ QCOMPARE(property.isDefaultProperty(), property3.isDefaultProperty());
+ QCOMPARE(property.defaultValue().propertyName(), property3.defaultValue().propertyName());
+ QCOMPARE(property.position(), property3.position());
+ QCOMPARE(property.length(), property3.length());
+ }
+
+ // QmlDomProperty
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("opacity");
+
+ QmlDomProperty property2(property);
+ QmlDomProperty property3;
+ property3 = property;
+
+ QCOMPARE(property.isValid(), property2.isValid());
+ QCOMPARE(property.propertyName(), property2.propertyName());
+ QCOMPARE(property.propertyNameParts(), property2.propertyNameParts());
+ QCOMPARE(property.isDefaultProperty(), property2.isDefaultProperty());
+ QCOMPARE(property.value().type(), property2.value().type());
+ QCOMPARE(property.position(), property2.position());
+ QCOMPARE(property.length(), property2.length());
+
+ QCOMPARE(property.isValid(), property3.isValid());
+ QCOMPARE(property.propertyName(), property3.propertyName());
+ QCOMPARE(property.propertyNameParts(), property3.propertyNameParts());
+ QCOMPARE(property.isDefaultProperty(), property3.isDefaultProperty());
+ QCOMPARE(property.value().type(), property3.value().type());
+ QCOMPARE(property.position(), property3.position());
+ QCOMPARE(property.length(), property3.length());
+ }
+
+ // QmlDomValueLiteral
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("x");
+ QmlDomValueLiteral literal = property.value().toLiteral();
+ QCOMPARE(literal.literal(), QString("10"));
+
+ QmlDomValueLiteral literal2(literal);
+ QmlDomValueLiteral literal3;
+ literal3 = literal2;
+
+ QCOMPARE(literal2.literal(), QString("10"));
+ QCOMPARE(literal3.literal(), QString("10"));
+ }
+
+
+ // QmlDomValueBinding
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("y");
+ QmlDomValueBinding binding = property.value().toBinding();
+ QCOMPARE(binding.binding(), QString("x + 10"));
+
+ QmlDomValueBinding binding2(binding);
+ QmlDomValueBinding binding3;
+ binding3 = binding2;
+
+ QCOMPARE(binding2.binding(), QString("x + 10"));
+ QCOMPARE(binding3.binding(), QString("x + 10"));
+ }
+
+ // QmlDomValueValueSource
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("z");
+ QmlDomValueValueSource source = property.value().toValueSource();
+ QCOMPARE(source.object().objectClassName(), QByteArray("NumberAnimation"));
+
+ QmlDomValueValueSource source2(source);
+ QmlDomValueValueSource source3;
+ source3 = source;
+
+ QCOMPARE(source2.object().objectClassName(), QByteArray("NumberAnimation"));
+ QCOMPARE(source3.object().objectClassName(), QByteArray("NumberAnimation"));
+ }
+
+ // QmlDomValueValueInterceptor
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("opacity");
+ QmlDomValueValueInterceptor interceptor = property.value().toValueInterceptor();
+ QCOMPARE(interceptor.object().objectClassName(), QByteArray("Behavior"));
+
+ QmlDomValueValueInterceptor interceptor2(interceptor);
+ QmlDomValueValueInterceptor interceptor3;
+ interceptor3 = interceptor;
+
+ QCOMPARE(interceptor2.object().objectClassName(), QByteArray("Behavior"));
+ QCOMPARE(interceptor3.object().objectClassName(), QByteArray("Behavior"));
+ }
+
+ // QmlDomComponent
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("data");
+ QCOMPARE(property.value().toList().values().count(), 1);
+ QmlDomComponent component =
+ property.value().toList().values().at(0).toObject().toComponent();
+ QCOMPARE(component.componentRoot().objectClassName(), QByteArray("Item"));
+
+ QmlDomComponent component2(component);
+ QmlDomComponent component3;
+ component3 = component;
+
+ QCOMPARE(component.componentRoot().objectClassName(), component2.componentRoot().objectClassName());
+ QCOMPARE(component.isValid(), component2.isValid());
+ QCOMPARE(component.objectType(), component2.objectType());
+ QCOMPARE(component.objectClassName(), component2.objectClassName());
+ QCOMPARE(component.objectTypeMajorVersion(), component2.objectTypeMajorVersion());
+ QCOMPARE(component.objectTypeMinorVersion(), component2.objectTypeMinorVersion());
+ QCOMPARE(component.objectId(), component2.objectId());
+ QCOMPARE(component.properties().count(), component2.properties().count());
+ QCOMPARE(component.dynamicProperties().count(), component2.dynamicProperties().count());
+ QCOMPARE(component.isCustomType(), component2.isCustomType());
+ QCOMPARE(component.customTypeData(), component2.customTypeData());
+ QCOMPARE(component.isComponent(), component2.isComponent());
+ QCOMPARE(component.position(), component2.position());
+ QCOMPARE(component.length(), component2.length());
+ QCOMPARE(component.url(), component2.url());
+
+ QCOMPARE(component.componentRoot().objectClassName(), component3.componentRoot().objectClassName());
+ QCOMPARE(component.isValid(), component3.isValid());
+ QCOMPARE(component.objectType(), component3.objectType());
+ QCOMPARE(component.objectClassName(), component3.objectClassName());
+ QCOMPARE(component.objectTypeMajorVersion(), component3.objectTypeMajorVersion());
+ QCOMPARE(component.objectTypeMinorVersion(), component3.objectTypeMinorVersion());
+ QCOMPARE(component.objectId(), component3.objectId());
+ QCOMPARE(component.properties().count(), component3.properties().count());
+ QCOMPARE(component.dynamicProperties().count(), component3.dynamicProperties().count());
+ QCOMPARE(component.isCustomType(), component3.isCustomType());
+ QCOMPARE(component.customTypeData(), component3.customTypeData());
+ QCOMPARE(component.isComponent(), component3.isComponent());
+ QCOMPARE(component.position(), component3.position());
+ QCOMPARE(component.length(), component3.length());
+ QCOMPARE(component.url(), component3.url());
+ }
+
+ // QmlDomValue
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("data");
+ QmlDomValue value = property.value();
+
+ QmlDomValue value2(value);
+ QmlDomValue value3;
+ value3 = value;
+
+ QCOMPARE(value.type(), value2.type());
+ QCOMPARE(value.isInvalid(), value2.isInvalid());
+ QCOMPARE(value.isLiteral(), value2.isLiteral());
+ QCOMPARE(value.isBinding(), value2.isBinding());
+ QCOMPARE(value.isValueSource(), value2.isValueSource());
+ QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
+ QCOMPARE(value.isObject(), value2.isObject());
+ QCOMPARE(value.isList(), value2.isList());
+ QCOMPARE(value.position(), value2.position());
+ QCOMPARE(value.length(), value2.length());
+
+ QCOMPARE(value.type(), value3.type());
+ QCOMPARE(value.isInvalid(), value3.isInvalid());
+ QCOMPARE(value.isLiteral(), value3.isLiteral());
+ QCOMPARE(value.isBinding(), value3.isBinding());
+ QCOMPARE(value.isValueSource(), value3.isValueSource());
+ QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
+ QCOMPARE(value.isObject(), value3.isObject());
+ QCOMPARE(value.isList(), value3.isList());
+ QCOMPARE(value.position(), value3.position());
+ QCOMPARE(value.length(), value3.length());
+ }
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("x");
+ QmlDomValue value = property.value();
+
+ QmlDomValue value2(value);
+ QmlDomValue value3;
+ value3 = value;
+
+ QCOMPARE(value.type(), value2.type());
+ QCOMPARE(value.isInvalid(), value2.isInvalid());
+ QCOMPARE(value.isLiteral(), value2.isLiteral());
+ QCOMPARE(value.isBinding(), value2.isBinding());
+ QCOMPARE(value.isValueSource(), value2.isValueSource());
+ QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
+ QCOMPARE(value.isObject(), value2.isObject());
+ QCOMPARE(value.isList(), value2.isList());
+ QCOMPARE(value.position(), value2.position());
+ QCOMPARE(value.length(), value2.length());
+
+ QCOMPARE(value.type(), value3.type());
+ QCOMPARE(value.isInvalid(), value3.isInvalid());
+ QCOMPARE(value.isLiteral(), value3.isLiteral());
+ QCOMPARE(value.isBinding(), value3.isBinding());
+ QCOMPARE(value.isValueSource(), value3.isValueSource());
+ QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
+ QCOMPARE(value.isObject(), value3.isObject());
+ QCOMPARE(value.isList(), value3.isList());
+ QCOMPARE(value.position(), value3.position());
+ QCOMPARE(value.length(), value3.length());
+ }
+ {
+ QmlDomValue value;
+
+ QmlDomValue value2(value);
+ QmlDomValue value3;
+ value3 = value;
+
+ QCOMPARE(value.type(), value2.type());
+ QCOMPARE(value.isInvalid(), value2.isInvalid());
+ QCOMPARE(value.isLiteral(), value2.isLiteral());
+ QCOMPARE(value.isBinding(), value2.isBinding());
+ QCOMPARE(value.isValueSource(), value2.isValueSource());
+ QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
+ QCOMPARE(value.isObject(), value2.isObject());
+ QCOMPARE(value.isList(), value2.isList());
+ QCOMPARE(value.position(), value2.position());
+ QCOMPARE(value.length(), value2.length());
+
+ QCOMPARE(value.type(), value3.type());
+ QCOMPARE(value.isInvalid(), value3.isInvalid());
+ QCOMPARE(value.isLiteral(), value3.isLiteral());
+ QCOMPARE(value.isBinding(), value3.isBinding());
+ QCOMPARE(value.isValueSource(), value3.isValueSource());
+ QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
+ QCOMPARE(value.isObject(), value3.isObject());
+ QCOMPARE(value.isList(), value3.isList());
+ QCOMPARE(value.position(), value3.position());
+ QCOMPARE(value.length(), value3.length());
+ }
+
+ // QmlDomList
+ {
+ QmlDomObject object = document.rootObject();
+ QmlDomProperty property = object.property("children");
+ QmlDomList list = property.value().toList();
+ QCOMPARE(list.values().count(), 2);
+
+ QmlDomList list2(list);
+ QmlDomList list3;
+ list3 = list2;
+
+ QCOMPARE(list.values().count(), list2.values().count());
+ QCOMPARE(list.position(), list2.position());
+ QCOMPARE(list.length(), list2.length());
+ QCOMPARE(list.commaPositions(), list2.commaPositions());
+
+ QCOMPARE(list.values().count(), list3.values().count());
+ QCOMPARE(list.position(), list3.position());
+ QCOMPARE(list.length(), list3.length());
+ QCOMPARE(list.commaPositions(), list3.commaPositions());
+
+ }
+}
+
+// Tests the position/length of various elements
+void tst_qmldom::position()
+{
+ QByteArray qml = "import Qt 4.6\n"
+ /*14*/ "Item {\n"
+ /*21*/ " id: myItem\n"
+ /*36*/ " property int a: 10\n"
+ /*59*/ " x: 10\n"
+ /*69*/ " y: x + 10\n"
+ /*83*/ " z: NumberAnimation {}\n"
+ /*109*/ " opacity: Behavior {}\n"
+ /*134*/ " Component {\n"
+ /*150*/ " Item{}\n"
+ /*165*/ " }\n"
+ /*171*/ " children: [ Item{}, Item{} ]\n"
+ /*204*/ "}\n";
+
+
+ QmlDomDocument document;
+ QVERIFY(document.load(&engine, qml));
+
+ QmlDomObject root = document.rootObject();
+
+ // All QmlDomDynamicProperty
+ QmlDomDynamicProperty dynProp = root.dynamicProperty("a");
+ QCOMPARE(dynProp.position(), 40);
+ QCOMPARE(dynProp.length(), 18);
+
+ // All QmlDomProperty
+ QmlDomProperty x = root.property("x");
+ QCOMPARE(x.position(), 63);
+ QCOMPARE(x.length(), 1);
+
+ QmlDomProperty y = root.property("y");
+ QCOMPARE(y.position(), 73);
+ QCOMPARE(y.length(), 1);
+
+ QmlDomProperty z = root.property("z");
+ QCOMPARE(z.position(), 87);
+ QCOMPARE(z.length(), 1);
+
+ QmlDomProperty opacity = root.property("opacity");
+ QCOMPARE(opacity.position(), 113);
+ QCOMPARE(opacity.length(), 7);
+
+ QmlDomProperty data = root.property("data");
+ QCOMPARE(data.position(), 138);
+ QCOMPARE(data.length(), 0);
+
+ QmlDomProperty children = root.property("children");
+ QCOMPARE(children.position(), 175);
+ QCOMPARE(children.length(), 8);
+
+ QmlDomList dataList = data.value().toList();
+ QCOMPARE(dataList.values().count(), 1);
+ QmlDomList childrenList = children.value().toList();
+ QCOMPARE(childrenList.values().count(), 2);
+
+ // All QmlDomObject
+ QCOMPARE(root.position(), 14);
+ QCOMPARE(root.length(), 191);
+
+ QmlDomObject numberAnimation = z.value().toValueSource().object();
+ QCOMPARE(numberAnimation.position(), 90);
+ QCOMPARE(numberAnimation.length(), 18);
+
+ QmlDomObject behavior = opacity.value().toValueInterceptor().object();
+ QCOMPARE(behavior.position(), 122);
+ QCOMPARE(behavior.length(), 11);
+
+ QmlDomObject component = dataList.values().at(0).toObject();
+ QCOMPARE(component.position(), 138);
+ QCOMPARE(component.length(), 32);
+
+ QmlDomObject componentRoot = component.toComponent().componentRoot();
+ QCOMPARE(componentRoot.position(), 158);
+ QCOMPARE(componentRoot.length(), 6);
+
+ QmlDomObject child1 = childrenList.values().at(0).toObject();
+ QCOMPARE(child1.position(), 187);
+ QCOMPARE(child1.length(), 6);
+
+ QmlDomObject child2 = childrenList.values().at(1).toObject();
+ QCOMPARE(child2.position(), 195);
+ QCOMPARE(child2.length(), 6);
+
+ // All QmlDomValue
+ QmlDomValue xValue = x.value();
+ QCOMPARE(xValue.position(), 66);
+ QCOMPARE(xValue.length(), 2);
+
+ QmlDomValue yValue = y.value();
+ QCOMPARE(yValue.position(), 76);
+ QCOMPARE(yValue.length(), 6);
+
+ QmlDomValue zValue = z.value();
+ QCOMPARE(zValue.position(), 90);
+ QCOMPARE(zValue.length(), 18);
+
+ QmlDomValue opacityValue = opacity.value();
+ QCOMPARE(opacityValue.position(), 122);
+ QCOMPARE(opacityValue.length(), 11);
+
+ QmlDomValue dataValue = data.value();
+ QCOMPARE(dataValue.position(), 138);
+ QCOMPARE(dataValue.length(), 32);
+
+ QmlDomValue child1Value = childrenList.values().at(0);
+ QCOMPARE(child1Value.position(), 187);
+ QCOMPARE(child1Value.length(), 6);
+
+ QmlDomValue child2Value = childrenList.values().at(1);
+ QCOMPARE(child2Value.position(), 195);
+ QCOMPARE(child2Value.length(), 6);
+
+ // All QmlDomList
+ qWarning("QmlListValue position test required");
+}
+
+QTEST_MAIN(tst_qmldom)
+
+#include "tst_qmldom.moc"
diff --git a/tests/auto/declarative/qmleasefollow/data/easefollow1.qml b/tests/auto/declarative/qmleasefollow/data/easefollow1.qml
new file mode 100644
index 0000000..0cc19eb
--- /dev/null
+++ b/tests/auto/declarative/qmleasefollow/data/easefollow1.qml
@@ -0,0 +1,3 @@
+import Qt 4.6
+
+EaseFollow {}
diff --git a/tests/auto/declarative/qmleasefollow/data/easefollow2.qml b/tests/auto/declarative/qmleasefollow/data/easefollow2.qml
new file mode 100644
index 0000000..b65964e
--- /dev/null
+++ b/tests/auto/declarative/qmleasefollow/data/easefollow2.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+EaseFollow {
+ source: 10; duration: 300; enabled: true; reversingMode: EaseFollow.Immediate
+}
diff --git a/tests/auto/declarative/qmleasefollow/data/easefollow3.qml b/tests/auto/declarative/qmleasefollow/data/easefollow3.qml
new file mode 100644
index 0000000..f8886e9
--- /dev/null
+++ b/tests/auto/declarative/qmleasefollow/data/easefollow3.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+EaseFollow {
+ source: 10; velocity: 250; enabled: false; reversingMode: EaseFollow.Sync
+ maximumEasingTime: 150
+}
diff --git a/tests/auto/declarative/qmleasefollow/qmleasefollow.pro b/tests/auto/declarative/qmleasefollow/qmleasefollow.pro
new file mode 100644
index 0000000..4224a7e
--- /dev/null
+++ b/tests/auto/declarative/qmleasefollow/qmleasefollow.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmleasefollow.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmleasefollow/tst_qmleasefollow.cpp b/tests/auto/declarative/qmleasefollow/tst_qmleasefollow.cpp
new file mode 100644
index 0000000..384ce25b
--- /dev/null
+++ b/tests/auto/declarative/qmleasefollow/tst_qmleasefollow.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmleasefollow_p.h>
+#include <private/qmlvaluetype_p.h>
+#include "../../../shared/util.h"
+
+class tst_qmleasefollow : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmleasefollow();
+
+private slots:
+ void defaultValues();
+ void values();
+ void disabled();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmleasefollow::tst_qmleasefollow()
+{
+}
+
+void tst_qmleasefollow::defaultValues()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/easefollow1.qml"));
+ QmlEaseFollow *obj = qobject_cast<QmlEaseFollow*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->sourceValue(), 0.);
+ QCOMPARE(obj->velocity(), 200.);
+ QCOMPARE(obj->enabled(), true);
+ QCOMPARE(obj->duration(), -1.);
+ QCOMPARE(obj->maximumEasingTime(), -1.);
+ QCOMPARE(obj->reversingMode(), QmlEaseFollow::Eased);
+
+ delete obj;
+}
+
+void tst_qmleasefollow::values()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/easefollow2.qml"));
+ QmlEaseFollow *obj = qobject_cast<QmlEaseFollow*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->sourceValue(), 10.);
+ QCOMPARE(obj->velocity(), 200.);
+ QCOMPARE(obj->enabled(), true);
+ QCOMPARE(obj->duration(), 300.);
+ QCOMPARE(obj->maximumEasingTime(), -1.);
+ QCOMPARE(obj->reversingMode(), QmlEaseFollow::Immediate);
+
+ delete obj;
+}
+
+void tst_qmleasefollow::disabled()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/easefollow3.qml"));
+ QmlEaseFollow *obj = qobject_cast<QmlEaseFollow*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->sourceValue(), 10.);
+ QCOMPARE(obj->velocity(), 250.);
+ QCOMPARE(obj->enabled(), false);
+ QCOMPARE(obj->maximumEasingTime(), 150.);
+ QCOMPARE(obj->reversingMode(), QmlEaseFollow::Sync);
+
+ delete obj;
+}
+
+QTEST_MAIN(tst_qmleasefollow)
+
+#include "tst_qmleasefollow.moc"
diff --git a/tests/auto/declarative/qmlecmascript/data/ConstantsOverrideBindings.qml b/tests/auto/declarative/qmlecmascript/data/ConstantsOverrideBindings.qml
new file mode 100644
index 0000000..b4a702b
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/ConstantsOverrideBindings.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property int c1: 0
+ property int c2: c1
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/CustomObject.qml b/tests/auto/declarative/qmlecmascript/data/CustomObject.qml
new file mode 100644
index 0000000..691d9ec
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/CustomObject.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ property string greeting: "hello world"
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/MethodsObject.qml b/tests/auto/declarative/qmlecmascript/data/MethodsObject.qml
new file mode 100644
index 0000000..f51ca86
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/MethodsObject.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ function testFunction() { return 19; }
+ function testFunction2() { return 18; }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/NestedTypeTransientErrors.qml b/tests/auto/declarative/qmlecmascript/data/NestedTypeTransientErrors.qml
new file mode 100644
index 0000000..7c32e56
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/NestedTypeTransientErrors.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ property int b: obj.prop.a
+
+ property var prop;
+ prop: QtObject {
+ property int a: 10
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml b/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml
new file mode 100644
index 0000000..b7bec63
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Item {
+ property int a: 3
+ property int binding: myFunction();
+ property int binding2: myCompFunction();
+
+ Script {
+ function myCompFunction() {
+ return a;
+ }
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/TypeForDynamicCreation.qml b/tests/auto/declarative/qmlecmascript/data/TypeForDynamicCreation.qml
new file mode 100644
index 0000000..56e0625
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/TypeForDynamicCreation.qml
@@ -0,0 +1,2 @@
+import Qt.test 1.0
+MyQmlObject{objectName:"objectThree"}
diff --git a/tests/auto/declarative/qmlecmascript/data/aliasPropertyAndBinding.qml b/tests/auto/declarative/qmlecmascript/data/aliasPropertyAndBinding.qml
new file mode 100644
index 0000000..5c3ea1f
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/aliasPropertyAndBinding.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+import Qt.test 1.0
+
+MyQmlObject {
+ property alias c1: myObject.c1
+ property int c2: 3
+ property int c3: c2
+ objectProperty: QtObject {
+ id: myObject
+ property int c1
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlecmascript/data/assignBasicTypes.2.qml b/tests/auto/declarative/qmlecmascript/data/assignBasicTypes.2.qml
new file mode 100644
index 0000000..db7f2b5
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/assignBasicTypes.2.qml
@@ -0,0 +1,26 @@
+import Qt.test 1.0
+
+MyTypeObject {
+ flagProperty: if(1) "FlagVal1 | FlagVal3"
+ enumProperty: if(1) "EnumVal2"
+ stringProperty: if(1) "Hello World!"
+ uintProperty: if(1) 10
+ intProperty: if(1) -19
+ realProperty: if(1) 23.2
+ doubleProperty: if(1) -19.7
+ floatProperty: if(1) 8.5
+ colorProperty: if(1) "red"
+ dateProperty: if(1) "1982-11-25"
+ timeProperty: if(1) "11:11:32"
+ dateTimeProperty: if(1) "2009-05-12T13:22:01"
+ pointProperty: if(1) "99,13"
+ pointFProperty: if(1) "-10.1,12.3"
+ sizeProperty: if(1) "99x13"
+ sizeFProperty: if(1) "0.1x0.2"
+ rectProperty: if(1) "9,7,100x200"
+ rectFProperty: if(1) "1000.1,-10.9,400x90.99"
+ boolProperty: if(1) true
+ variantProperty: if(1) "Hello World!"
+ vectorProperty: if(1) "10,1,2.2"
+ urlProperty: if(1) "main.qml"
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/assignBasicTypes.qml b/tests/auto/declarative/qmlecmascript/data/assignBasicTypes.qml
new file mode 100644
index 0000000..128db69
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/assignBasicTypes.qml
@@ -0,0 +1,29 @@
+import Qt.test 1.0
+import Qt 4.6
+
+MyTypeObject {
+ Component.onCompleted: {
+ flagProperty = "FlagVal1 | FlagVal3"
+ enumProperty = "EnumVal2"
+ stringProperty = "Hello World!"
+ uintProperty = 10
+ intProperty = -19
+ realProperty = 23.2
+ doubleProperty = -19.7
+ floatProperty = 8.5
+ colorProperty = "red"
+ dateProperty = "1982-11-25"
+ timeProperty = "11:11:32"
+ dateTimeProperty = "2009-05-12T13:22:01"
+ pointProperty = "99,13"
+ pointFProperty = "-10.1,12.3"
+ sizeProperty = "99x13"
+ sizeFProperty = "0.1x0.2"
+ rectProperty = "9,7,100x200"
+ rectFProperty = "1000.1,-10.9,400x90.99"
+ boolProperty = true
+ variantProperty = "Hello World!"
+ vectorProperty = "10,1,2.2"
+ urlProperty = "main.qml"
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml b/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml
new file mode 100644
index 0000000..061eda0
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import Qt.test 1.0 as Namespace
+
+MyQmlObject {
+ id: me
+ property int a: MyQmlObject.value
+ property int b: Namespace.MyQmlObject.value
+ property int c: me.Namespace.MyQmlObject.value
+ property int d: me.Namespace.MyQmlObject.value
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/bindingLoop.qml b/tests/auto/declarative/qmlecmascript/data/bindingLoop.qml
new file mode 100644
index 0000000..80545cf
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/bindingLoop.qml
@@ -0,0 +1,14 @@
+import Qt.test 1.0
+
+MyQmlContainer {
+ children : [
+ MyQmlObject {
+ id: object1
+ stringProperty: "hello" + object2.stringProperty
+ },
+ MyQmlObject {
+ id: object2
+ stringProperty: "hello" + object1.stringProperty
+ }
+ ]
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml b/tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml
new file mode 100644
index 0000000..3147f63
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml
@@ -0,0 +1,5 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ stringProperty: trueProperty?'pass':'fail'
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml b/tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml
new file mode 100644
index 0000000..c89bb49
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml
@@ -0,0 +1,5 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ stringProperty: falseProperty?'fail':'pass'
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/bug.1.qml b/tests/auto/declarative/qmlecmascript/data/bug.1.qml
new file mode 100644
index 0000000..266de76
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/bug.1.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+QtObject {
+ property int a: 10
+ property bool b: false
+
+ property int test
+
+ test: ((a == 10)?(a + 1):0) + ((b == true)?9:3)
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/compositePropertyType.qml b/tests/auto/declarative/qmlecmascript/data/compositePropertyType.qml
new file mode 100644
index 0000000..80a2814
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/compositePropertyType.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property CustomObject myObject
+ myObject: CustomObject { }
+
+ Component.onCompleted: console.log(myObject.greeting)
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.1.qml b/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.1.qml
new file mode 100644
index 0000000..13c5ae5
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.1.qml
@@ -0,0 +1,8 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property int c1: 0
+ property int c2: c1
+
+ onBasicSignal: c2 = 13
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.2.qml b/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.2.qml
new file mode 100644
index 0000000..207a06b
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.2.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property alias c1: myConstants.c1
+ property alias c2: myConstants.c2
+
+ objectProperty: ConstantsOverrideBindings {
+ id: myConstants
+ c2: 10
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.3.qml b/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.3.qml
new file mode 100644
index 0000000..ca9d1d8
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/constantsOverrideBindings.3.qml
@@ -0,0 +1,7 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property int c1: 0
+ property int c2: c1
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/deferredProperties.qml b/tests/auto/declarative/qmlecmascript/data/deferredProperties.qml
new file mode 100644
index 0000000..e01f708
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/deferredProperties.qml
@@ -0,0 +1,10 @@
+import Qt.test 1.0
+
+MyDeferredObject {
+ id: root
+ value: 10
+ objectProperty: MyQmlObject {
+ value: root.value
+ }
+ objectProperty2: MyQmlObject { id: blah }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/deletedObject.qml b/tests/auto/declarative/qmlecmascript/data/deletedObject.qml
new file mode 100644
index 0000000..6bc3a17
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/deletedObject.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+import Qt.test 1.0
+
+QtObject {
+ property var obj
+ obj: MyQmlObject {
+ id: myObject
+ value: 92
+ }
+
+ property bool test1: false
+ property bool test2: false
+ property bool test3: false
+ property bool test4: false
+
+ Component.onCompleted: {
+ test1 = myObject.value == 92;
+ test2 = obj.value == 92;
+
+ myObject.deleteOnSet = 1;
+
+ test3 = myObject.value == undefined;
+ // test4 = obj.value == undefined;
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/dynamicCreation.helper.qml b/tests/auto/declarative/qmlecmascript/data/dynamicCreation.helper.qml
new file mode 100644
index 0000000..d790d63
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/dynamicCreation.helper.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyQmlObject{
+ objectName: "objectTwo"
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/dynamicCreation.qml b/tests/auto/declarative/qmlecmascript/data/dynamicCreation.qml
new file mode 100644
index 0000000..ed5e571
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/dynamicCreation.qml
@@ -0,0 +1,21 @@
+import Qt.test 1.0
+
+MyQmlObject{
+ id: obj
+ objectName: "obj"
+ function createOne()
+ {
+ obj.objectProperty = createQmlObject('import Qt.test 1.0; MyQmlObject{objectName:"objectOne"}', obj);
+ }
+
+ function createTwo()
+ {
+ var component = createComponent('dynamicCreation.helper.qml');
+ obj.objectProperty = component.createObject();
+ }
+
+ function createThree()
+ {
+ obj.objectProperty = createQmlObject('TypeForDynamicCreation{}', obj);
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/dynamicDeletion.qml b/tests/auto/declarative/qmlecmascript/data/dynamicDeletion.qml
new file mode 100644
index 0000000..0855b29
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/dynamicDeletion.qml
@@ -0,0 +1,20 @@
+import Qt.test 1.0
+
+MyQmlObject{
+ id: obj
+ objectName: "obj"
+ function create()
+ {
+ obj.objectProperty = createQmlObject('import Qt.test 1.0; MyQmlObject{objectName:"emptyObject"}', obj);
+ }
+
+ function killOther()
+ {
+ obj.objectProperty.destroy(500);
+ }
+
+ function killMe()
+ {
+ obj.destroy();//Must not segfault
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/enums.1.qml b/tests/auto/declarative/qmlecmascript/data/enums.1.qml
new file mode 100644
index 0000000..6351823
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/enums.1.qml
@@ -0,0 +1,20 @@
+import Qt.test 1.0
+import Qt.test 1.0 as Namespace
+
+MyQmlObject {
+ // Enums from non-namespaced type
+ property int a: MyQmlObject.EnumValue1
+ property int b: MyQmlObject.EnumValue2
+ property int c: MyQmlObject.EnumValue3
+ property int d: MyQmlObject.EnumValue4
+
+ // Enums from namespaced type
+ property int e: Namespace.MyQmlObject.EnumValue1
+ property int f: Namespace.MyQmlObject.EnumValue2
+ property int g: Namespace.MyQmlObject.EnumValue3
+ property int h: Namespace.MyQmlObject.EnumValue4
+
+ // Test that enums don't mask attached properties
+ property int i: MyQmlObject.value
+ property int j: Namespace.MyQmlObject.value
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/enums.2.qml b/tests/auto/declarative/qmlecmascript/data/enums.2.qml
new file mode 100644
index 0000000..bdc672f
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/enums.2.qml
@@ -0,0 +1,8 @@
+import Qt.test 1.0
+import Qt.test 1.0 as Namespace
+
+MyQmlObject {
+ property int a: MyQmlObject.EnumValue10
+ property int b: Namespace.MyQmlObject.EnumValue10
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/exceptionClearsOnReeval.qml b/tests/auto/declarative/qmlecmascript/data/exceptionClearsOnReeval.qml
new file mode 100644
index 0000000..a2f0d1a
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/exceptionClearsOnReeval.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property bool test: objectProperty.objectProperty.trueProperty
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning.qml b/tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning.qml
new file mode 100644
index 0000000..acc3163
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+import Qt.test 1.0
+
+MyQmlObject {
+ Component.onCompleted:
+ { throw(new Error("JS exception")) }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning2.qml b/tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning2.qml
new file mode 100644
index 0000000..44e10c1
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/exceptionProducesWarning2.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+import Qt.test 1.0
+
+MyQmlObject {
+ value: { throw(new Error("JS exception")) }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml b/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml
new file mode 100644
index 0000000..9a82ad1
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml
@@ -0,0 +1,8 @@
+import Qt.test 1.0
+import Qt 4.6
+
+QtObject {
+ property MyExtendedObject a;
+ a: MyExtendedObject { id: root }
+ property int b: Math.max(root.extendedProperty, 0)
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/extensionObjects.qml b/tests/auto/declarative/qmlecmascript/data/extensionObjects.qml
new file mode 100644
index 0000000..a902312
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/extensionObjects.qml
@@ -0,0 +1,10 @@
+import Qt.test 1.0
+
+MyExtendedObject
+{
+ baseProperty: baseExtendedProperty
+ baseExtendedProperty: 13
+
+ coreProperty: extendedProperty
+ extendedProperty: 9
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/externalScript.1.qml b/tests/auto/declarative/qmlecmascript/data/externalScript.1.qml
new file mode 100644
index 0000000..2ac7b6e
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/externalScript.1.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ property int test: external_script_func();
+
+ Script {
+ // Single source as non-array literal
+ source: "externalScript.js"
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/externalScript.2.js b/tests/auto/declarative/qmlecmascript/data/externalScript.2.js
new file mode 100644
index 0000000..78c3a86
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/externalScript.2.js
@@ -0,0 +1,8 @@
+function external_script_func2() {
+ return a;
+}
+
+function is_a_undefined() {
+ return a == undefined;
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/externalScript.2.qml b/tests/auto/declarative/qmlecmascript/data/externalScript.2.qml
new file mode 100644
index 0000000..dec657c
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/externalScript.2.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ property int test: external_script_func();
+
+ Script {
+ // Single source as array
+ source: [ "externalScript.js" ]
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/externalScript.3.qml b/tests/auto/declarative/qmlecmascript/data/externalScript.3.qml
new file mode 100644
index 0000000..d7acf38
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/externalScript.3.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+QtObject {
+ property int test: external_script_func();
+ property int test2: external_script_func2();
+ property bool test3: is_a_undefined();
+
+ Script {
+ // Multiple script
+ source: [ "externalScript.js", "externalScript.2.js" ]
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/externalScript.4.qml b/tests/auto/declarative/qmlecmascript/data/externalScript.4.qml
new file mode 100644
index 0000000..16211aa
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/externalScript.4.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+
+QtObject {
+ property int test: external_script_func();
+ property bool test2: is_a_undefined();
+
+ // Disconnected scripts
+ Script {
+ source: "externalScript.js"
+ }
+
+ Script {
+ source: "externalScript.2.js"
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/externalScript.js b/tests/auto/declarative/qmlecmascript/data/externalScript.js
new file mode 100644
index 0000000..8928652
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/externalScript.js
@@ -0,0 +1,6 @@
+var a = 92;
+
+function external_script_func() {
+ return a;
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.1.qml b/tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.1.qml
new file mode 100644
index 0000000..2db0fc6
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.1.qml
@@ -0,0 +1,13 @@
+import Qt.test 1.0
+import Qt 4.6
+
+MyQmlObject {
+ objectProperty: if(1) otherObject
+
+ property var obj
+
+ obj: QtObject {
+ id: otherObject
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.qml b/tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.qml
new file mode 100644
index 0000000..f66428d
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/idShortcutInvalidates.qml
@@ -0,0 +1,12 @@
+import Qt.test 1.0
+import Qt 4.6
+
+MyQmlObject {
+ objectProperty: otherObject
+
+ property var obj
+
+ obj: QtObject {
+ id: otherObject
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/jsObject.qml b/tests/auto/declarative/qmlecmascript/data/jsObject.qml
new file mode 100644
index 0000000..4128c92
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/jsObject.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+QtObject {
+ property int test
+
+ Component.onCompleted: {
+ var o = new Object;
+ o.test = 92;
+ test = o.test;
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/listProperties.qml b/tests/auto/declarative/qmlecmascript/data/listProperties.qml
new file mode 100644
index 0000000..cae1721
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/listProperties.qml
@@ -0,0 +1,44 @@
+import Qt.test 1.0
+import Qt 4.6
+
+MyQmlObject {
+ id: root
+
+ objectListProperty: [
+ QtObject { property int a: 10 },
+ QtObject { property int a: 11 }
+ ]
+
+ objectQmlListProperty: [
+ QtObject { property int a: 10 },
+ QtObject { property int a: 1 },
+ QtObject { property int a: 39 }
+ ]
+
+ Script {
+ function calcTest1() {
+ var rv = 0;
+ for (var ii = 0; ii < root.objectListProperty.length; ++ii) {
+ rv += root.objectListProperty[ii].a;
+ }
+ return rv;
+ }
+
+ function calcTest2() {
+ var rv = 0;
+ for (var ii = 0; ii < root.objectQmlListProperty.length; ++ii) {
+ rv += root.objectQmlListProperty[ii].a;
+ }
+ return rv;
+ }
+ }
+
+ property int test1: calcTest1();
+ property int test2: root.objectListProperty.length
+ property int test3: calcTest2();
+ property int test4: root.objectQmlListProperty.length
+ property bool test5: root.objectQmlListProperty[1] != undefined
+ property bool test6: root.objectQmlListProperty[100] == undefined
+ property bool test7: root.objectListProperty[1] != undefined
+ property bool test8: root.objectListProperty[100] == undefined
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/listToVariant.qml b/tests/auto/declarative/qmlecmascript/data/listToVariant.qml
new file mode 100644
index 0000000..47f4e50
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/listToVariant.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ property var test: children
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/methods.1.qml b/tests/auto/declarative/qmlecmascript/data/methods.1.qml
new file mode 100644
index 0000000..0bbee16
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/methods.1.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ id: myObject
+ onBasicSignal: myObject.methodNoArgs()
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/methods.2.qml b/tests/auto/declarative/qmlecmascript/data/methods.2.qml
new file mode 100644
index 0000000..9f0c6b1
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/methods.2.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ id: myObject
+ onBasicSignal: myObject.method(163)
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/methods.3.qml b/tests/auto/declarative/qmlecmascript/data/methods.3.qml
new file mode 100644
index 0000000..79efc50
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/methods.3.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+QtObject {
+ function testFunction() { return 19; }
+
+ property int test: testFunction()
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/methods.4.qml b/tests/auto/declarative/qmlecmascript/data/methods.4.qml
new file mode 100644
index 0000000..aac711c
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/methods.4.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+MethodsObject {
+ function testFunction2() { return 17; }
+ function testFunction3() { return 16; }
+
+ property int test: testFunction()
+ property int test2: testFunction2()
+ property int test3: testFunction3()
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/methods.5.qml b/tests/auto/declarative/qmlecmascript/data/methods.5.qml
new file mode 100644
index 0000000..3d45b15
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/methods.5.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+Item {
+ property alias x: item.x
+ Item { id: item }
+
+ function testFunction() { return 9; }
+ property int test: testFunction();
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml b/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml
new file mode 100644
index 0000000..7da09e4
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ property string test: thing.stringProperty
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/nonExistantAttachedObject.qml b/tests/auto/declarative/qmlecmascript/data/nonExistantAttachedObject.qml
new file mode 100644
index 0000000..f9585db
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/nonExistantAttachedObject.qml
@@ -0,0 +1,5 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ stringProperty: MyQmlContainer.prop
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml b/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml
new file mode 100644
index 0000000..18e488a
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+
+Item {
+ id: root
+
+ property var item: child
+ Item { id: child }
+
+ property bool test1: child == child
+ property bool test2: child.parent == root
+ property bool test3: root != child
+ property bool test4: item == child
+ property bool test5: item != root
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/outerBindingOverridesInnerBinding.qml b/tests/auto/declarative/qmlecmascript/data/outerBindingOverridesInnerBinding.qml
new file mode 100644
index 0000000..0a933e8
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/outerBindingOverridesInnerBinding.qml
@@ -0,0 +1,14 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property alias c1: myConstants.c1
+ property alias c2: myConstants.c2
+ property int c3: 0
+
+ objectProperty: ConstantsOverrideBindings {
+ id: myConstants
+ c2: c3
+ }
+
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/qmlToString.qml b/tests/auto/declarative/qmlecmascript/data/qmlToString.qml
new file mode 100644
index 0000000..ac296ce
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/qmlToString.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+
+MyQmlObject{
+ id: obj
+ objectName: "objName"
+ function testToString()
+ {
+ obj.stringProperty = obj.toString();
+ }
+
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/scope.2.qml b/tests/auto/declarative/qmlecmascript/data/scope.2.qml
new file mode 100644
index 0000000..8e5aa0b
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scope.2.qml
@@ -0,0 +1,42 @@
+import Qt 4.6
+
+Item {
+ property int a: 0
+ property int b: 0
+
+ Script {
+ function b() { return 11; }
+ function c() { return 33; }
+ }
+
+ QtObject {
+ id: a
+ property int value: 19
+ }
+
+ QtObject {
+ id: c
+ property int value: 24
+ }
+
+ QtObject {
+ id: nested
+ property int a: 1
+ property int test: a.value
+ property int test2: b()
+ property int test3: c.value
+ }
+
+
+ // id takes precedence over local, and root properties
+ property int test1: a.value
+ property alias test2: nested.test
+
+ // methods takes precedence over local, and root properties
+ property int test3: b()
+ property alias test4: nested.test2
+
+ // id takes precedence over methods
+ property int test5: c.value
+ property alias test6: nested.test3
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/scope.qml b/tests/auto/declarative/qmlecmascript/data/scope.qml
new file mode 100644
index 0000000..cccd3d3
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scope.qml
@@ -0,0 +1,48 @@
+import Qt 4.6
+
+Item {
+ id: root
+
+ property int a: 1
+ property int binding: a
+ property string binding2: a + "Test"
+ property int binding3: myFunction()
+ property int binding4: myNestedFunction()
+
+ Script {
+ function myFunction() {
+ return a;
+ }
+ }
+
+ Item {
+ id: nestedObject
+
+ Script {
+ function myNestedFunction() {
+ return a;
+ }
+ }
+
+ property int a: 2
+ property int binding: a
+ property string binding2: a + "Test"
+ property int binding3: myFunction()
+ property int binding4: myNestedFunction()
+ }
+
+ ScopeObject {
+ id: compObject
+ }
+
+ property alias test1: root.binding
+ property alias test2: nestedObject.binding
+ property alias test3: root.binding2
+ property alias test4: nestedObject.binding2
+ property alias test5: root.binding3
+ property alias test6: nestedObject.binding3
+ property alias test7: root.binding4
+ property alias test8: nestedObject.binding4
+ property alias test9: compObject.binding
+ property alias test10: compObject.binding2
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptAccess.js b/tests/auto/declarative/qmlecmascript/data/scriptAccess.js
new file mode 100644
index 0000000..c00d285
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptAccess.js
@@ -0,0 +1,7 @@
+var extVariable = 19;
+
+function extMethod()
+{
+ return extVariable;
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml b/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml
new file mode 100644
index 0000000..feb6d16
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+
+Item {
+ Script {
+ function method() {
+ return 10;
+ }
+ }
+
+ Script {
+ source: "scriptAccess.js"
+ }
+
+ property int test1: method()
+ property int test2: extMethod()
+ property int test3: extVariable
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.js b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js
new file mode 100644
index 0000000..1d7b357
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js
@@ -0,0 +1,2 @@
+// Comment
+a = 10
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml
new file mode 100644
index 0000000..c2edb41
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml
@@ -0,0 +1,17 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ Script { source: "scriptErrors.js" }
+ Script { function getValue() { a = 10; return 0; } }
+
+ property int t: a.value
+ property int w: getValue();
+ property int x: undefinedObject
+ property int y: (a.value, undefinedObject)
+
+ onBasicSignal: { console.log(a.value); }
+ id: myObj
+ onAnotherBasicSignal: myObj.trueProperty = false;
+ onThirdBasicSignal: myObj.fakeProperty = "";
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml
new file mode 100644
index 0000000..58cf805
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml
@@ -0,0 +1,17 @@
+import Qt.test 1.0
+
+MyQmlContainer {
+ property bool triggerDelete: false
+
+ children: [
+ MyQmlObject {
+ // Will trigger deletion on binding assignment
+ deleteOnSet: Math.max(0, 1)
+ },
+
+ MyQmlObject {
+ // Will trigger deletion on binding assignment, but after component creation
+ deleteOnSet: if (triggerDelete) 1; else 0;
+ }
+ ]
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml
new file mode 100644
index 0000000..074851a
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml
@@ -0,0 +1,18 @@
+import Qt.test 1.0
+
+MyQmlContainer {
+ property bool triggerDelete: false
+
+ children: [
+ MyQmlObject {
+ // Will trigger deletion during binding evaluation
+ stringProperty: {deleteMe(), "Hello"}
+ },
+
+ MyQmlObject {
+ // Will trigger deletion during binding evaluation, but after component creation
+ stringProperty: if (triggerDelete) { deleteMe(), "Hello" } else { "World" }
+ }
+
+ ]
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/shutdownErrors.qml b/tests/auto/declarative/qmlecmascript/data/shutdownErrors.qml
new file mode 100644
index 0000000..5a19639
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/shutdownErrors.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+Item {
+ property int test: myObject.object.a
+
+ Item {
+ id: myObject
+ property QtObject object;
+ object: QtObject {
+ property int a: 10
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/signalAssignment.1.qml b/tests/auto/declarative/qmlecmascript/data/signalAssignment.1.qml
new file mode 100644
index 0000000..fbd0914
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/signalAssignment.1.qml
@@ -0,0 +1,5 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ onBasicSignal: setString('pass')
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/signalAssignment.2.qml b/tests/auto/declarative/qmlecmascript/data/signalAssignment.2.qml
new file mode 100644
index 0000000..8addcb9
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/signalAssignment.2.qml
@@ -0,0 +1,5 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ onArgumentSignal: setString('pass ' + a + ' ' + b + ' ' + c)
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml b/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml
new file mode 100644
index 0000000..6fc8b02
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml
@@ -0,0 +1,16 @@
+import Qt.test 1.0
+
+MyQmlObject
+{
+ id: root
+ property int intProperty
+ property real realProperty
+ property color colorProperty
+ property var variantProperty
+
+ signal mySignal(int a, real b, color c, var d)
+
+ onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; }
+
+ onBasicSignal: root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1))
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml b/tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml
new file mode 100644
index 0000000..7d419cd
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml
@@ -0,0 +1,20 @@
+import Qt.test 1.0
+import Qt 4.6
+
+MyQmlObject {
+ property real base: 50
+ property alias test1: myObject.test1
+ property alias test2: myObject.test2
+
+ objectProperty: QtObject {
+ id: myObject
+ property real test1: base
+ property real test2: Math.max(0, base)
+ }
+
+ // Signal with no args
+ onBasicSignal: base = 200
+ // Signal with args
+ onArgumentSignal: base = 400
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/transientErrors.qml b/tests/auto/declarative/qmlecmascript/data/transientErrors.qml
new file mode 100644
index 0000000..fa7e01c
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/transientErrors.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+QtObject {
+ property var obj: nested
+
+ property var obj2
+ obj2: NestedTypeTransientErrors {
+ id: nested
+ }
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.2.qml b/tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.2.qml
new file mode 100644
index 0000000..e73d38e2
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.2.qml
@@ -0,0 +1,10 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ resettableProperty: 19
+
+ function doReset() {
+ resettableProperty = undefined;
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.qml b/tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.qml
new file mode 100644
index 0000000..eceff60
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/undefinedResetsProperty.qml
@@ -0,0 +1,7 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property bool setUndefined: false
+
+ resettableProperty: setUndefined?undefined:92
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/valueTypeFunctions.qml b/tests/auto/declarative/qmlecmascript/data/valueTypeFunctions.qml
new file mode 100644
index 0000000..33b4a68
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/valueTypeFunctions.qml
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+
+MyTypeObject {
+ rectProperty: Qt.rect(0,0,100,100)
+ rectFProperty: Qt.rect(0,0.5,100,99.5)
+}
diff --git a/tests/auto/declarative/qmlecmascript/qmlecmascript.pro b/tests/auto/declarative/qmlecmascript/qmlecmascript.pro
new file mode 100644
index 0000000..9f592e8
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/qmlecmascript.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative script
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlecmascript.cpp \
+ testtypes.cpp
+HEADERS += testtypes.h
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
diff --git a/tests/auto/declarative/qmlecmascript/testtypes.cpp b/tests/auto/declarative/qmlecmascript/testtypes.cpp
new file mode 100644
index 0000000..df0cb18
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/testtypes.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "testtypes.h"
+
+class BaseExtensionObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int baseExtendedProperty READ extendedProperty WRITE setExtendedProperty NOTIFY extendedPropertyChanged);
+public:
+ BaseExtensionObject(QObject *parent) : QObject(parent), m_value(0) {}
+
+ int extendedProperty() const { return m_value; }
+ void setExtendedProperty(int v) { m_value = v; emit extendedPropertyChanged(); }
+
+signals:
+ void extendedPropertyChanged();
+private:
+ int m_value;
+};
+
+class ExtensionObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int extendedProperty READ extendedProperty WRITE setExtendedProperty NOTIFY extendedPropertyChanged);
+public:
+ ExtensionObject(QObject *parent) : QObject(parent), m_value(0) {}
+
+ int extendedProperty() const { return m_value; }
+ void setExtendedProperty(int v) { m_value = v; emit extendedPropertyChanged(); }
+
+signals:
+ void extendedPropertyChanged();
+private:
+ int m_value;
+};
+
+QML_DEFINE_TYPE(Qt.test, 1,0, MyQmlObject,MyQmlObject);
+QML_DEFINE_TYPE(Qt.test, 1,0, MyDeferredObject,MyDeferredObject);
+QML_DEFINE_TYPE(Qt.test, 1,0, MyQmlContainer,MyQmlContainer);
+QML_DEFINE_EXTENDED_TYPE(Qt.test, 1,0, MyBaseExtendedObject,MyBaseExtendedObject,BaseExtensionObject);
+QML_DEFINE_EXTENDED_TYPE(Qt.test, 1,0, MyExtendedObject,MyExtendedObject,ExtensionObject);
+QML_DEFINE_TYPE(Qt.test, 1,0, MyTypeObject, MyTypeObject);
+
+#include "testtypes.moc"
diff --git a/tests/auto/declarative/qmlecmascript/testtypes.h b/tests/auto/declarative/qmlecmascript/testtypes.h
new file mode 100644
index 0000000..09c850d
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/testtypes.h
@@ -0,0 +1,595 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TESTTYPES_H
+#define TESTTYPES_H
+
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsize.h>
+#include <QtDeclarative/qmllist.h>
+#include <QtCore/qrect.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qvector3d.h>
+#include <QtCore/qdatetime.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qmlscriptstring.h>
+#include <QtDeclarative/qmlcomponent.h>
+
+class MyQmlAttachedObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value CONSTANT)
+public:
+ MyQmlAttachedObject(QObject *parent) : QObject(parent) {}
+
+ int value() const { return 19; }
+};
+
+class MyQmlObject : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(MyEnum)
+ Q_ENUMS(MyEnum2)
+ Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet)
+ Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT)
+ Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT)
+ Q_PROPERTY(int value READ value WRITE setValue)
+ Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged)
+ Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged)
+ Q_PROPERTY(QmlList<QObject *> *objectQmlListProperty READ objectQmlListProperty CONSTANT)
+ Q_PROPERTY(QList<QObject *> *objectListProperty READ objectListProperty CONSTANT)
+ Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
+
+public:
+ MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13) {}
+
+ enum MyEnum { EnumValue1 = 0, EnumValue2 = 1 };
+ enum MyEnum2 { EnumValue3 = 2, EnumValue4 = 3 };
+
+ bool trueProperty() const { return true; }
+ bool falseProperty() const { return false; }
+
+ QString stringProperty() const { return m_string; }
+ void setStringProperty(const QString &s)
+ {
+ if (s == m_string)
+ return;
+ m_string = s;
+ emit stringChanged();
+ }
+
+ QObject *objectProperty() const { return m_object; }
+ void setObjectProperty(QObject *obj) {
+ if (obj == m_object)
+ return;
+ m_object = obj;
+ emit objectChanged();
+ }
+
+ QmlList<QObject *> *objectQmlListProperty() { return &m_objectQmlList; }
+ QList<QObject *> *objectListProperty() { return &m_objectQList; }
+
+ bool methodCalled() const { return m_methodCalled; }
+ bool methodIntCalled() const { return m_methodIntCalled; }
+
+ QString string() const { return m_string; }
+
+ static MyQmlAttachedObject *qmlAttachedProperties(QObject *o) {
+ return new MyQmlAttachedObject(o);
+ }
+
+ int deleteOnSet() const { return 1; }
+ void setDeleteOnSet(int v) { if(v) delete this; }
+
+ int value() const { return m_value; }
+ void setValue(int v) { m_value = v; }
+
+ int resettableProperty() const { return m_resetProperty; }
+ void setResettableProperty(int v) { m_resetProperty = v; }
+ void resetProperty() { m_resetProperty = 13; }
+
+signals:
+ void basicSignal();
+ void argumentSignal(int a, QString b, qreal c);
+ void stringChanged();
+ void objectChanged();
+ void anotherBasicSignal();
+ void thirdBasicSignal();
+
+public slots:
+ void deleteMe() { delete this; }
+ void methodNoArgs() { m_methodCalled = true; }
+ void method(int a) { if(a == 163) m_methodIntCalled = true; }
+ void setString(const QString &s) { m_string = s; }
+
+private:
+ friend class tst_qmlecmascript;
+ bool m_methodCalled;
+ bool m_methodIntCalled;
+
+ QObject *m_object;
+ QString m_string;
+ QmlConcreteList<QObject *> m_objectQmlList;
+ QList<QObject *> m_objectQList;
+ int m_value;
+ int m_resetProperty;
+};
+
+QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(MyQmlObject);
+
+class MyQmlContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<MyQmlObject*>* children READ children CONSTANT)
+public:
+ MyQmlContainer() {}
+
+ QList<MyQmlObject*> *children() { return &m_children; }
+
+private:
+ QList<MyQmlObject*> m_children;
+};
+
+QML_DECLARE_TYPE(MyQmlContainer);
+
+class MyExpression : public QmlExpression
+{
+public:
+ MyExpression(QmlContext *ctxt, const QString &expr)
+ : QmlExpression(ctxt, expr, 0), changed(false)
+ {
+ }
+
+ void emitValueChanged() {
+ changed = true;
+ QmlExpression::emitValueChanged();
+ }
+ bool changed;
+};
+
+
+class MyDefaultObject1 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int horseLegs READ horseLegs CONSTANT);
+ Q_PROPERTY(int antLegs READ antLegs CONSTANT);
+public:
+ int horseLegs() const { return 4; }
+ int antLegs() const { return 6; }
+};
+
+class MyDefaultObject2 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int antLegs READ antLegs CONSTANT);
+ Q_PROPERTY(int emuLegs READ emuLegs CONSTANT);
+public:
+ int antLegs() const { return 5; } // Had an accident
+ int emuLegs() const { return 2; }
+};
+
+class MyDefaultObject3 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int antLegs READ antLegs CONSTANT);
+ Q_PROPERTY(int humanLegs READ humanLegs CONSTANT);
+public:
+ int antLegs() const { return 7; } // Mutant
+ int humanLegs() const { return 2; }
+ int millipedeLegs() const { return 1000; }
+};
+
+class MyDeferredObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
+ Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty);
+ Q_PROPERTY(QObject *objectProperty2 READ objectProperty2 WRITE setObjectProperty2);
+ Q_CLASSINFO("DeferredPropertyNames", "value,objectProperty,objectProperty2");
+
+public:
+ MyDeferredObject() : m_value(0), m_object(0), m_object2(0) {}
+
+ int value() const { return m_value; }
+ void setValue(int v) { m_value = v; emit valueChanged(); }
+
+ QObject *objectProperty() const { return m_object; }
+ void setObjectProperty(QObject *obj) { m_object = obj; }
+
+ QObject *objectProperty2() const { return m_object2; }
+ void setObjectProperty2(QObject *obj) { m_object2 = obj; }
+
+signals:
+ void valueChanged();
+
+private:
+ int m_value;
+ QObject *m_object;
+ QObject *m_object2;
+};
+QML_DECLARE_TYPE(MyDeferredObject);
+
+class MyBaseExtendedObject : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(int baseProperty READ baseProperty WRITE setBaseProperty);
+public:
+ MyBaseExtendedObject() : m_value(0) {}
+
+ int baseProperty() const { return m_value; }
+ void setBaseProperty(int v) { m_value = v; }
+
+private:
+ int m_value;
+};
+QML_DECLARE_TYPE(MyBaseExtendedObject);
+
+class MyExtendedObject : public MyBaseExtendedObject
+{
+Q_OBJECT
+Q_PROPERTY(int coreProperty READ coreProperty WRITE setCoreProperty);
+public:
+ MyExtendedObject() : m_value(0) {}
+
+ int coreProperty() const { return m_value; }
+ void setCoreProperty(int v) { m_value = v; }
+
+private:
+ int m_value;
+};
+QML_DECLARE_TYPE(MyExtendedObject);
+
+class MyTypeObject : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(MyEnum)
+ Q_FLAGS(MyFlags)
+
+ Q_PROPERTY(QString id READ id WRITE setId);
+ Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty);
+ Q_PROPERTY(QmlComponent *componentProperty READ componentProperty WRITE setComponentProperty);
+ Q_PROPERTY(MyFlags flagProperty READ flagProperty WRITE setFlagProperty);
+ Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty);
+ Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty);
+ Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty);
+ Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty);
+ Q_PROPERTY(qreal realProperty READ realProperty WRITE setRealProperty);
+ Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty);
+ Q_PROPERTY(float floatProperty READ floatProperty WRITE setFloatProperty);
+ Q_PROPERTY(QColor colorProperty READ colorProperty WRITE setColorProperty);
+ Q_PROPERTY(QDate dateProperty READ dateProperty WRITE setDateProperty);
+ Q_PROPERTY(QTime timeProperty READ timeProperty WRITE setTimeProperty);
+ Q_PROPERTY(QDateTime dateTimeProperty READ dateTimeProperty WRITE setDateTimeProperty);
+ Q_PROPERTY(QPoint pointProperty READ pointProperty WRITE setPointProperty);
+ Q_PROPERTY(QPointF pointFProperty READ pointFProperty WRITE setPointFProperty);
+ Q_PROPERTY(QSize sizeProperty READ sizeProperty WRITE setSizeProperty);
+ Q_PROPERTY(QSizeF sizeFProperty READ sizeFProperty WRITE setSizeFProperty);
+ Q_PROPERTY(QRect rectProperty READ rectProperty WRITE setRectProperty NOTIFY rectPropertyChanged);
+ Q_PROPERTY(QRect rectProperty2 READ rectProperty2 WRITE setRectProperty2);
+ Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty);
+ Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty);
+ Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty);
+ Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty);
+ Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty);
+
+ Q_PROPERTY(QmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty);
+
+public:
+ MyTypeObject()
+ : objectPropertyValue(0), componentPropertyValue(0) {}
+
+ QString idValue;
+ QString id() const {
+ return idValue;
+ }
+ void setId(const QString &v) {
+ idValue = v;
+ }
+
+ QObject *objectPropertyValue;
+ QObject *objectProperty() const {
+ return objectPropertyValue;
+ }
+ void setObjectProperty(QObject *v) {
+ objectPropertyValue = v;
+ }
+
+ QmlComponent *componentPropertyValue;
+ QmlComponent *componentProperty() const {
+ return componentPropertyValue;
+ }
+ void setComponentProperty(QmlComponent *v) {
+ componentPropertyValue = v;
+ }
+
+ enum MyFlag { FlagVal1 = 0x01, FlagVal2 = 0x02, FlagVal3 = 0x04 };
+ Q_DECLARE_FLAGS(MyFlags, MyFlag)
+ MyFlags flagPropertyValue;
+ MyFlags flagProperty() const {
+ return flagPropertyValue;
+ }
+ void setFlagProperty(MyFlags v) {
+ flagPropertyValue = v;
+ }
+
+ enum MyEnum { EnumVal1, EnumVal2 };
+ MyEnum enumPropertyValue;
+ MyEnum enumProperty() const {
+ return enumPropertyValue;
+ }
+ void setEnumProperty(MyEnum v) {
+ enumPropertyValue = v;
+ }
+
+ QString stringPropertyValue;
+ QString stringProperty() const {
+ return stringPropertyValue;
+ }
+ void setStringProperty(const QString &v) {
+ stringPropertyValue = v;
+ }
+
+ uint uintPropertyValue;
+ uint uintProperty() const {
+ return uintPropertyValue;
+ }
+ void setUintProperty(const uint &v) {
+ uintPropertyValue = v;
+ }
+
+ int intPropertyValue;
+ int intProperty() const {
+ return intPropertyValue;
+ }
+ void setIntProperty(const int &v) {
+ intPropertyValue = v;
+ }
+
+ qreal realPropertyValue;
+ qreal realProperty() const {
+ return realPropertyValue;
+ }
+ void setRealProperty(const qreal &v) {
+ realPropertyValue = v;
+ }
+
+ double doublePropertyValue;
+ double doubleProperty() const {
+ return doublePropertyValue;
+ }
+ void setDoubleProperty(const double &v) {
+ doublePropertyValue = v;
+ }
+
+ float floatPropertyValue;
+ float floatProperty() const {
+ return floatPropertyValue;
+ }
+ void setFloatProperty(const float &v) {
+ floatPropertyValue = v;
+ }
+
+ QColor colorPropertyValue;
+ QColor colorProperty() const {
+ return colorPropertyValue;
+ }
+ void setColorProperty(const QColor &v) {
+ colorPropertyValue = v;
+ }
+
+ QDate datePropertyValue;
+ QDate dateProperty() const {
+ return datePropertyValue;
+ }
+ void setDateProperty(const QDate &v) {
+ datePropertyValue = v;
+ }
+
+ QTime timePropertyValue;
+ QTime timeProperty() const {
+ return timePropertyValue;
+ }
+ void setTimeProperty(const QTime &v) {
+ timePropertyValue = v;
+ }
+
+ QDateTime dateTimePropertyValue;
+ QDateTime dateTimeProperty() const {
+ return dateTimePropertyValue;
+ }
+ void setDateTimeProperty(const QDateTime &v) {
+ dateTimePropertyValue = v;
+ }
+
+ QPoint pointPropertyValue;
+ QPoint pointProperty() const {
+ return pointPropertyValue;
+ }
+ void setPointProperty(const QPoint &v) {
+ pointPropertyValue = v;
+ }
+
+ QPointF pointFPropertyValue;
+ QPointF pointFProperty() const {
+ return pointFPropertyValue;
+ }
+ void setPointFProperty(const QPointF &v) {
+ pointFPropertyValue = v;
+ }
+
+ QSize sizePropertyValue;
+ QSize sizeProperty() const {
+ return sizePropertyValue;
+ }
+ void setSizeProperty(const QSize &v) {
+ sizePropertyValue = v;
+ }
+
+ QSizeF sizeFPropertyValue;
+ QSizeF sizeFProperty() const {
+ return sizeFPropertyValue;
+ }
+ void setSizeFProperty(const QSizeF &v) {
+ sizeFPropertyValue = v;
+ }
+
+ QRect rectPropertyValue;
+ QRect rectProperty() const {
+ return rectPropertyValue;
+ }
+ void setRectProperty(const QRect &v) {
+ rectPropertyValue = v;
+ emit rectPropertyChanged();
+ }
+
+ QRect rectPropertyValue2;
+ QRect rectProperty2() const {
+ return rectPropertyValue2;
+ }
+ void setRectProperty2(const QRect &v) {
+ rectPropertyValue2 = v;
+ }
+
+ QRectF rectFPropertyValue;
+ QRectF rectFProperty() const {
+ return rectFPropertyValue;
+ }
+ void setRectFProperty(const QRectF &v) {
+ rectFPropertyValue = v;
+ }
+
+ bool boolPropertyValue;
+ bool boolProperty() const {
+ return boolPropertyValue;
+ }
+ void setBoolProperty(const bool &v) {
+ boolPropertyValue = v;
+ }
+
+ QVariant variantPropertyValue;
+ QVariant variantProperty() const {
+ return variantPropertyValue;
+ }
+ void setVariantProperty(const QVariant &v) {
+ variantPropertyValue = v;
+ }
+
+ QVector3D vectorPropertyValue;
+ QVector3D vectorProperty() const {
+ return vectorPropertyValue;
+ }
+ void setVectorProperty(const QVector3D &v) {
+ vectorPropertyValue = v;
+ }
+
+ QUrl urlPropertyValue;
+ QUrl urlProperty() const {
+ return urlPropertyValue;
+ }
+ void setUrlProperty(const QUrl &v) {
+ urlPropertyValue = v;
+ }
+
+ QmlScriptString scriptPropertyValue;
+ QmlScriptString scriptProperty() const {
+ return scriptPropertyValue;
+ }
+ void setScriptProperty(const QmlScriptString &v) {
+ scriptPropertyValue = v;
+ }
+
+ void doAction() { emit action(); }
+signals:
+ void action();
+ void rectPropertyChanged();
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
+QML_DECLARE_TYPE(MyTypeObject);
+
+Q_DECLARE_METATYPE(QScriptValue);
+class MyInvokableObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyInvokableObject() { reset(); }
+
+ int invoked() const { return m_invoked; }
+ bool error() const { return m_invokedError; }
+ const QVariantList &actuals() const { return m_actuals; }
+ void reset() { m_invoked = -1; m_invokedError = false; m_actuals.clear(); }
+
+ Q_INVOKABLE QPointF method_get_QPointF() { return QPointF(99.3, -10.2); }
+ Q_INVOKABLE QPoint method_get_QPoint() { return QPoint(9, 12); }
+
+ Q_INVOKABLE void method_NoArgs() { invoke(0); }
+ Q_INVOKABLE int method_NoArgs_int() { invoke(1); return 6; }
+ Q_INVOKABLE qreal method_NoArgs_real() { invoke(2); return 19.7; }
+ Q_INVOKABLE QPointF method_NoArgs_QPointF() { invoke(3); return QPointF(123, 4.5); }
+ Q_INVOKABLE QObject *method_NoArgs_QObject() { invoke(4); return this; }
+ Q_INVOKABLE MyInvokableObject *method_NoArgs_unknown() { invoke(5); return this; }
+ Q_INVOKABLE QScriptValue method_NoArgs_QScriptValue() { invoke(6); return QScriptValue("Hello world"); }
+ Q_INVOKABLE QVariant method_NoArgs_QVariant() { invoke(7); return QVariant("QML rocks"); }
+
+ Q_INVOKABLE void method_int(int a) { invoke(8); m_actuals << a; }
+ Q_INVOKABLE void method_intint(int a, int b) { invoke(9); m_actuals << a << b; }
+ Q_INVOKABLE void method_real(qreal a) { invoke(10); m_actuals << a; }
+ Q_INVOKABLE void method_QString(QString a) { invoke(11); m_actuals << a; }
+ Q_INVOKABLE void method_QPointF(QPointF a) { invoke(12); m_actuals << a; }
+ Q_INVOKABLE void method_QObject(QObject *a) { invoke(13); m_actuals << qVariantFromValue(a); }
+ Q_INVOKABLE void method_QScriptValue(QScriptValue a) { invoke(14); m_actuals << qVariantFromValue(a); }
+ Q_INVOKABLE void method_intQScriptValue(int a, QScriptValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); }
+
+ Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; }
+ Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; }
+
+private:
+ void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;}
+ int m_invoked;
+ bool m_invokedError;
+ QVariantList m_actuals;
+};
+
+#endif // TESTTYPES_H
+
diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
new file mode 100644
index 0000000..e5472bb
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
@@ -0,0 +1,1663 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/private/qguard_p.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qnumeric.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlglobalscriptclass_p.h>
+#include "testtypes.h"
+
+/*
+This test covers evaluation of ECMAScript expressions and bindings from within
+QML. This does not include static QML language issues.
+
+Static QML language issues are covered in qmllanguage
+*/
+inline QUrl TEST_FILE(const QString &filename)
+{
+ QFileInfo fileInfo(__FILE__);
+ return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
+}
+
+inline QUrl TEST_FILE(const char *filename)
+{
+ return TEST_FILE(QLatin1String(filename));
+}
+
+class tst_qmlecmascript : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlecmascript() {}
+
+private slots:
+ void assignBasicTypes();
+ void idShortcutInvalidates();
+ void boolPropertiesEvaluateAsBool();
+ void methods();
+ void signalAssignment();
+ void bindingLoop();
+ void basicExpressions();
+ void basicExpressions_data();
+ void arrayExpressions();
+ void contextPropertiesTriggerReeval();
+ void objectPropertiesTriggerReeval();
+ void deferredProperties();
+ void extensionObjects();
+ void attachedProperties();
+ void enums();
+ void valueTypeFunctions();
+ void constantsOverrideBindings();
+ void outerBindingOverridesInnerBinding();
+ void aliasPropertyAndBinding();
+ void nonExistantAttachedObject();
+ void scope();
+ void signalParameterTypes();
+ void objectsCompareAsEqual();
+ void scriptAccess();
+ void dynamicCreation_data();
+ void dynamicCreation();
+ void dynamicDestruction();
+ void objectToString();
+ void selfDeletingBinding();
+ void extendedObjectPropertyLookup();
+ void scriptErrors();
+ void signalTriggeredBindings();
+ void listProperties();
+ void exceptionClearsOnReeval();
+ void exceptionSlotProducesWarning();
+ void exceptionBindingProducesWarning();
+ void transientErrors();
+ void shutdownErrors();
+ void externalScript();
+ void compositePropertyType();
+ void jsObject();
+ void undefinedResetsProperty();
+ void listToVariant();
+ void multiEngineObject();
+ void deletedObject();
+
+ void bug1();
+
+ void callQtInvokables();
+private:
+ QmlEngine engine;
+};
+
+void tst_qmlecmascript::assignBasicTypes()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
+ QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
+ QCOMPARE(object->stringProperty(), QString("Hello World!"));
+ QCOMPARE(object->uintProperty(), uint(10));
+ QCOMPARE(object->intProperty(), -19);
+ QCOMPARE((float)object->realProperty(), float(23.2));
+ QCOMPARE((float)object->doubleProperty(), float(-19.7));
+ QCOMPARE((float)object->floatProperty(), float(8.5));
+ QCOMPARE(object->colorProperty(), QColor("red"));
+ QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
+ QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
+ QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
+ QCOMPARE(object->pointProperty(), QPoint(99,13));
+ QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
+ QCOMPARE(object->sizeProperty(), QSize(99, 13));
+ QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
+ QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
+ QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
+ QCOMPARE(object->boolProperty(), true);
+ QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
+ QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
+ QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
+ delete object;
+ }
+ {
+ QmlComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
+ QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
+ QCOMPARE(object->stringProperty(), QString("Hello World!"));
+ QCOMPARE(object->uintProperty(), uint(10));
+ QCOMPARE(object->intProperty(), -19);
+ QCOMPARE((float)object->realProperty(), float(23.2));
+ QCOMPARE((float)object->doubleProperty(), float(-19.7));
+ QCOMPARE((float)object->floatProperty(), float(8.5));
+ QCOMPARE(object->colorProperty(), QColor("red"));
+ QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
+ QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
+ QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
+ QCOMPARE(object->pointProperty(), QPoint(99,13));
+ QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
+ QCOMPARE(object->sizeProperty(), QSize(99, 13));
+ QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
+ QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
+ QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
+ QCOMPARE(object->boolProperty(), true);
+ QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
+ QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
+ QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
+ delete object;
+ }
+}
+
+void tst_qmlecmascript::idShortcutInvalidates()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->objectProperty() != 0);
+ delete object->objectProperty();
+ QVERIFY(object->objectProperty() == 0);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->objectProperty() != 0);
+ delete object->objectProperty();
+ QVERIFY(object->objectProperty() == 0);
+ }
+}
+
+void tst_qmlecmascript::boolPropertiesEvaluateAsBool()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ }
+ {
+ QmlComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ }
+}
+
+void tst_qmlecmascript::signalAssignment()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->string(), QString());
+ emit object->basicSignal();
+ QCOMPARE(object->string(), QString("pass"));
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->string(), QString());
+ emit object->argumentSignal(19, "Hello world!", 10.3);
+ QCOMPARE(object->string(), QString("pass 19 Hello world! 10.3"));
+ }
+}
+
+void tst_qmlecmascript::methods()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("methods.1.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), false);
+ emit object->basicSignal();
+ QCOMPARE(object->methodCalled(), true);
+ QCOMPARE(object->methodIntCalled(), false);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("methods.2.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), false);
+ emit object->basicSignal();
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), true);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("methods.3.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("test").toInt(), 19);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("methods.4.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("test").toInt(), 19);
+ QCOMPARE(object->property("test2").toInt(), 17);
+ QCOMPARE(object->property("test3").toInt(), 16);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("methods.5.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("test").toInt(), 9);
+ }
+}
+
+void tst_qmlecmascript::bindingLoop()
+{
+ QmlComponent component(&engine, TEST_FILE("bindingLoop.qml"));
+ QString warning = "QML MyQmlObject (" + component.url().toString() + ":9:9) Binding loop detected for property \"stringProperty\"";
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+void tst_qmlecmascript::basicExpressions_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addColumn<QVariant>("result");
+ QTest::addColumn<bool>("nest");
+
+ QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
+ QTest::newRow("Context property") << "a" << QVariant(1944) << false;
+ QTest::newRow("Context property") << "a" << QVariant(1944) << true;
+ QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
+ QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
+ QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
+ QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
+ QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
+ QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
+ QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
+ QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
+ QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
+ QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
+ QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
+ QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
+ QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
+ QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
+ QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
+ QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
+}
+
+void tst_qmlecmascript::basicExpressions()
+{
+ QFETCH(QString, expression);
+ QFETCH(QVariant, result);
+ QFETCH(bool, nest);
+
+ MyQmlObject object1;
+ MyQmlObject object2;
+ MyQmlObject object3;
+ MyDefaultObject1 default1;
+ MyDefaultObject2 default2;
+ MyDefaultObject3 default3;
+ object1.setStringProperty("Object1");
+ object2.setStringProperty("Object2");
+ object3.setStringProperty("Object3");
+
+ QmlContext context(engine.rootContext());
+ QmlContext nestedContext(&context);
+
+ context.addDefaultObject(&default1);
+ context.addDefaultObject(&default2);
+ context.setContextProperty("a", QVariant(1944));
+ context.setContextProperty("b", QVariant("Milk"));
+ context.setContextProperty("object", &object1);
+ context.setContextProperty("objectOverride", &object2);
+ nestedContext.addDefaultObject(&default3);
+ nestedContext.setContextProperty("b", QVariant("Cow"));
+ nestedContext.setContextProperty("objectOverride", &object3);
+ nestedContext.setContextProperty("millipedeLegs", QVariant(100));
+
+ MyExpression expr(nest?&nestedContext:&context, expression);
+ QCOMPARE(expr.value(), result);
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void tst_qmlecmascript::arrayExpressions()
+{
+ QObject obj1;
+ QObject obj2;
+ QObject obj3;
+
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("a", &obj1);
+ context.setContextProperty("b", &obj2);
+ context.setContextProperty("c", &obj3);
+
+ MyExpression expr(&context, "[a, b, c, 10]");
+ QVariant result = expr.value();
+ QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
+ QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
+ QCOMPARE(list.count(), 4);
+ QCOMPARE(list.at(0), &obj1);
+ QCOMPARE(list.at(1), &obj2);
+ QCOMPARE(list.at(2), &obj3);
+ QCOMPARE(list.at(3), (QObject *)0);
+}
+
+// Tests that modifying a context property will reevaluate expressions
+void tst_qmlecmascript::contextPropertiesTriggerReeval()
+{
+ QmlContext context(engine.rootContext());
+ MyQmlObject object1;
+ MyQmlObject object2;
+ MyQmlObject *object3 = new MyQmlObject;
+
+ object1.setStringProperty("Hello");
+ object2.setStringProperty("World");
+
+ context.setContextProperty("testProp", QVariant(1));
+ context.setContextProperty("testObj", &object1);
+ context.setContextProperty("testObj2", object3);
+
+ {
+ MyExpression expr(&context, "testProp + 1");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant(2));
+
+ context.setContextProperty("testProp", QVariant(2));
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant(3));
+ }
+
+ {
+ MyExpression expr(&context, "testProp + testProp + testProp");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant(6));
+
+ context.setContextProperty("testProp", QVariant(4));
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant(12));
+ }
+
+ {
+ MyExpression expr(&context, "testObj.stringProperty");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant("Hello"));
+
+ context.setContextProperty("testObj", &object2);
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant("World"));
+ }
+
+ {
+ MyExpression expr(&context, "testObj.stringProperty /**/");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant("World"));
+
+ context.setContextProperty("testObj", &object1);
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant("Hello"));
+ }
+
+ {
+ MyExpression expr(&context, "testObj2");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant::fromValue((QObject *)object3));
+ }
+
+}
+
+void tst_qmlecmascript::objectPropertiesTriggerReeval()
+{
+ QmlContext context(engine.rootContext());
+ MyQmlObject object1;
+ MyQmlObject object2;
+ MyQmlObject object3;
+ context.setContextProperty("testObj", &object1);
+
+ object1.setStringProperty(QLatin1String("Hello"));
+ object2.setStringProperty(QLatin1String("Dog"));
+ object3.setStringProperty(QLatin1String("Cat"));
+
+ {
+ MyExpression expr(&context, "testObj.stringProperty");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant("Hello"));
+
+ object1.setStringProperty(QLatin1String("World"));
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant("World"));
+ }
+
+ {
+ MyExpression expr(&context, "testObj.objectProperty.stringProperty");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant());
+
+ object1.setObjectProperty(&object2);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Dog"));
+
+ object1.setObjectProperty(&object3);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Cat"));
+
+ object1.setObjectProperty(0);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant());
+
+ object1.setObjectProperty(&object3);
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Cat"));
+
+ object3.setStringProperty("Donkey");
+ QCOMPARE(expr.changed, true);
+ expr.changed = false;
+ QCOMPARE(expr.value(), QVariant("Donkey"));
+ }
+}
+
+void tst_qmlecmascript::deferredProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("deferredProperties.qml"));
+ MyDeferredObject *object =
+ qobject_cast<MyDeferredObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->value(), 0);
+ QVERIFY(object->objectProperty() == 0);
+ QVERIFY(object->objectProperty2() != 0);
+ qmlExecuteDeferred(object);
+ QCOMPARE(object->value(), 10);
+ QVERIFY(object->objectProperty() != 0);
+ MyQmlObject *qmlObject =
+ qobject_cast<MyQmlObject *>(object->objectProperty());
+ QVERIFY(qmlObject != 0);
+ QCOMPARE(qmlObject->value(), 10);
+ object->setValue(19);
+ QCOMPARE(qmlObject->value(), 19);
+}
+
+void tst_qmlecmascript::extensionObjects()
+{
+ QmlComponent component(&engine, TEST_FILE("extensionObjects.qml"));
+ MyExtendedObject *object =
+ qobject_cast<MyExtendedObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->baseProperty(), 13);
+ QCOMPARE(object->coreProperty(), 9);
+
+ object->setProperty("extendedProperty", QVariant(11));
+ object->setProperty("baseExtendedProperty", QVariant(92));
+ QCOMPARE(object->coreProperty(), 11);
+ QCOMPARE(object->baseProperty(), 92);
+}
+
+void tst_qmlecmascript::attachedProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("attachedProperty.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("a").toInt(), 19);
+ QCOMPARE(object->property("b").toInt(), 19);
+ QCOMPARE(object->property("c").toInt(), 19);
+ QCOMPARE(object->property("d").toInt(), 19);
+
+ // ### Need to test attached property assignment
+}
+
+void tst_qmlecmascript::enums()
+{
+ // Existant enums
+ {
+ QmlComponent component(&engine, TEST_FILE("enums.1.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("a").toInt(), 0);
+ QCOMPARE(object->property("b").toInt(), 1);
+ QCOMPARE(object->property("c").toInt(), 2);
+ QCOMPARE(object->property("d").toInt(), 3);
+ QCOMPARE(object->property("e").toInt(), 0);
+ QCOMPARE(object->property("f").toInt(), 1);
+ QCOMPARE(object->property("g").toInt(), 2);
+ QCOMPARE(object->property("h").toInt(), 3);
+ QCOMPARE(object->property("i").toInt(), 19);
+ QCOMPARE(object->property("j").toInt(), 19);
+ }
+ // Non-existant enums
+ {
+ QmlComponent component(&engine, TEST_FILE("enums.2.qml"));
+
+ QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int";
+ QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("a").toInt(), 0);
+ QCOMPARE(object->property("b").toInt(), 0);
+ }
+}
+
+void tst_qmlecmascript::valueTypeFunctions()
+{
+ QmlComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
+ MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
+ QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
+}
+
+/*
+Tests that writing a constant to a property with a binding on it disables the
+binding.
+*/
+void tst_qmlecmascript::constantsOverrideBindings()
+{
+ // From ECMAScript
+ {
+ QmlComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("c2").toInt(), 0);
+ object->setProperty("c1", QVariant(9));
+ QCOMPARE(object->property("c2").toInt(), 9);
+
+ emit object->basicSignal();
+
+ QCOMPARE(object->property("c2").toInt(), 13);
+ object->setProperty("c1", QVariant(8));
+ QCOMPARE(object->property("c2").toInt(), 13);
+ }
+
+ // During construction
+ {
+ QmlComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("c1").toInt(), 0);
+ QCOMPARE(object->property("c2").toInt(), 10);
+ object->setProperty("c1", QVariant(9));
+ QCOMPARE(object->property("c1").toInt(), 9);
+ QCOMPARE(object->property("c2").toInt(), 10);
+ }
+
+#if 0
+ // From C++
+ {
+ QmlComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("c2").toInt(), 0);
+ object->setProperty("c1", QVariant(9));
+ QCOMPARE(object->property("c2").toInt(), 9);
+
+ object->setProperty("c2", QVariant(13));
+ QCOMPARE(object->property("c2").toInt(), 13);
+ object->setProperty("c1", QVariant(7));
+ QCOMPARE(object->property("c1").toInt(), 7);
+ QCOMPARE(object->property("c2").toInt(), 13);
+ }
+#endif
+}
+
+/*
+Tests that assigning a binding to a property that already has a binding causes
+the original binding to be disabled.
+*/
+void tst_qmlecmascript::outerBindingOverridesInnerBinding()
+{
+ QmlComponent component(&engine,
+ TEST_FILE("outerBindingOverridesInnerBinding.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("c1").toInt(), 0);
+ QCOMPARE(object->property("c2").toInt(), 0);
+ QCOMPARE(object->property("c3").toInt(), 0);
+
+ object->setProperty("c1", QVariant(9));
+ QCOMPARE(object->property("c1").toInt(), 9);
+ QCOMPARE(object->property("c2").toInt(), 0);
+ QCOMPARE(object->property("c3").toInt(), 0);
+
+ object->setProperty("c3", QVariant(8));
+ QCOMPARE(object->property("c1").toInt(), 9);
+ QCOMPARE(object->property("c2").toInt(), 8);
+ QCOMPARE(object->property("c3").toInt(), 8);
+}
+
+/*
+Access a non-existant attached object.
+
+Tests for a regression where this used to crash.
+*/
+void tst_qmlecmascript::nonExistantAttachedObject()
+{
+ QmlComponent component(&engine, TEST_FILE("nonExistantAttachedObject.qml"));
+
+ QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+void tst_qmlecmascript::scope()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("scope.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), 1);
+ QCOMPARE(object->property("test2").toInt(), 2);
+ QCOMPARE(object->property("test3").toString(), QString("1Test"));
+ QCOMPARE(object->property("test4").toString(), QString("2Test"));
+ QCOMPARE(object->property("test5").toInt(), 1);
+ QCOMPARE(object->property("test6").toInt(), 1);
+ QCOMPARE(object->property("test7").toInt(), 2);
+ QCOMPARE(object->property("test8").toInt(), 2);
+ QCOMPARE(object->property("test9").toInt(), 1);
+ QCOMPARE(object->property("test10").toInt(), 3);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("scope.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), 19);
+ QCOMPARE(object->property("test2").toInt(), 19);
+ QCOMPARE(object->property("test3").toInt(), 11);
+ QCOMPARE(object->property("test4").toInt(), 11);
+ QCOMPARE(object->property("test5").toInt(), 24);
+ QCOMPARE(object->property("test6").toInt(), 24);
+ }
+}
+
+/*
+Tests that "any" type passes through a synthesized signal parameter. This
+is essentially a test of QmlMetaType::copy()
+*/
+void tst_qmlecmascript::signalParameterTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+
+ emit object->basicSignal();
+
+ QCOMPARE(object->property("intProperty").toInt(), 10);
+ QCOMPARE(object->property("realProperty").toReal(), 19.2);
+ QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
+ QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
+}
+
+/*
+Test that two JS objects for the same QObject compare as equal.
+*/
+void tst_qmlecmascript::objectsCompareAsEqual()
+{
+ QmlComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toBool(), true);
+ QCOMPARE(object->property("test2").toBool(), true);
+ QCOMPARE(object->property("test3").toBool(), true);
+ QCOMPARE(object->property("test4").toBool(), true);
+ QCOMPARE(object->property("test5").toBool(), true);
+}
+
+/*
+Confirm bindings and alias properties can coexist.
+
+Tests for a regression where the binding would not reevaluate.
+*/
+void tst_qmlecmascript::aliasPropertyAndBinding()
+{
+ QmlComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("c2").toInt(), 3);
+ QCOMPARE(object->property("c3").toInt(), 3);
+
+ object->setProperty("c2", QVariant(19));
+
+ QCOMPARE(object->property("c2").toInt(), 19);
+ QCOMPARE(object->property("c3").toInt(), 19);
+}
+
+/*
+Tests that only methods of Script {} blocks are exposed.
+*/
+void tst_qmlecmascript::scriptAccess()
+{
+ QmlComponent component(&engine, TEST_FILE("scriptAccess.qml"));
+
+ QString warning = component.url().toString() + ":16: Unable to assign [undefined] to int";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), 10);
+ QCOMPARE(object->property("test2").toInt(), 19);
+ QCOMPARE(object->property("test3").toInt(), 0);
+}
+
+void tst_qmlecmascript::dynamicCreation_data()
+{
+ QTest::addColumn<QString>("method");
+ QTest::addColumn<QString>("createdName");
+
+ QTest::newRow("One") << "createOne" << "objectOne";
+ QTest::newRow("Two") << "createTwo" << "objectTwo";
+ QTest::newRow("Three") << "createThree" << "objectThree";
+}
+
+/*
+Test using createQmlObject to dynamically generate an item
+Also using createComponent is tested.
+*/
+void tst_qmlecmascript::dynamicCreation()
+{
+ QFETCH(QString, method);
+ QFETCH(QString, createdName);
+
+ QmlComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+
+ QMetaObject::invokeMethod(object, method.toUtf8());
+ QObject *created = object->objectProperty();
+ QVERIFY(created);
+ QCOMPARE(created->objectName(), createdName);
+}
+
+/*
+ Tests the destroy function
+*/
+void tst_qmlecmascript::dynamicDestruction()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
+ QGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QGuard<QObject> createdQmlObject = 0;
+
+ QMetaObject::invokeMethod(object, "create");
+ createdQmlObject = object->objectProperty();
+ QVERIFY(createdQmlObject);
+ QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
+
+ QMetaObject::invokeMethod(object, "killOther");
+ QVERIFY(createdQmlObject);
+ QTest::qWait(0);
+ QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ QVERIFY(createdQmlObject);
+ for (int ii = 0; createdQmlObject && ii < 10; ++ii) {
+ if (createdQmlObject) {
+ QTest::qWait(100);
+ QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ }
+ }
+ QVERIFY(!createdQmlObject);
+
+ QMetaObject::invokeMethod(object, "killMe");
+ QVERIFY(object);
+ QTest::qWait(0);
+ QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ QVERIFY(!object);
+}
+
+/*
+ tests that id.toString() works
+*/
+void tst_qmlecmascript::objectToString()
+{
+ QmlComponent component(&engine, TEST_FILE("qmlToString.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QMetaObject::invokeMethod(object, "testToString");
+ QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
+ QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
+}
+
+/*
+Tests bindings that indirectly cause their own deletion work.
+
+This test is best run under valgrind to ensure no invalid memory access occur.
+*/
+void tst_qmlecmascript::selfDeletingBinding()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ object->setProperty("triggerDelete", true);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ object->setProperty("triggerDelete", true);
+ }
+}
+
+/*
+Test that extended object properties can be accessed.
+
+This test a regression where this used to crash. The issue was specificially
+for extended objects that did not include a synthesized meta object (so non-root
+and no synthesiszed properties).
+*/
+void tst_qmlecmascript::extendedObjectPropertyLookup()
+{
+ QmlComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+/*
+Test file/lineNumbers for binding/Script errors.
+*/
+void tst_qmlecmascript::scriptErrors()
+{
+ QmlComponent component(&engine, TEST_FILE("scriptErrors.qml"));
+ QString url = component.url().toString();
+
+ QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
+ QString warning2 = url + ":7: TypeError: Result of expression 'a' [undefined] is not an object.";
+ QString warning3 = url + ":5: Error: Invalid write to global property \"a\"";
+ QString warning4 = url + ":12: TypeError: Result of expression 'a' [undefined] is not an object.";
+ QString warning5 = url + ":10: TypeError: Result of expression 'a' [undefined] is not an object.";
+ QString warning6 = url + ":9: Unable to assign [undefined] to int";
+ QString warning7 = url + ":14: Error: Cannot assign to read-only property \"trueProperty\"";
+ QString warning8 = url + ":15: Error: Cannot assign to non-existant property \"fakeProperty\"";
+
+ QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
+ emit object->basicSignal();
+
+ QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
+ emit object->anotherBasicSignal();
+
+ QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
+ emit object->thirdBasicSignal();
+}
+
+/*
+Test bindings still work when the reeval is triggered from within
+a signal script.
+*/
+void tst_qmlecmascript::signalTriggeredBindings()
+{
+ QmlComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("base").toReal(), 50.);
+ QCOMPARE(object->property("test1").toReal(), 50.);
+ QCOMPARE(object->property("test2").toReal(), 50.);
+
+ object->basicSignal();
+
+ QCOMPARE(object->property("base").toReal(), 200.);
+ QCOMPARE(object->property("test1").toReal(), 200.);
+ QCOMPARE(object->property("test2").toReal(), 200.);
+
+ object->argumentSignal(10, QString(), 10);
+
+ QCOMPARE(object->property("base").toReal(), 400.);
+ QCOMPARE(object->property("test1").toReal(), 400.);
+ QCOMPARE(object->property("test2").toReal(), 400.);
+}
+
+/*
+Test that list properties can be iterated from ECMAScript
+*/
+void tst_qmlecmascript::listProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("listProperties.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), 21);
+ QCOMPARE(object->property("test2").toInt(), 2);
+ QCOMPARE(object->property("test3").toInt(), 50);
+ QCOMPARE(object->property("test4").toInt(), 3);
+ QCOMPARE(object->property("test5").toBool(), true);
+ QCOMPARE(object->property("test6").toBool(), true);
+ QCOMPARE(object->property("test7").toBool(), true);
+ QCOMPARE(object->property("test8").toBool(), true);
+}
+
+void tst_qmlecmascript::exceptionClearsOnReeval()
+{
+ QmlComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
+ QString url = component.url().toString();
+
+ QString warning = url + ":4: TypeError: Result of expression 'objectProperty.objectProperty' [undefined] is not an object.";
+
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), false);
+
+ MyQmlObject object2;
+ MyQmlObject object3;
+ object2.setObjectProperty(&object3);
+ object->setObjectProperty(&object2);
+
+ QCOMPARE(object->property("test").toBool(), true);
+}
+
+void tst_qmlecmascript::exceptionSlotProducesWarning()
+{
+ QmlComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
+ QString url = component.url().toString();
+
+ QString warning = component.url().toString() + ":6: Error: JS exception";
+
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+}
+
+void tst_qmlecmascript::exceptionBindingProducesWarning()
+{
+ QmlComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
+ QString url = component.url().toString();
+
+ QString warning = component.url().toString() + ":5: Error: JS exception";
+
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+}
+
+static int transientErrorsMsgCount = 0;
+static void transientErrorsMsgHandler(QtMsgType, const char *)
+{
+ ++transientErrorsMsgCount;
+}
+
+// Check that transient binding errors are not displayed
+void tst_qmlecmascript::transientErrors()
+{
+ QmlComponent component(&engine, TEST_FILE("transientErrors.qml"));
+
+ transientErrorsMsgCount = 0;
+ QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ qInstallMsgHandler(old);
+
+ QCOMPARE(transientErrorsMsgCount, 0);
+}
+
+// Check that errors during shutdown are minimized
+void tst_qmlecmascript::shutdownErrors()
+{
+ QmlComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ transientErrorsMsgCount = 0;
+ QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
+
+ delete object;
+
+ qInstallMsgHandler(old);
+ QCOMPARE(transientErrorsMsgCount, 0);
+}
+
+// Check that Script::source property works as expected
+void tst_qmlecmascript::externalScript()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("externalScript.1.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toInt(), 92);
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("externalScript.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toInt(), 92);
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("externalScript.3.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toInt(), 92);
+ QCOMPARE(object->property("test2").toInt(), 92);
+ QCOMPARE(object->property("test3").toBool(), false);
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("externalScript.4.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toInt(), 92);
+ QCOMPARE(object->property("test2").toBool(), true);
+
+ delete object;
+ }
+}
+
+void tst_qmlecmascript::compositePropertyType()
+{
+ QmlComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
+ QTest::ignoreMessage(QtDebugMsg, "hello world");
+ QObject *object = qobject_cast<QObject *>(component.create());
+ delete object;
+}
+
+// QTBUG-5759
+void tst_qmlecmascript::jsObject()
+{
+ QmlComponent component(&engine, TEST_FILE("jsObject.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toInt(), 92);
+
+ delete object;
+}
+
+void tst_qmlecmascript::undefinedResetsProperty()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("resettableProperty").toInt(), 92);
+
+ object->setProperty("setUndefined", true);
+
+ QCOMPARE(object->property("resettableProperty").toInt(), 13);
+
+ object->setProperty("setUndefined", false);
+
+ QCOMPARE(object->property("resettableProperty").toInt(), 92);
+
+ delete object;
+ }
+ {
+ QmlComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("resettableProperty").toInt(), 19);
+
+ QMetaObject::invokeMethod(object, "doReset");
+
+ QCOMPARE(object->property("resettableProperty").toInt(), 13);
+
+ delete object;
+ }
+}
+
+// QTBUG-6781
+void tst_qmlecmascript::bug1()
+{
+ QmlComponent component(&engine, TEST_FILE("bug.1.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toInt(), 14);
+
+ object->setProperty("a", 11);
+
+ QCOMPARE(object->property("test").toInt(), 3);
+
+ object->setProperty("b", true);
+
+ QCOMPARE(object->property("test").toInt(), 9);
+
+ delete object;
+}
+
+void tst_qmlecmascript::callQtInvokables()
+{
+ MyInvokableObject o;
+
+ QmlEngine qmlengine;
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(&qmlengine);
+ QScriptEngine *engine = &ep->scriptEngine;
+ ep->globalClass->explicitSetProperty("object", ep->objectClass->newQObject(&o));
+
+ // Non-existant methods
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_nonexistant()").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_nonexistant(10, 11)").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ // Insufficient arguments
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ // Excessive arguments
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 9);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+ QCOMPARE(o.actuals().at(1), QVariant(11));
+
+ // Test return types
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 0);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.7)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 2);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ {
+ QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
+ QVERIFY(ret.isVariant());
+ QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 3);
+ QCOMPARE(o.actuals().count(), 0);
+ }
+
+ o.reset();
+ {
+ QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
+ QVERIFY(ret.isQObject());
+ QCOMPARE(ret.toQObject(), (QObject *)&o);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 4);
+ QCOMPARE(o.actuals().count(), 0);
+ }
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 5);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ {
+ QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString("Hello world"));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 6);
+ QCOMPARE(o.actuals().count(), 0);
+ }
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 7);
+ QCOMPARE(o.actuals().count(), 0);
+
+ // Test arg types
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 9);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(122));
+ QCOMPARE(o.actuals().at(1), QVariant(9));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94.3));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94.3));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant("19"));
+
+ o.reset();
+ {
+ QString expected = "MyInvokableObject(0x" + QString::number((intptr_t)&o, 16) + ")";
+ QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(expected));
+ }
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QString()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QString()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(4));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(8));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(3));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(44));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
+
+ // Test overloads - QML will always invoke the *last* method
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_overload(10)").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 17);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+ QCOMPARE(o.actuals().at(1), QVariant(11));
+}
+
+// QTBUG-5675
+void tst_qmlecmascript::listToVariant()
+{
+ QmlComponent component(&engine, TEST_FILE("listToVariant.qml"));
+
+ MyQmlContainer container;
+
+ QmlContext context(engine.rootContext());
+ context.addDefaultObject(&container);
+
+ QObject *object = component.create(&context);
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test"), QVariant::fromValue(container.children()));
+
+ delete object;
+}
+
+// QTBUG-7957
+void tst_qmlecmascript::multiEngineObject()
+{
+ MyQmlObject obj;
+ obj.setStringProperty("Howdy planet");
+
+ QmlEngine e1;
+ e1.rootContext()->setContextProperty("thing", &obj);
+ QmlComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
+
+ QmlEngine e2;
+ e2.rootContext()->setContextProperty("thing", &obj);
+ QmlComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
+
+ QObject *o1 = c1.create();
+ QObject *o2 = c2.create();
+
+ QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
+ QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
+
+ delete o2;
+ delete o1;
+}
+
+// Test that references to QObjects are cleanup when the object is destroyed
+void tst_qmlecmascript::deletedObject()
+{
+ QmlComponent component(&engine, TEST_FILE("deletedObject.qml"));
+
+ QObject *object = component.create();
+
+ QCOMPARE(object->property("test1").toBool(), true);
+ QCOMPARE(object->property("test2").toBool(), true);
+ QCOMPARE(object->property("test3").toBool(), true);
+ QEXPECT_FAIL("", "QTBUG-8077", Continue);
+ QCOMPARE(object->property("test4").toBool(), true);
+
+ delete object;
+}
+
+QTEST_MAIN(tst_qmlecmascript)
+
+#include "tst_qmlecmascript.moc"
diff --git a/tests/auto/declarative/qmlengine/qmlengine.pro b/tests/auto/declarative/qmlengine/qmlengine.pro
new file mode 100644
index 0000000..21d55a4
--- /dev/null
+++ b/tests/auto/declarative/qmlengine/qmlengine.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative webkit network
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlengine.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlengine/tst_qmlengine.cpp b/tests/auto/declarative/qmlengine/tst_qmlengine.cpp
new file mode 100644
index 0000000..af8e44f
--- /dev/null
+++ b/tests/auto/declarative/qmlengine/tst_qmlengine.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlEngine>
+#include <QmlContext>
+#include <QNetworkAccessManager>
+#include <QPointer>
+#include <QDir>
+#include <QDesktopServices>
+#include <QDebug>
+#include <QmlComponent>
+#include <QmlNetworkAccessManagerFactory>
+
+class tst_qmlengine : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlengine() {}
+
+private slots:
+ void rootContext();
+ void networkAccessManager();
+ void baseUrl();
+ void contextForObject();
+ void offlineStoragePath();
+ void clearComponentCache();
+};
+
+void tst_qmlengine::rootContext()
+{
+ QmlEngine engine;
+
+ QVERIFY(engine.rootContext());
+
+ QCOMPARE(engine.rootContext()->engine(), &engine);
+ QVERIFY(engine.rootContext()->parentContext() == 0);
+}
+
+class NetworkAccessManagerFactory : public QmlNetworkAccessManagerFactory
+{
+public:
+ NetworkAccessManagerFactory() : manager(0) {}
+
+ QNetworkAccessManager *create(QObject *parent) {
+ manager = new QNetworkAccessManager(parent);
+ return manager;
+ }
+
+ QNetworkAccessManager *manager;
+};
+
+void tst_qmlengine::networkAccessManager()
+{
+ QmlEngine *engine = new QmlEngine;
+
+ // Test QmlEngine created manager
+ QPointer<QNetworkAccessManager> manager = engine->networkAccessManager();
+ QVERIFY(manager != 0);
+ delete engine;
+
+ // Test factory created manager
+ engine = new QmlEngine;
+ NetworkAccessManagerFactory factory;
+ engine->setNetworkAccessManagerFactory(&factory);
+ QVERIFY(engine->networkAccessManager() == factory.manager);
+ delete engine;
+}
+
+void tst_qmlengine::baseUrl()
+{
+ QmlEngine engine;
+
+ QUrl cwd = QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
+
+ QCOMPARE(engine.baseUrl(), cwd);
+ QCOMPARE(engine.rootContext()->resolvedUrl(QUrl("main.qml")), cwd.resolved(QUrl("main.qml")));
+
+ QDir dir = QDir::current();
+ dir.cdUp();
+ QVERIFY(dir != QDir::current());
+ QDir::setCurrent(dir.path());
+ QVERIFY(QDir::current() == dir);
+
+ QUrl cwd2 = QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
+ QCOMPARE(engine.baseUrl(), cwd2);
+ QCOMPARE(engine.rootContext()->resolvedUrl(QUrl("main.qml")), cwd2.resolved(QUrl("main.qml")));
+
+ engine.setBaseUrl(cwd);
+ QCOMPARE(engine.baseUrl(), cwd);
+ QCOMPARE(engine.rootContext()->resolvedUrl(QUrl("main.qml")), cwd.resolved(QUrl("main.qml")));
+}
+
+void tst_qmlengine::contextForObject()
+{
+ QmlEngine *engine = new QmlEngine;
+
+ // Test null-object
+ QVERIFY(QmlEngine::contextForObject(0) == 0);
+
+ // Test an object with no context
+ QObject object;
+ QVERIFY(QmlEngine::contextForObject(&object) == 0);
+
+ // Test setting null-object
+ QmlEngine::setContextForObject(0, engine->rootContext());
+
+ // Test setting null-context
+ QmlEngine::setContextForObject(&object, 0);
+
+ // Test setting context
+ QmlEngine::setContextForObject(&object, engine->rootContext());
+ QVERIFY(QmlEngine::contextForObject(&object) == engine->rootContext());
+
+ QmlContext context(engine->rootContext());
+
+ // Try changing context
+ QTest::ignoreMessage(QtWarningMsg, "QmlEngine::setContextForObject(): Object already has a QmlContext");
+ QmlEngine::setContextForObject(&object, &context);
+ QVERIFY(QmlEngine::contextForObject(&object) == engine->rootContext());
+
+ // Delete context
+ delete engine; engine = 0;
+ QVERIFY(QmlEngine::contextForObject(&object) == 0);
+}
+
+void tst_qmlengine::offlineStoragePath()
+{
+ // Without these set, QDesktopServices::storageLocation returns
+ // strings with extra "//" at the end. We set them to ignore this problem.
+ qApp->setApplicationName("tst_qmlengine");
+ qApp->setOrganizationName("Nokia");
+ qApp->setOrganizationDomain("nokia.com");
+
+ QmlEngine engine;
+
+ QDir dir(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
+ dir.mkpath("QML");
+ dir.cd("QML");
+ dir.mkpath("OfflineStorage");
+ dir.cd("OfflineStorage");
+
+ QCOMPARE(QDir::fromNativeSeparators(engine.offlineStoragePath()), dir.path());
+
+ engine.setOfflineStoragePath(QDir::homePath());
+ QCOMPARE(engine.offlineStoragePath(), QDir::homePath());
+}
+
+void tst_qmlengine::clearComponentCache()
+{
+ QmlEngine engine;
+
+ // Create original qml file
+ {
+ QFile file("temp.qml");
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ file.write("import Qt 4.6\nQtObject {\nproperty int test: 10\n}\n");
+ file.close();
+ }
+
+ // Test "test" property
+ {
+ QmlComponent component(&engine, "temp.qml");
+ QObject *obj = component.create();
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 10);
+ delete obj;
+ }
+
+ // Modify qml file
+ {
+ QFile file("temp.qml");
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ file.write("import Qt 4.6\nQtObject {\nproperty int test: 11\n}\n");
+ file.close();
+ }
+
+ // Test cache hit
+ {
+ QmlComponent component(&engine, "temp.qml");
+ QObject *obj = component.create();
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 10);
+ delete obj;
+ }
+
+ // Clear cache
+ engine.clearComponentCache();
+
+ // Test cache refresh
+ {
+ QmlComponent component(&engine, "temp.qml");
+ QObject *obj = component.create();
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 11);
+ delete obj;
+ }
+}
+
+QTEST_MAIN(tst_qmlengine)
+
+#include "tst_qmlengine.moc"
diff --git a/tests/auto/declarative/qmlerror/qmlerror.pro b/tests/auto/declarative/qmlerror/qmlerror.pro
new file mode 100644
index 0000000..fa9b79e
--- /dev/null
+++ b/tests/auto/declarative/qmlerror/qmlerror.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlerror.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlerror/test.txt b/tests/auto/declarative/qmlerror/test.txt
new file mode 100644
index 0000000..cdafd9e
--- /dev/null
+++ b/tests/auto/declarative/qmlerror/test.txt
@@ -0,0 +1,3 @@
+Line Content
+Line2 Content
+Line3 Content
diff --git a/tests/auto/declarative/qmlerror/tst_qmlerror.cpp b/tests/auto/declarative/qmlerror/tst_qmlerror.cpp
new file mode 100644
index 0000000..70fef1d
--- /dev/null
+++ b/tests/auto/declarative/qmlerror/tst_qmlerror.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlError>
+#include <QDebug>
+
+class tst_qmlerror : public QObject
+{
+ Q_OBJECT
+private slots:
+ void url();
+ void description();
+ void line();
+ void column();
+ void toString();
+
+ void copy();
+ void debug();
+};
+
+void tst_qmlerror::url()
+{
+ QmlError error;
+
+ QCOMPARE(error.url(), QUrl());
+
+ error.setUrl(QUrl("http://www.nokia.com/main.qml"));
+
+ QCOMPARE(error.url(), QUrl("http://www.nokia.com/main.qml"));
+
+ QmlError error2 = error;
+
+ QCOMPARE(error2.url(), QUrl("http://www.nokia.com/main.qml"));
+
+ error.setUrl(QUrl("http://qt.nokia.com/main.qml"));
+
+ QCOMPARE(error.url(), QUrl("http://qt.nokia.com/main.qml"));
+ QCOMPARE(error2.url(), QUrl("http://www.nokia.com/main.qml"));
+}
+
+void tst_qmlerror::description()
+{
+ QmlError error;
+
+ QCOMPARE(error.description(), QString());
+
+ error.setDescription("An Error");
+
+ QCOMPARE(error.description(), QString("An Error"));
+
+ QmlError error2 = error;
+
+ QCOMPARE(error2.description(), QString("An Error"));
+
+ error.setDescription("Another Error");
+
+ QCOMPARE(error.description(), QString("Another Error"));
+ QCOMPARE(error2.description(), QString("An Error"));
+}
+
+void tst_qmlerror::line()
+{
+ QmlError error;
+
+ QCOMPARE(error.line(), -1);
+
+ error.setLine(102);
+
+ QCOMPARE(error.line(), 102);
+
+ QmlError error2 = error;
+
+ QCOMPARE(error2.line(), 102);
+
+ error.setLine(4);
+
+ QCOMPARE(error.line(), 4);
+ QCOMPARE(error2.line(), 102);
+}
+
+void tst_qmlerror::column()
+{
+ QmlError error;
+
+ QCOMPARE(error.column(), -1);
+
+ error.setColumn(16);
+
+ QCOMPARE(error.column(), 16);
+
+ QmlError error2 = error;
+
+ QCOMPARE(error2.column(), 16);
+
+ error.setColumn(3);
+
+ QCOMPARE(error.column(), 3);
+ QCOMPARE(error2.column(), 16);
+}
+
+void tst_qmlerror::toString()
+{
+ {
+ QmlError error;
+ error.setUrl(QUrl("http://www.nokia.com/main.qml"));
+ error.setDescription("An Error");
+ error.setLine(92);
+ error.setColumn(13);
+
+ QCOMPARE(error.toString(), QString("http://www.nokia.com/main.qml:92:13: An Error"));
+ }
+
+ {
+ QmlError error;
+ error.setUrl(QUrl("http://www.nokia.com/main.qml"));
+ error.setDescription("An Error");
+ error.setLine(92);
+
+ QCOMPARE(error.toString(), QString("http://www.nokia.com/main.qml:92: An Error"));
+ }
+}
+
+void tst_qmlerror::copy()
+{
+ QmlError error;
+ error.setUrl(QUrl("http://www.nokia.com/main.qml"));
+ error.setDescription("An Error");
+ error.setLine(92);
+ error.setColumn(13);
+
+ QmlError error2(error);
+ QmlError error3;
+ error3 = error;
+
+ error.setUrl(QUrl("http://qt.nokia.com/main.qml"));
+ error.setDescription("Another Error");
+ error.setLine(2);
+ error.setColumn(33);
+
+ QCOMPARE(error.url(), QUrl("http://qt.nokia.com/main.qml"));
+ QCOMPARE(error.description(), QString("Another Error"));
+ QCOMPARE(error.line(), 2);
+ QCOMPARE(error.column(), 33);
+
+ QCOMPARE(error2.url(), QUrl("http://www.nokia.com/main.qml"));
+ QCOMPARE(error2.description(), QString("An Error"));
+ QCOMPARE(error2.line(), 92);
+ QCOMPARE(error2.column(), 13);
+
+ QCOMPARE(error3.url(), QUrl("http://www.nokia.com/main.qml"));
+ QCOMPARE(error3.description(), QString("An Error"));
+ QCOMPARE(error3.line(), 92);
+ QCOMPARE(error3.column(), 13);
+
+}
+
+void tst_qmlerror::debug()
+{
+ {
+ QmlError error;
+ error.setUrl(QUrl("http://www.nokia.com/main.qml"));
+ error.setDescription("An Error");
+ error.setLine(92);
+ error.setColumn(13);
+
+ QTest::ignoreMessage(QtWarningMsg, "http://www.nokia.com/main.qml:92:13: An Error ");
+ qWarning() << error;
+ }
+
+ {
+ QUrl url(QUrl::fromLocalFile(QString(SRCDIR) + "/").resolved(QUrl("test.txt")));
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription("An Error");
+ error.setLine(2);
+ error.setColumn(5);
+
+ QString out = url.toString() + ":2:5: An Error \n Line2 Content \n ^ ";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(out));
+
+ qWarning() << error;
+ }
+
+ {
+ QUrl url(QUrl::fromLocalFile(QString(SRCDIR) + "/").resolved(QUrl("foo.txt")));
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription("An Error");
+ error.setLine(2);
+ error.setColumn(5);
+
+ QString out = url.toString() + ":2:5: An Error ";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(out));
+
+ qWarning() << error;
+ }
+}
+
+
+
+QTEST_MAIN(tst_qmlerror)
+
+#include "tst_qmlerror.moc"
diff --git a/tests/auto/declarative/qmlfontloader/data/dummy.ttf b/tests/auto/declarative/qmlfontloader/data/dummy.ttf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/auto/declarative/qmlfontloader/data/dummy.ttf
diff --git a/tests/auto/declarative/qmlfontloader/data/tarzeau_ocr_a.ttf b/tests/auto/declarative/qmlfontloader/data/tarzeau_ocr_a.ttf
new file mode 100644
index 0000000..cf93f96
--- /dev/null
+++ b/tests/auto/declarative/qmlfontloader/data/tarzeau_ocr_a.ttf
Binary files differ
diff --git a/tests/auto/declarative/qmlfontloader/qmlfontloader.pro b/tests/auto/declarative/qmlfontloader/qmlfontloader.pro
new file mode 100644
index 0000000..bc89639
--- /dev/null
+++ b/tests/auto/declarative/qmlfontloader/qmlfontloader.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlfontloader.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlfontloader/tst_qmlfontloader.cpp b/tests/auto/declarative/qmlfontloader/tst_qmlfontloader.cpp
new file mode 100644
index 0000000..19372a0
--- /dev/null
+++ b/tests/auto/declarative/qmlfontloader/tst_qmlfontloader.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlfontloader_p.h>
+#include "../../../shared/util.h"
+
+class tst_qmlfontloader : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlfontloader();
+
+private slots:
+ void noFont();
+ void namedFont();
+ void localFont();
+ void failLocalFont();
+ void webFont();
+ void failWebFont();
+
+private slots:
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlfontloader::tst_qmlfontloader()
+{
+}
+
+void tst_qmlfontloader::noFont()
+{
+ QString componentStr = "import Qt 4.6\nFontLoader { }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlFontLoader *fontObject = qobject_cast<QmlFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QCOMPARE(fontObject->name(), QString(""));
+ QCOMPARE(fontObject->source(), QUrl(""));
+ QTRY_VERIFY(fontObject->status() == QmlFontLoader::Null);
+
+ delete fontObject;
+}
+
+void tst_qmlfontloader::namedFont()
+{
+ QString componentStr = "import Qt 4.6\nFontLoader { name: \"Helvetica\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlFontLoader *fontObject = qobject_cast<QmlFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QCOMPARE(fontObject->source(), QUrl(""));
+ QCOMPARE(fontObject->name(), QString("Helvetica"));
+ QTRY_VERIFY(fontObject->status() == QmlFontLoader::Ready);
+}
+
+void tst_qmlfontloader::localFont()
+{
+ QString componentStr = "import Qt 4.6\nFontLoader { source: \"" SRCDIR "/data/tarzeau_ocr_a.ttf\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlFontLoader *fontObject = qobject_cast<QmlFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString("OCRA"));
+ QTRY_VERIFY(fontObject->status() == QmlFontLoader::Ready);
+}
+
+void tst_qmlfontloader::failLocalFont()
+{
+ QString componentStr = "import Qt 4.6\nFontLoader { source: \"" + QUrl::fromLocalFile(SRCDIR "/data/dummy.ttf").toString() + "\" }";
+ QTest::ignoreMessage(QtWarningMsg, QString("Cannot load font: QUrl( \"" + QUrl::fromLocalFile(SRCDIR "/data/dummy.ttf").toString() + "\" ) ").toUtf8().constData());
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlFontLoader *fontObject = qobject_cast<QmlFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString(""));
+ QTRY_VERIFY(fontObject->status() == QmlFontLoader::Error);
+}
+
+void tst_qmlfontloader::webFont()
+{
+ QString componentStr = "import Qt 4.6\nFontLoader { source: \"http://www.princexml.com/fonts/steffmann/Starburst.ttf\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlFontLoader *fontObject = qobject_cast<QmlFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString("Starburst"));
+ QTRY_VERIFY(fontObject->status() == QmlFontLoader::Ready);
+}
+
+void tst_qmlfontloader::failWebFont()
+{
+ QString componentStr = "import Qt 4.6\nFontLoader { source: \"http://wrong.address.com/Starburst.ttf\" }";
+ QTest::ignoreMessage(QtWarningMsg, "Cannot load font: QUrl( \"http://wrong.address.com/Starburst.ttf\" ) ");
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlFontLoader *fontObject = qobject_cast<QmlFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString(""));
+ QTRY_VERIFY(fontObject->status() == QmlFontLoader::Error);
+}
+
+QTEST_MAIN(tst_qmlfontloader)
+
+#include "tst_qmlfontloader.moc"
diff --git a/tests/auto/declarative/qmlgraphicsanchors/data/anchors.qml b/tests/auto/declarative/qmlgraphicsanchors/data/anchors.qml
new file mode 100644
index 0000000..b64d0b0
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/data/anchors.qml
@@ -0,0 +1,162 @@
+import Qt 4.6
+
+Rectangle {
+ color: "white"
+ width: 240
+ height: 320
+ Rectangle { id: masterRect; objectName: "masterRect"; x: 26; width: 96; height: 20; color: "red" }
+ Rectangle {
+ id: rect1; objectName: "rect1"
+ y: 20; width: 10; height: 10
+ anchors.left: masterRect.left
+ }
+ Rectangle {
+ id: rect2; objectName: "rect2"
+ y: 20; width: 10; height: 10
+ anchors.left: masterRect.right
+ }
+ Rectangle {
+ id: rect3; objectName: "rect3"
+ y: 20; width: 10; height: 10
+ anchors.left: masterRect.horizontalCenter
+ }
+ Rectangle {
+ id: rect4; objectName: "rect4"
+ y: 30; width: 10; height: 10
+ anchors.right: masterRect.left
+ }
+ Rectangle {
+ id: rect5; objectName: "rect5"
+ y: 30; width: 10; height: 10
+ anchors.right: masterRect.right
+ }
+ Rectangle {
+ id: rect6; objectName: "rect6"
+ y: 30; width: 10; height: 10
+ anchors.right: masterRect.horizontalCenter
+ }
+ Rectangle {
+ id: rect7; objectName: "rect7"
+ y: 50; width: 10; height: 10
+ anchors.left: parent.left
+ }
+ Rectangle {
+ id: rect8; objectName: "rect8"
+ y: 50; width: 10; height: 10
+ anchors.left: parent.right
+ }
+ Rectangle {
+ id: rect9; objectName: "rect9"
+ y: 50; width: 10; height: 10
+ anchors.left: parent.horizontalCenter
+ }
+ Rectangle {
+ id: rect10; objectName: "rect10"
+ y: 60; width: 10; height: 10
+ anchors.right: parent.left
+ }
+ Rectangle {
+ id: rect11; objectName: "rect11"
+ y: 60; width: 10; height: 10
+ anchors.right: parent.right
+ }
+ Rectangle {
+ id: rect12; objectName: "rect12"
+ y: 60; width: 10; height: 10
+ anchors.right: parent.horizontalCenter
+ }
+ Rectangle {
+ id: rect13; objectName: "rect13"
+ x: 200; width: 10; height: 10
+ anchors.top: masterRect.bottom
+ }
+ Rectangle {
+ id: rect14; objectName: "rect14"
+ width: 10; height: 10; color: "steelblue"
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ Rectangle {
+ id: rect15; objectName: "rect15"
+ y: 200; height: 10
+ anchors.left: masterRect.left
+ anchors.right: masterRect.right
+ }
+ Rectangle {
+ id: rect16; objectName: "rect16"
+ y: 220; height: 10
+ anchors.left: masterRect.left
+ anchors.horizontalCenter: masterRect.right
+ }
+ Rectangle {
+ id: rect17; objectName: "rect17"
+ y: 240; height: 10
+ anchors.right: masterRect.right
+ anchors.horizontalCenter: masterRect.left
+ }
+ Rectangle {
+ id: rect18; objectName: "rect18"
+ x: 180; width: 10
+ anchors.top: masterRect.bottom
+ anchors.bottom: rect12.top
+ }
+ Rectangle {
+ id: rect19; objectName: "rect19"
+ y: 70; width: 10; height: 10
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ Rectangle {
+ id: rect20; objectName: "rect20"
+ y: 70; width: 10; height: 10
+ anchors.horizontalCenter: parent.right
+ }
+ Rectangle {
+ id: rect21; objectName: "rect21"
+ y: 70; width: 10; height: 10
+ anchors.horizontalCenter: parent.left
+ }
+ Rectangle {
+ id: rect22; objectName: "rect22"
+ width: 10; height: 10
+ anchors.centerIn: masterRect
+ }
+ Rectangle {
+ id: rect23; objectName: "rect23"
+ anchors.left: masterRect.left
+ anchors.leftMargin: 5
+ anchors.right: masterRect.right
+ anchors.rightMargin: 5
+ anchors.top: masterRect.top
+ anchors.topMargin: 5
+ anchors.bottom: masterRect.bottom
+ anchors.bottomMargin: 5
+ }
+ Rectangle {
+ id: rect24; objectName: "rect24"
+ width: 10; height: 10
+ anchors.horizontalCenter: masterRect.left
+ anchors.horizontalCenterOffset: width/2
+ }
+ Rectangle {
+ id: rect25; objectName: "rect25"
+ width: 10; height: 10
+ anchors.verticalCenter: rect12.top
+ anchors.verticalCenterOffset: height/2
+ }
+ Rectangle {
+ id: rect26; objectName: "rect26"
+ width: 10; height: 10
+ anchors.baseline: masterRect.top
+ anchors.baselineOffset: height/2
+ }
+ Text {
+ id: text1; objectName: "text1"
+ y: 200;
+ text: "Hello"
+ }
+ Text {
+ id: text2; objectName: "text2"
+ anchors.baseline: text1.baseline
+ anchors.left: text1.right
+ text: "World"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsanchors/data/centerin.qml b/tests/auto/declarative/qmlgraphicsanchors/data/centerin.qml
new file mode 100644
index 0000000..09b97f6
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/data/centerin.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 200
+ Rectangle {
+ objectName: "centered"
+ width: 50; height: 50; color: "blue"
+ anchors.centerIn: parent;
+ anchors.verticalCenterOffset: 30
+ anchors.horizontalCenterOffset: 10
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsanchors/data/crash1.qml b/tests/auto/declarative/qmlgraphicsanchors/data/crash1.qml
new file mode 100644
index 0000000..fd9dc55
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/data/crash1.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+Column {
+ Text {
+ text: "foo"
+ anchors.fill: parent
+ }
+ Text {
+ text: "bar"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsanchors/data/fill.qml b/tests/auto/declarative/qmlgraphicsanchors/data/fill.qml
new file mode 100644
index 0000000..902465c
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/data/fill.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 200
+ Rectangle {
+ objectName: "filler"
+ width: 50; height: 50; color: "blue"
+ anchors.fill: parent;
+ anchors.leftMargin: 10;
+ anchors.rightMargin: 20;
+ anchors.topMargin: 30;
+ anchors.bottomMargin: 40;
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsanchors/data/loop1.qml b/tests/auto/declarative/qmlgraphicsanchors/data/loop1.qml
new file mode 100644
index 0000000..a266612
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/data/loop1.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Rectangle {
+ id: rect
+ width: 120; height: 200; color: "white"
+ Text { id: text1; anchors.right: text2.right; text: "Hello" }
+ Text { id: text2; anchors.right: text1.right; anchors.rightMargin: 10; text: "World" }
+}
diff --git a/tests/auto/declarative/qmlgraphicsanchors/data/loop2.qml b/tests/auto/declarative/qmlgraphicsanchors/data/loop2.qml
new file mode 100644
index 0000000..acb57cd
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/data/loop2.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+Rectangle {
+ id: container;
+ width: 600;
+ height: 600;
+
+ Image {
+ id: image1
+ source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/3311388091_ac2a257feb.jpg"
+ anchors.right: image2.left
+ }
+
+ Image {
+ id: image2
+ source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/oslo_groupphoto.jpg"
+ anchors.left: image1.right
+ anchors.leftMargin: 20
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsanchors/data/margins.qml b/tests/auto/declarative/qmlgraphicsanchors/data/margins.qml
new file mode 100644
index 0000000..4a29e77
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/data/margins.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 200
+ Rectangle {
+ objectName: "filler"
+ width: 50; height: 50; color: "blue"
+ anchors.fill: parent;
+ anchors.margins: 10
+ anchors.leftMargin: 5
+ anchors.topMargin: 6
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsanchors/qmlgraphicsanchors.pro b/tests/auto/declarative/qmlgraphicsanchors/qmlgraphicsanchors.pro
new file mode 100644
index 0000000..755de3f
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/qmlgraphicsanchors.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlgraphicsanchors.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsanchors/tst_qmlgraphicsanchors.cpp b/tests/auto/declarative/qmlgraphicsanchors/tst_qmlgraphicsanchors.cpp
new file mode 100644
index 0000000..5850cf0
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanchors/tst_qmlgraphicsanchors.cpp
@@ -0,0 +1,459 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QSignalSpy>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlview.h>
+#include <private/qmlgraphicsrectangle_p.h>
+#include <private/qmlgraphicstext_p.h>
+#include <QtDeclarative/private/qmlgraphicsanchors_p_p.h>
+
+Q_DECLARE_METATYPE(QmlGraphicsAnchors::UsedAnchor)
+Q_DECLARE_METATYPE(QmlGraphicsAnchorLine::AnchorLine)
+
+
+class tst_anchors : public QObject
+{
+ Q_OBJECT
+public:
+ tst_anchors() {}
+
+ template<typename T>
+ T *findItem(QmlGraphicsItem *parent, const QString &id);
+
+private slots:
+ void basicAnchors();
+ void loops();
+ void illegalSets();
+ void illegalSets_data();
+ void reset();
+ void reset_data();
+ void resetConvenience();
+ void nullItem();
+ void nullItem_data();
+ void crash1();
+ void centerIn();
+ void fill();
+ void margins();
+};
+
+/*
+ Find an item with the specified id.
+*/
+template<typename T>
+T *tst_anchors::findItem(QmlGraphicsItem *parent, const QString &objectName)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ QList<QGraphicsItem *> children = parent->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(children.at(i)->toGraphicsObject());
+ if (item) {
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ return static_cast<T*>(item);
+ }
+ item = findItem<T>(item, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+ }
+
+ return 0;
+}
+
+void tst_anchors::basicAnchors()
+{
+ QmlView *view = new QmlView;
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/anchors.qml"));
+
+ view->execute();
+ qApp->processEvents();
+
+ //sibling horizontal
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect1"))->x(), 26.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect2"))->x(), 122.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect3"))->x(), 74.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect4"))->x(), 16.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect5"))->x(), 112.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect6"))->x(), 64.0);
+
+ //parent horizontal
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect7"))->x(), 0.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect8"))->x(), 240.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect9"))->x(), 120.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect10"))->x(), -10.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect11"))->x(), 230.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect12"))->x(), 110.0);
+
+ //vertical
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect13"))->y(), 20.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect14"))->y(), 155.0);
+
+ //stretch
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect15"))->x(), 26.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect15"))->width(), 96.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect16"))->x(), 26.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect16"))->width(), 192.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect17"))->x(), -70.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect17"))->width(), 192.0);
+
+ //vertical stretch
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect18"))->y(), 20.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect18"))->height(), 40.0);
+
+ //more parent horizontal
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect19"))->x(), 115.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect20"))->x(), 235.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect21"))->x(), -5.0);
+
+ //centerIn
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect22"))->x(), 69.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect22"))->y(), 5.0);
+
+ //margins
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect23"))->x(), 31.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect23"))->y(), 5.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect23"))->width(), 86.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect23"))->height(), 10.0);
+
+ // offsets
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect24"))->x(), 26.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect25"))->y(), 60.0);
+ QCOMPARE(findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("rect26"))->y(), 5.0);
+
+ //baseline
+ QmlGraphicsText *text1 = findItem<QmlGraphicsText>(view->root(), QLatin1String("text1"));
+ QmlGraphicsText *text2 = findItem<QmlGraphicsText>(view->root(), QLatin1String("text2"));
+ QCOMPARE(text1->y(), text2->y());
+
+ delete view;
+}
+
+// mostly testing that we don't crash
+void tst_anchors::loops()
+{
+ {
+ QmlView *view = new QmlView;
+
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/loop1.qml"));
+
+ QString expect = "QML Text (" + view->url().toString() + ":6:5" + ") Possible anchor loop detected on horizontal anchor.";
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+
+ {
+ QmlView *view = new QmlView;
+
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/loop2.qml"));
+
+ QString expect = "QML Image (" + view->url().toString() + ":8:3" + ") Possible anchor loop detected on horizontal anchor.";
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+}
+
+void tst_anchors::illegalSets()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, warning);
+
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
+
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\n" + qml.toUtf8()), QUrl::fromLocalFile(""));
+ if (!component.isReady())
+ qWarning() << "Test errors:" << component.errors();
+ QVERIFY(component.isReady());
+ QObject *o = component.create();
+ delete o;
+}
+
+void tst_anchors::illegalSets_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("warning");
+
+ QTest::newRow("H - too many anchors")
+ << "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
+ << "QML Rectangle (file::2:23) Can't specify left, right, and hcenter anchors.";
+
+ foreach (const QString &side, QStringList() << "left" << "right") {
+ QTest::newRow("H - anchor to V")
+ << QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(side)
+ << "QML Rectangle (file::2:13) Can't anchor a horizontal edge to a vertical edge.";
+
+ QTest::newRow("H - anchor to non parent/sibling")
+ << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
+ << "QML Rectangle (file::2:45) Can't anchor to an item that isn't a parent or sibling.";
+
+ QTest::newRow("H - anchor to self")
+ << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
+ << "QML Rectangle (file::2:1) Can't anchor item to self.";
+ }
+
+
+ QTest::newRow("V - too many anchors")
+ << "Rectangle { id: rect; Rectangle { anchors.top: rect.top; anchors.bottom: rect.bottom; anchors.verticalCenter: rect.verticalCenter } }"
+ << "QML Rectangle (file::2:23) Can't specify top, bottom, and vcenter anchors.";
+
+ QTest::newRow("V - too many anchors with baseline")
+ << "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
+ << "QML Text (file::2:47) Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors.";
+
+ foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
+
+ QTest::newRow("V - anchor to H")
+ << QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(side)
+ << "QML Rectangle (file::2:13) Can't anchor a vertical edge to a horizontal edge.";
+
+ QTest::newRow("V - anchor to non parent/sibling")
+ << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
+ << "QML Rectangle (file::2:45) Can't anchor to an item that isn't a parent or sibling.";
+
+ QTest::newRow("V - anchor to self")
+ << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
+ << "QML Rectangle (file::2:1) Can't anchor item to self.";
+ }
+
+
+ QTest::newRow("centerIn - anchor to non parent/sibling")
+ << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.centerIn: rect} }"
+ << "QML Rectangle (file::2:45) Can't anchor to an item that isn't a parent or sibling.";
+
+
+ QTest::newRow("fill - anchor to non parent/sibling")
+ << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.fill: rect} }"
+ << "QML Rectangle (file::2:45) Can't anchor to an item that isn't a parent or sibling.";
+}
+
+void tst_anchors::reset()
+{
+ QFETCH(QString, side);
+ QFETCH(QmlGraphicsAnchorLine::AnchorLine, anchorLine);
+ QFETCH(QmlGraphicsAnchors::UsedAnchor, usedAnchor);
+
+ QmlGraphicsItem *baseItem = new QmlGraphicsItem;
+
+ QmlGraphicsAnchorLine anchor;
+ anchor.item = baseItem;
+ anchor.anchorLine = anchorLine;
+
+ QmlGraphicsItem *item = new QmlGraphicsItem;
+
+ const QMetaObject *meta = item->anchors()->metaObject();
+ QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
+
+ QVERIFY(p.write(item->anchors(), qVariantFromValue(anchor)));
+ QCOMPARE(item->anchors()->usedAnchors().testFlag(usedAnchor), true);
+
+ QVERIFY(p.reset(item->anchors()));
+ QCOMPARE(item->anchors()->usedAnchors().testFlag(usedAnchor), false);
+
+ delete item;
+ delete baseItem;
+}
+
+void tst_anchors::reset_data()
+{
+ QTest::addColumn<QString>("side");
+ QTest::addColumn<QmlGraphicsAnchorLine::AnchorLine>("anchorLine");
+ QTest::addColumn<QmlGraphicsAnchors::UsedAnchor>("usedAnchor");
+
+ QTest::newRow("left") << "left" << QmlGraphicsAnchorLine::Left << QmlGraphicsAnchors::HasLeftAnchor;
+ QTest::newRow("top") << "top" << QmlGraphicsAnchorLine::Top << QmlGraphicsAnchors::HasTopAnchor;
+ QTest::newRow("right") << "right" << QmlGraphicsAnchorLine::Right << QmlGraphicsAnchors::HasRightAnchor;
+ QTest::newRow("bottom") << "bottom" << QmlGraphicsAnchorLine::Bottom << QmlGraphicsAnchors::HasBottomAnchor;
+
+ QTest::newRow("hcenter") << "horizontalCenter" << QmlGraphicsAnchorLine::HCenter << QmlGraphicsAnchors::HasHCenterAnchor;
+ QTest::newRow("vcenter") << "verticalCenter" << QmlGraphicsAnchorLine::VCenter << QmlGraphicsAnchors::HasVCenterAnchor;
+ QTest::newRow("baseline") << "baseline" << QmlGraphicsAnchorLine::Baseline << QmlGraphicsAnchors::HasBaselineAnchor;
+}
+
+void tst_anchors::resetConvenience()
+{
+ QmlGraphicsItem *baseItem = new QmlGraphicsItem;
+ QmlGraphicsItem *item = new QmlGraphicsItem;
+
+ //fill
+ item->anchors()->setFill(baseItem);
+ QVERIFY(item->anchors()->fill() == baseItem);
+ item->anchors()->resetFill();
+ QVERIFY(item->anchors()->fill() == 0);
+
+ //centerIn
+ item->anchors()->setCenterIn(baseItem);
+ QVERIFY(item->anchors()->centerIn() == baseItem);
+ item->anchors()->resetCenterIn();
+ QVERIFY(item->anchors()->centerIn() == 0);
+
+ delete item;
+ delete baseItem;
+}
+
+void tst_anchors::nullItem()
+{
+ QFETCH(QString, side);
+
+ QmlGraphicsAnchorLine anchor;
+ QmlGraphicsItem *item = new QmlGraphicsItem;
+
+ const QMetaObject *meta = item->anchors()->metaObject();
+ QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
+
+ QTest::ignoreMessage(QtWarningMsg, "QML Item (unknown location) Can't anchor to a null item.");
+ QVERIFY(p.write(item->anchors(), qVariantFromValue(anchor)));
+
+ delete item;
+}
+
+void tst_anchors::nullItem_data()
+{
+ QTest::addColumn<QString>("side");
+
+ QTest::newRow("left") << "left";
+ QTest::newRow("top") << "top";
+ QTest::newRow("right") << "right";
+ QTest::newRow("bottom") << "bottom";
+
+ QTest::newRow("hcenter") << "horizontalCenter";
+ QTest::newRow("vcenter") << "verticalCenter";
+ QTest::newRow("baseline") << "baseline";
+}
+
+void tst_anchors::crash1()
+{
+ QmlView *view = new QmlView;
+
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/crash1.qml"));
+
+ QString expect = "QML Text (" + view->url().toString() + ":4:5" + ") Possible anchor loop detected on fill.";
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); // XXX ideally, should be one message
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+}
+
+void tst_anchors::fill()
+{
+ QmlView *view = new QmlView;
+
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/fill.qml"));
+
+ view->execute();
+ qApp->processEvents();
+ QmlGraphicsRectangle* rect = findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("filler"));
+ QCOMPARE(rect->x(), 0.0 + 10.0);
+ QCOMPARE(rect->y(), 0.0 + 30.0);
+ QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
+ //Alter Offsets (QTBUG-6631)
+ rect->anchors()->setLeftMargin(20.0);
+ rect->anchors()->setRightMargin(0.0);
+ rect->anchors()->setBottomMargin(0.0);
+ rect->anchors()->setTopMargin(10.0);
+ QCOMPARE(rect->x(), 0.0 + 20.0);
+ QCOMPARE(rect->y(), 0.0 + 10.0);
+ QCOMPARE(rect->width(), 200.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 10.0);
+
+ delete view;
+}
+
+void tst_anchors::centerIn()
+{
+ QmlView *view = new QmlView;
+
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/centerin.qml"));
+
+ view->execute();
+ qApp->processEvents();
+ QmlGraphicsRectangle* rect = findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("centered"));
+ QCOMPARE(rect->x(), 75.0 + 10);
+ QCOMPARE(rect->y(), 75.0 + 30);
+ //Alter Offsets (QTBUG-6631)
+ rect->anchors()->setHorizontalCenterOffset(-20.0);
+ rect->anchors()->setVerticalCenterOffset(-10.0);
+ QCOMPARE(rect->x(), 75.0 - 20.0);
+ QCOMPARE(rect->y(), 75.0 - 10.0);
+
+ delete view;
+}
+
+void tst_anchors::margins()
+{
+ QmlView *view = new QmlView;
+
+ view->setUrl(QUrl::fromLocalFile(SRCDIR "/data/margins.qml"));
+
+ view->execute();
+ qApp->processEvents();
+ QmlGraphicsRectangle* rect = findItem<QmlGraphicsRectangle>(view->root(), QLatin1String("filler"));
+ QCOMPARE(rect->x(), 5.0);
+ QCOMPARE(rect->y(), 6.0);
+ QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
+ QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
+
+ rect->anchors()->setTopMargin(0.0);
+ rect->anchors()->setMargins(20.0);
+
+ QCOMPARE(rect->x(), 5.0);
+ QCOMPARE(rect->y(), 20.0);
+ QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
+
+ delete view;
+}
+
+QTEST_MAIN(tst_anchors)
+
+#include "tst_qmlgraphicsanchors.moc"
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.gif b/tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.gif
new file mode 100644
index 0000000..1270bfa
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.gif
Binary files differ
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.qml b/tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.qml
new file mode 100644
index 0000000..5bada34
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/data/colors.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+AnimatedImage {
+ source: "colors.gif"
+}
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.gif b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.gif
new file mode 100644
index 0000000..7c4cd18
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.gif
Binary files differ
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.qml b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.qml
new file mode 100644
index 0000000..a70db5d
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickman.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+AnimatedImage {
+ source: "stickman.gif"
+}
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanpause.qml b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanpause.qml
new file mode 100644
index 0000000..7ab17d4
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanpause.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+AnimatedImage {
+ source: "stickman.gif"
+ paused: true
+ currentFrame: 2
+}
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanstopped.qml b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanstopped.qml
new file mode 100644
index 0000000..53b0c3a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/data/stickmanstopped.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+AnimatedImage {
+ source: "stickman.gif"
+ playing: false
+}
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/qmlgraphicsanimatedimage.pro b/tests/auto/declarative/qmlgraphicsanimatedimage/qmlgraphicsanimatedimage.pro
new file mode 100644
index 0000000..877dfab
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/qmlgraphicsanimatedimage.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative network
+HEADERS += ../shared/testhttpserver.h
+SOURCES += tst_qmlgraphicsanimatedimage.cpp ../shared/testhttpserver.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsanimatedimage/tst_qmlgraphicsanimatedimage.cpp b/tests/auto/declarative/qmlgraphicsanimatedimage/tst_qmlgraphicsanimatedimage.cpp
new file mode 100644
index 0000000..bc10e30
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsanimatedimage/tst_qmlgraphicsanimatedimage.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlview.h>
+#include <private/qmlgraphicsrectangle_p.h>
+#include <private/qmlgraphicsimage_p.h>
+#include <private/qmlgraphicsanimatedimage_p.h>
+
+#include "../shared/testhttpserver.h"
+
+#define TRY_WAIT(expr) \
+ do { \
+ for (int ii = 0; ii < 6; ++ii) { \
+ if ((expr)) break; \
+ QTest::qWait(50); \
+ } \
+ QVERIFY((expr)); \
+ } while (false)
+
+
+class tst_animatedimage : public QObject
+{
+ Q_OBJECT
+public:
+ tst_animatedimage() {}
+
+private slots:
+ void play();
+ void pause();
+ void stopped();
+ void setFrame();
+ void frameCount();
+ void remote();
+ void remote_data();
+ void invalidSource();
+};
+
+void tst_animatedimage::play()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickman.qml"));
+ QmlGraphicsAnimatedImage *anim = qobject_cast<QmlGraphicsAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+
+ delete anim;
+}
+
+void tst_animatedimage::pause()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanpause.qml"));
+ QmlGraphicsAnimatedImage *anim = qobject_cast<QmlGraphicsAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QVERIFY(anim->isPaused());
+
+ delete anim;
+}
+
+void tst_animatedimage::stopped()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanstopped.qml"));
+ QmlGraphicsAnimatedImage *anim = qobject_cast<QmlGraphicsAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(!anim->isPlaying());
+ QCOMPARE(anim->currentFrame(), 0);
+
+ delete anim;
+}
+
+void tst_animatedimage::setFrame()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanpause.qml"));
+ QmlGraphicsAnimatedImage *anim = qobject_cast<QmlGraphicsAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QCOMPARE(anim->currentFrame(), 2);
+
+ delete anim;
+}
+
+void tst_animatedimage::frameCount()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/colors.qml"));
+ QmlGraphicsAnimatedImage *anim = qobject_cast<QmlGraphicsAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QCOMPARE(anim->frameCount(), 3);
+
+ delete anim;
+}
+
+void tst_animatedimage::remote()
+{
+ QFETCH(QString, fileName);
+ QFETCH(bool, paused);
+
+ TestHTTPServer server(14445);
+ QVERIFY(server.isValid());
+ server.serveDirectory(SRCDIR "/data");
+
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl("http://127.0.0.1:14445/" + fileName));
+ TRY_WAIT(component.isReady());
+
+ QmlGraphicsAnimatedImage *anim = qobject_cast<QmlGraphicsAnimatedImage *>(component.create());
+ QVERIFY(anim);
+
+ TRY_WAIT(anim->isPlaying());
+ if (paused) {
+ TRY_WAIT(anim->isPaused());
+ QCOMPARE(anim->currentFrame(), 2);
+ }
+
+ delete anim;
+}
+
+void tst_animatedimage::remote_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<bool>("paused");
+
+ QTest::newRow("playing") << "stickman.qml" << false;
+ QTest::newRow("paused") << "stickmanpause.qml" << true;
+}
+
+void tst_animatedimage::invalidSource()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
+ QVERIFY(component.isReady());
+
+ QTest::ignoreMessage(QtWarningMsg, "Error Reading Animated Image File QUrl( \"file:no-such-file.gif\" ) ");
+
+ QmlGraphicsAnimatedImage *anim = qobject_cast<QmlGraphicsAnimatedImage *>(component.create());
+ QVERIFY(anim);
+
+ QVERIFY(!anim->isPlaying());
+ QVERIFY(!anim->isPaused());
+ QCOMPARE(anim->currentFrame(), 0);
+ QCOMPARE(anim->frameCount(), 0);
+}
+
+QTEST_MAIN(tst_animatedimage)
+
+#include "tst_qmlgraphicsanimatedimage.moc"
diff --git a/tests/auto/declarative/qmlgraphicsborderimage/data/colors-round.sci b/tests/auto/declarative/qmlgraphicsborderimage/data/colors-round.sci
new file mode 100644
index 0000000..5d2f49f
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsborderimage/data/colors-round.sci
@@ -0,0 +1,7 @@
+border.left:10
+border.top:20
+border.right:30
+border.bottom:40
+horizontalTileRule:Round
+verticalTileRule:Repeat
+source:colors.png
diff --git a/tests/auto/declarative/qmlgraphicsborderimage/data/colors.png b/tests/auto/declarative/qmlgraphicsborderimage/data/colors.png
new file mode 100644
index 0000000..dfb62f3
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsborderimage/data/colors.png
Binary files differ
diff --git a/tests/auto/declarative/qmlgraphicsborderimage/data/invalid.sci b/tests/auto/declarative/qmlgraphicsborderimage/data/invalid.sci
new file mode 100644
index 0000000..98c72c9
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsborderimage/data/invalid.sci
@@ -0,0 +1,7 @@
+border.left:10
+border.top:20
+border.down:30
+border.up:40
+horizontalTileRule:Roun
+verticalTileRule:Repea
+source:colors.png
diff --git a/tests/auto/declarative/qmlgraphicsborderimage/qmlgraphicsborderimage.pro b/tests/auto/declarative/qmlgraphicsborderimage/qmlgraphicsborderimage.pro
new file mode 100644
index 0000000..1f606e5
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsborderimage/qmlgraphicsborderimage.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui network
+macx:CONFIG -= app_bundle
+
+HEADERS += ../shared/testhttpserver.h
+SOURCES += tst_qmlgraphicsborderimage.cpp ../shared/testhttpserver.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsborderimage/tst_qmlgraphicsborderimage.cpp b/tests/auto/declarative/qmlgraphicsborderimage/tst_qmlgraphicsborderimage.cpp
new file mode 100644
index 0000000..1ae0227
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsborderimage/tst_qmlgraphicsborderimage.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QTextDocument>
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QDir>
+
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicsborderimage_p.h>
+#include <private/qmlgraphicsimagebase_p.h>
+#include <private/qmlgraphicsscalegrid_p_p.h>
+#include <private/qmlgraphicsloader_p.h>
+#include <QtDeclarative/qmlcontext.h>
+
+#include "../shared/testhttpserver.h"
+
+
+#define SERVER_PORT 14445
+#define SERVER_ADDR "http://127.0.0.1:14445"
+
+#define TRY_WAIT(expr) \
+ do { \
+ for (int ii = 0; ii < 6; ++ii) { \
+ if ((expr)) break; \
+ QTest::qWait(50); \
+ } \
+ QVERIFY((expr)); \
+ } while (false)
+
+
+class tst_qmlgraphicsborderimage : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicsborderimage();
+
+private slots:
+ void noSource();
+ void imageSource();
+ void imageSource_data();
+ void clearSource();
+ void resized();
+ void smooth();
+ void tileModes();
+ void sciSource();
+ void sciSource_data();
+ void invalidSciFile();
+ void pendingRemoteRequest();
+ void pendingRemoteRequest_data();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlgraphicsborderimage::tst_qmlgraphicsborderimage()
+{
+}
+
+void tst_qmlgraphicsborderimage::noSource()
+{
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->source(), QUrl());
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsborderimage::imageSource_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<bool>("remote");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << false << "";
+ QTest::newRow("local not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString() << false
+ << "Cannot open QUrl( \"" + QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString() + "\" ) ";
+ QTest::newRow("remote") << SERVER_ADDR "/colors.png" << true << "";
+ QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << true
+ << "\"Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found\" ";
+}
+
+void tst_qmlgraphicsborderimage::imageSource()
+{
+ QFETCH(QString, source);
+ QFETCH(bool, remote);
+ QFETCH(QString, error);
+
+ TestHTTPServer *server = 0;
+ if (remote) {
+ server = new TestHTTPServer(SERVER_PORT);
+ QVERIFY(server->isValid());
+ server->serveDirectory(SRCDIR "/data");
+ }
+
+ if (!error.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
+
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" + source + "\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+
+ if (remote)
+ TRY_WAIT(obj->status() == QmlGraphicsBorderImage::Loading);
+
+ QCOMPARE(obj->source(), remote ? source : QUrl(source));
+
+ if (error.isEmpty()) {
+ TRY_WAIT(obj->status() == QmlGraphicsBorderImage::Ready);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Stretch);
+ } else {
+ TRY_WAIT(obj->status() == QmlGraphicsBorderImage::Error);
+ }
+
+ delete obj;
+ delete server;
+}
+
+void tst_qmlgraphicsborderimage::clearSource()
+{
+ QString componentStr = "import Qt 4.6\nBorderImage { source: srcImage }";
+ QmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.png"));
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->status() == QmlGraphicsBorderImage::Ready);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+
+ ctxt->setContextProperty("srcImage", "");
+ QVERIFY(obj->source().isEmpty());
+ QVERIFY(obj->status() == QmlGraphicsBorderImage::Null);
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+}
+
+void tst_qmlgraphicsborderimage::resized()
+{
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" + QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() + "\"; width: 300; height: 300 }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsborderimage::smooth()
+{
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" SRCDIR "/data/colors.png\"; smooth: true; width: 300; height: 300 }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->smooth(), true);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsborderimage::tileModes()
+{
+ {
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" SRCDIR "/data/colors.png\"; width: 100; height: 300; horizontalTileMode: BorderImage.Repeat; verticalTileMode: BorderImage.Repeat }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 100.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Repeat);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Repeat);
+
+ delete obj;
+ }
+ {
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" SRCDIR "/data/colors.png\"; width: 300; height: 150; horizontalTileMode: BorderImage.Round; verticalTileMode: BorderImage.Round }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 150.);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Round);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Round);
+
+ delete obj;
+ }
+}
+
+void tst_qmlgraphicsborderimage::sciSource()
+{
+ QFETCH(QString, source);
+ QFETCH(bool, valid);
+
+ bool remote = source.startsWith("http");
+ TestHTTPServer *server = 0;
+ if (remote) {
+ server = new TestHTTPServer(SERVER_PORT);
+ QVERIFY(server->isValid());
+ server->serveDirectory(SRCDIR "/data");
+ }
+
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" + source + "\"; width: 300; height: 300 }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+
+ if (remote)
+ TRY_WAIT(obj->status() == QmlGraphicsBorderImage::Loading);
+
+ QCOMPARE(obj->source(), remote ? source : QUrl(source));
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+
+ if (valid) {
+ TRY_WAIT(obj->status() == QmlGraphicsBorderImage::Ready);
+ QCOMPARE(obj->border()->left(), 10);
+ QCOMPARE(obj->border()->top(), 20);
+ QCOMPARE(obj->border()->right(), 30);
+ QCOMPARE(obj->border()->bottom(), 40);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Round);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Repeat);
+ } else {
+ TRY_WAIT(obj->status() == QmlGraphicsBorderImage::Error);
+ }
+
+ delete obj;
+ delete server;
+}
+
+void tst_qmlgraphicsborderimage::sciSource_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<bool>("valid");
+
+ QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors-round.sci").toString() << true;
+ QTest::newRow("local not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file.sci").toString() << false;
+ QTest::newRow("remote") << SERVER_ADDR "/colors-round.sci" << true;
+ QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.sci" << false;
+}
+
+void tst_qmlgraphicsborderimage::invalidSciFile()
+{
+ QTest::ignoreMessage(QtWarningMsg, "Unknown tile rule specified. Using Stretch "); // for "Roun"
+ QTest::ignoreMessage(QtWarningMsg, "Unknown tile rule specified. Using Stretch "); // for "Repea"
+
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" + QUrl::fromLocalFile(SRCDIR "/data/invalid.sci").toString() +"\"; width: 300; height: 300 }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->status(), QmlGraphicsImageBase::Error);
+ QCOMPARE(obj->horizontalTileMode(), QmlGraphicsBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QmlGraphicsBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsborderimage::pendingRemoteRequest()
+{
+ QFETCH(QString, source);
+
+ QString componentStr = "import Qt 4.6\nBorderImage { source: \"" + source + "\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsBorderImage *obj = qobject_cast<QmlGraphicsBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->status(), QmlGraphicsBorderImage::Loading);
+
+ // verify no crash
+ // This will cause a delayed "QThread: Destroyed while thread is still running" warning
+ delete obj;
+ QTest::qWait(50);
+}
+
+void tst_qmlgraphicsborderimage::pendingRemoteRequest_data()
+{
+ QTest::addColumn<QString>("source");
+
+ QTest::newRow("png file") << "http://no-such-qt-server-like-this/none.png";
+ QTest::newRow("sci file") << "http://no-such-qt-server-like-this/none.sci";
+}
+
+QTEST_MAIN(tst_qmlgraphicsborderimage)
+
+#include "tst_qmlgraphicsborderimage.moc"
diff --git a/tests/auto/declarative/qmlgraphicsflickable/data/flickable01.qml b/tests/auto/declarative/qmlgraphicsflickable/data/flickable01.qml
new file mode 100644
index 0000000..8a1843c
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflickable/data/flickable01.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+Flickable {
+}
diff --git a/tests/auto/declarative/qmlgraphicsflickable/data/flickable02.qml b/tests/auto/declarative/qmlgraphicsflickable/data/flickable02.qml
new file mode 100644
index 0000000..3e08359
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflickable/data/flickable02.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Flickable {
+ width: 100; height: 100
+ viewportWidth: row.width; viewportHeight: row.height
+
+ Row {
+ id: row
+ Repeater {
+ model: 4
+ Rectangle { width: 200; height: 300; color: "blue" }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsflickable/data/flickable03.qml b/tests/auto/declarative/qmlgraphicsflickable/data/flickable03.qml
new file mode 100644
index 0000000..3ed173d
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflickable/data/flickable03.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Flickable {
+ width: 100; height: 100
+ viewportWidth: column.width; viewportHeight: column.height
+
+ Column {
+ id: column
+ Repeater {
+ model: 4
+ Rectangle { width: 200; height: 300; color: "blue" }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsflickable/data/flickable04.qml b/tests/auto/declarative/qmlgraphicsflickable/data/flickable04.qml
new file mode 100644
index 0000000..1425d85
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflickable/data/flickable04.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+Flickable {
+ width: 100; height: 100
+ viewportWidth: column.width; viewportHeight: column.height
+ pressDelay: 200; overShoot: false; interactive: false
+ maximumFlickVelocity: 2000
+
+ Column {
+ id: column
+ Repeater {
+ model: 4
+ Rectangle { width: 200; height: 300; color: "blue" }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsflickable/qmlgraphicsflickable.pro b/tests/auto/declarative/qmlgraphicsflickable/qmlgraphicsflickable.pro
new file mode 100644
index 0000000..7c4c959
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflickable/qmlgraphicsflickable.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicsflickable.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsflickable/tst_qmlgraphicsflickable.cpp b/tests/auto/declarative/qmlgraphicsflickable/tst_qmlgraphicsflickable.cpp
new file mode 100644
index 0000000..c0ffeb7
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflickable/tst_qmlgraphicsflickable.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicsflickable_p.h>
+#include <private/qmlvaluetype_p.h>
+#include <math.h>
+
+class tst_qmlgraphicsflickable : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicsflickable();
+
+private slots:
+ void create();
+ void horizontalViewportSize();
+ void verticalViewportSize();
+ void properties();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlgraphicsflickable::tst_qmlgraphicsflickable()
+{
+}
+
+void tst_qmlgraphicsflickable::create()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable01.qml"));
+ QmlGraphicsFlickable *obj = qobject_cast<QmlGraphicsFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->isAtXBeginning(), true);
+ QCOMPARE(obj->isAtXEnd(), false);
+ QCOMPARE(obj->isAtYBeginning(), true);
+ QCOMPARE(obj->isAtYEnd(), false);
+ QCOMPARE(obj->viewportX(), 0.);
+ QCOMPARE(obj->viewportY(), 0.);
+
+ QCOMPARE(obj->horizontalVelocity(), 0.);
+ QCOMPARE(obj->verticalVelocity(), 0.);
+ QCOMPARE(obj->reportedVelocitySmoothing(), 100.);
+
+ QCOMPARE(obj->isInteractive(), true);
+ QCOMPARE(obj->overShoot(), true);
+ QCOMPARE(obj->pressDelay(), 0);
+ QCOMPARE(obj->maximumFlickVelocity(), 2000.);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsflickable::horizontalViewportSize()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable02.qml"));
+ QmlGraphicsFlickable *obj = qobject_cast<QmlGraphicsFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->viewportWidth(), 800.);
+ QCOMPARE(obj->viewportHeight(), 300.);
+ QCOMPARE(obj->isAtXBeginning(), true);
+ QCOMPARE(obj->isAtXEnd(), false);
+ QCOMPARE(obj->isAtYBeginning(), true);
+ QCOMPARE(obj->isAtYEnd(), false);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsflickable::verticalViewportSize()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml"));
+ QmlGraphicsFlickable *obj = qobject_cast<QmlGraphicsFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->viewportWidth(), 200.);
+ QCOMPARE(obj->viewportHeight(), 1200.);
+ QCOMPARE(obj->isAtXBeginning(), true);
+ QCOMPARE(obj->isAtXEnd(), false);
+ QCOMPARE(obj->isAtYBeginning(), true);
+ QCOMPARE(obj->isAtYEnd(), false);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsflickable::properties()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable04.qml"));
+ QmlGraphicsFlickable *obj = qobject_cast<QmlGraphicsFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->isInteractive(), false);
+ QCOMPARE(obj->overShoot(), false);
+ QCOMPARE(obj->pressDelay(), 200);
+ QCOMPARE(obj->maximumFlickVelocity(), 2000.);
+
+ delete obj;
+}
+
+QTEST_MAIN(tst_qmlgraphicsflickable)
+
+#include "tst_qmlgraphicsflickable.moc"
diff --git a/tests/auto/declarative/qmlgraphicsflipable/data/test-flipable.qml b/tests/auto/declarative/qmlgraphicsflipable/data/test-flipable.qml
new file mode 100644
index 0000000..21d356d
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflipable/data/test-flipable.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+Flipable {
+ id: flipable
+ width: 640; height: 480
+
+ front: Rectangle { anchors.fill: flipable }
+ back: Rectangle { anchors.fill: flipable }
+}
diff --git a/tests/auto/declarative/qmlgraphicsflipable/qmlgraphicsflipable.pro b/tests/auto/declarative/qmlgraphicsflipable/qmlgraphicsflipable.pro
new file mode 100644
index 0000000..b046086
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflipable/qmlgraphicsflipable.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicsflipable.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsflipable/tst_qmlgraphicsflipable.cpp b/tests/auto/declarative/qmlgraphicsflipable/tst_qmlgraphicsflipable.cpp
new file mode 100644
index 0000000..e571e4e
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsflipable/tst_qmlgraphicsflipable.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicsflipable_p.h>
+#include <private/qmlvaluetype_p.h>
+#include <QFontMetrics>
+#include <private/qmlgraphicsrectangle_p.h>
+#include <math.h>
+
+class tst_qmlgraphicsflipable : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicsflipable();
+
+private slots:
+ void create();
+ void checkFrontAndBack();
+ void setFrontAndBack();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlgraphicsflipable::tst_qmlgraphicsflipable()
+{
+}
+
+void tst_qmlgraphicsflipable::create()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
+ QmlGraphicsFlipable *obj = qobject_cast<QmlGraphicsFlipable*>(c.create());
+
+ QVERIFY(obj != 0);
+ delete obj;
+}
+
+void tst_qmlgraphicsflipable::checkFrontAndBack()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
+ QmlGraphicsFlipable *obj = qobject_cast<QmlGraphicsFlipable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->front() != 0);
+ QVERIFY(obj->back() != 0);
+ delete obj;
+}
+
+void tst_qmlgraphicsflipable::setFrontAndBack()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
+ QmlGraphicsFlipable *obj = qobject_cast<QmlGraphicsFlipable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->front() != 0);
+ QVERIFY(obj->back() != 0);
+
+ QString message = "QML Flipable (" + c.url().toString() + ":3:1) front is a write-once property";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ obj->setFront(new QmlGraphicsRectangle());
+
+ message = "QML Flipable (" + c.url().toString() + ":3:1) back is a write-once property";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ obj->setBack(new QmlGraphicsRectangle());
+ delete obj;
+}
+
+QTEST_MAIN(tst_qmlgraphicsflipable)
+
+#include "tst_qmlgraphicsflipable.moc"
diff --git a/tests/auto/declarative/qmlgraphicsgridview/data/gridview-initCurrent.qml b/tests/auto/declarative/qmlgraphicsgridview/data/gridview-initCurrent.qml
new file mode 100644
index 0000000..32833d2
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsgridview/data/gridview-initCurrent.qml
@@ -0,0 +1,51 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ width: 80
+ height: 60
+ border.color: "blue"
+ Text {
+ text: index
+ }
+ Text {
+ x: 40
+ text: wrapper.x + ", " + wrapper.y
+ }
+ Text {
+ y: 20
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ y: 40
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ color: GridView.isCurrentItem ? "lightsteelblue" : "white"
+ }
+ }
+ ]
+ GridView {
+ id: grid
+ objectName: "grid"
+ focus: true
+ width: 240
+ height: 320
+ currentIndex: 5
+ cellWidth: 80
+ cellHeight: 60
+ delegate: myDelegate
+ model: testModel
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsgridview/data/gridview.qml b/tests/auto/declarative/qmlgraphicsgridview/data/gridview.qml
new file mode 100644
index 0000000..344b4b5
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsgridview/data/gridview.qml
@@ -0,0 +1,50 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ width: 80
+ height: 60
+ border.color: "blue"
+ Text {
+ text: index
+ }
+ Text {
+ x: 40
+ text: wrapper.x + ", " + wrapper.y
+ }
+ Text {
+ y: 20
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ y: 40
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ color: GridView.isCurrentItem ? "lightsteelblue" : "white"
+ }
+ }
+ ]
+ GridView {
+ id: grid
+ objectName: "grid"
+ width: 240
+ height: 320
+ cellWidth: 80
+ cellHeight: 60
+ flow: (testTopToBottom == false) ? "LeftToRight" : "TopToBottom"
+ model: testModel
+ delegate: myDelegate
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsgridview/data/gridview2.qml b/tests/auto/declarative/qmlgraphicsgridview/data/gridview2.qml
new file mode 100644
index 0000000..62b5bd3
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsgridview/data/gridview2.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+GridView {
+ anchors.fill: parent
+ width: 320; height: 200
+ cellWidth: 100; cellHeight: 100; cacheBuffer: 200; focus: true
+ keyNavigationWraps: true; highlightFollowsCurrentItem: false
+
+ model: ListModel {
+ id: appModel
+ ListElement { lColor: "red" }
+ ListElement { lColor: "yellow" }
+ ListElement { lColor: "green" }
+ ListElement { lColor: "blue" }
+ }
+
+ delegate: Item {
+ width: 100; height: 100
+ Rectangle {
+ color: lColor; x: 4; y: 4
+ width: 92; height: 92
+ }
+ }
+
+ highlight: Rectangle { width: 100; height: 100; color: "black" }
+}
diff --git a/tests/auto/declarative/qmlgraphicsgridview/data/gridview3.qml b/tests/auto/declarative/qmlgraphicsgridview/data/gridview3.qml
new file mode 100644
index 0000000..b133d55
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsgridview/data/gridview3.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+GridView {
+ anchors.fill: parent
+ width: 320; height: 200
+}
diff --git a/tests/auto/declarative/qmlgraphicsgridview/qmlgraphicsgridview.pro b/tests/auto/declarative/qmlgraphicsgridview/qmlgraphicsgridview.pro
new file mode 100644
index 0000000..8eae8ae
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsgridview/qmlgraphicsgridview.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicsgridview.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsgridview/tst_qmlgraphicsgridview.cpp b/tests/auto/declarative/qmlgraphicsgridview/tst_qmlgraphicsgridview.cpp
new file mode 100644
index 0000000..c157e62
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsgridview/tst_qmlgraphicsgridview.cpp
@@ -0,0 +1,989 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmlengine.h>
+#include <qmlcomponent.h>
+#include <QtTest/QtTest>
+#include <private/qlistmodelinterface_p.h>
+#include <qmlview.h>
+#include <private/qmlgraphicsgridview_p.h>
+#include <private/qmlgraphicstext_p.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+
+class tst_QmlGraphicsGridView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsGridView();
+
+private slots:
+ void items();
+ void changed();
+ void inserted();
+ void removed();
+ void moved();
+ void changeFlow();
+ void currentIndex();
+ void defaultValues();
+ void properties();
+ void positionViewAtIndex();
+
+private:
+ QmlView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QmlGraphicsItem *parent, const QString &id, int index=-1);
+ template<typename T>
+ QList<T*> findItems(QmlGraphicsItem *parent, const QString &objectName);
+ void dumpTree(QmlGraphicsItem *parent, int depth = 0);
+};
+
+class TestModel : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ emit endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QmlGraphicsGridView::tst_QmlGraphicsGridView()
+{
+}
+
+void tst_QmlGraphicsGridView::items()
+{
+ QmlView *canvas = createView(SRCDIR "/data/gridview.qml");
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Billy", "22345");
+ model.addItem("Sam", "2945");
+ model.addItem("Ben", "04321");
+ model.addItem("Jim", "0780");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsGridView *gridview = findItem<QmlGraphicsGridView>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ QCOMPARE(gridview->count(), model.count());
+ QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ for (int i = 0; i < model.count(); ++i) {
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ // set an empty model and confirm that items are destroyed
+ TestModel model2;
+ ctxt->setContextProperty("testModel", &model2);
+
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ QVERIFY(itemCount == 0);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsGridView::changed()
+{
+ QmlView *canvas = createView(SRCDIR "/data/gridview.qml");
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Billy", "22345");
+ model.addItem("Sam", "2945");
+ model.addItem("Ben", "04321");
+ model.addItem("Jim", "0780");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsFlickable *gridview = findItem<QmlGraphicsFlickable>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.modifyItem(1, "Will", "9876");
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsGridView::inserted()
+{
+ QmlView *canvas = createView(SRCDIR "/data/gridview.qml");
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsGridView *gridview = findItem<QmlGraphicsGridView>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.insertItem(1, "Will", "9876");
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ QCOMPARE(item->x(), (i%3)*80.0);
+ QCOMPARE(item->y(), (i/3)*60.0);
+ }
+
+ model.insertItem(0, "Foo", "1111"); // zero index, and current item
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ name = findItem<QmlGraphicsText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ QCOMPARE(gridview->currentIndex(), 1);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ }
+
+ for (int i = model.count(); i < 30; ++i)
+ model.insertItem(i, "Hello", QString::number(i));
+ QTest::qWait(300);
+
+ gridview->setViewportY(120);
+ QTest::qWait(300);
+
+ // Insert item outside visible area
+ model.insertItem(1, "Hello", "1324");
+ QTest::qWait(300);
+
+ QVERIFY(gridview->viewportY() == 120);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsGridView::removed()
+{
+ QmlView *canvas = createView(SRCDIR "/data/gridview.qml");
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsGridView *gridview = findItem<QmlGraphicsGridView>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.removeItem(1);
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove first item (which is the current item);
+ model.removeItem(0);
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ name = findItem<QmlGraphicsText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove items not visible
+ model.removeItem(25);
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove items before visible
+ gridview->setViewportY(120);
+ QTest::qWait(500);
+ gridview->setCurrentIndex(10);
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Setting currentIndex above shouldn't cause view to scroll
+ QCOMPARE(gridview->viewportY(), 120.0);
+
+ model.removeItem(1);
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly
+ for (int i = 6; i < 18; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove currentIndex
+ QmlGraphicsItem *oldCurrent = gridview->currentItem();
+ model.removeItem(9);
+ QTest::qWait(500);
+
+ QCOMPARE(gridview->currentIndex(), 9);
+ QVERIFY(gridview->currentItem() != oldCurrent);
+
+ gridview->setViewportY(0);
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ }
+
+ // remove item outside current view.
+ gridview->setCurrentIndex(32);
+ QTest::qWait(500);
+ gridview->setViewportY(240);
+
+ model.removeItem(30);
+ QVERIFY(gridview->currentIndex() == 31);
+
+ // remove current item beyond visible items.
+ gridview->setCurrentIndex(20);
+ QTest::qWait(500);
+ gridview->setViewportY(0);
+ model.removeItem(20);
+ QTest::qWait(500);
+
+ QCOMPARE(gridview->currentIndex(), 20);
+ QVERIFY(gridview->currentItem() != 0);
+
+ // remove item before current, but visible
+ gridview->setCurrentIndex(8);
+ QTest::qWait(500);
+ gridview->setViewportY(240);
+ oldCurrent = gridview->currentItem();
+ model.removeItem(6);
+ QTest::qWait(500);
+
+ QCOMPARE(gridview->currentIndex(), 7);
+ QVERIFY(gridview->currentItem() == oldCurrent);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsGridView::moved()
+{
+ QmlView *canvas = createView(SRCDIR "/data/gridview.qml");
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsGridView *gridview = findItem<QmlGraphicsGridView>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.moveItem(1, 8);
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ name = findItem<QmlGraphicsText>(viewport, "textName", 8);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(8));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", 8);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(8));
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ }
+
+ gridview->setViewportY(120);
+
+ // move outside visible area
+ model.moveItem(1, 25);
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly and indexes correct
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count()-1;
+ for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), qreal((i%3)*80));
+ QCOMPARE(item->y(), qreal((i/3)*60));
+ name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ // move from outside visible into visible
+ model.moveItem(28, 8);
+
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly and indexes correct
+ for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->x() == (i%3)*80);
+ QVERIFY(item->y() == (i/3)*60);
+ name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsGridView::currentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QString filename(SRCDIR "/data/gridview-initCurrent.qml");
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsGridView *gridview = findItem<QmlGraphicsGridView>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ QTest::qWait(500);
+
+ // current item should be third item
+ QCOMPARE(gridview->currentIndex(), 5);
+ QCOMPARE(gridview->currentItem(), findItem<QmlGraphicsItem>(viewport, "wrapper", 5));
+ QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
+
+ gridview->moveCurrentIndexRight();
+ QCOMPARE(gridview->currentIndex(), 6);
+ gridview->moveCurrentIndexDown();
+ QCOMPARE(gridview->currentIndex(), 9);
+ gridview->moveCurrentIndexUp();
+ QCOMPARE(gridview->currentIndex(), 6);
+ gridview->moveCurrentIndexLeft();
+ QCOMPARE(gridview->currentIndex(), 5);
+
+ // no wrap
+ gridview->setCurrentIndex(0);
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ gridview->moveCurrentIndexUp();
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ gridview->moveCurrentIndexLeft();
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ gridview->setCurrentIndex(model.count()-1);
+ QTest::qWait(500);
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ gridview->moveCurrentIndexRight();
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ gridview->moveCurrentIndexDown();
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ // with wrap
+ gridview->setWrapEnabled(true);
+
+ gridview->setCurrentIndex(0);
+ QCOMPARE(gridview->currentIndex(), 0);
+ QTest::qWait(500);
+
+ gridview->moveCurrentIndexLeft();
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ QTest::qWait(500);
+ QCOMPARE(gridview->viewportY(), 279.0);
+
+ gridview->moveCurrentIndexRight();
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ QTest::qWait(500);
+ QCOMPARE(gridview->viewportY(), 0.0);
+
+ // Test keys
+ canvas->show();
+ canvas->setFocus();
+ qApp->processEvents();
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(gridview->currentIndex(), 3);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ gridview->setFlow(QmlGraphicsGridView::TopToBottom);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(gridview->currentIndex(), 5);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(gridview->currentIndex(), 1);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(gridview->currentIndex(), 0);
+
+
+ // turn off auto highlight
+ gridview->setHighlightFollowsCurrentItem(false);
+ QVERIFY(gridview->highlightFollowsCurrentItem() == false);
+
+ QTest::qWait(500);
+ QVERIFY(gridview->highlightItem());
+ qreal hlPosX = gridview->highlightItem()->x();
+ qreal hlPosY = gridview->highlightItem()->y();
+
+ gridview->setCurrentIndex(5);
+ QTest::qWait(500);
+ QCOMPARE(gridview->highlightItem()->x(), hlPosX);
+ QCOMPARE(gridview->highlightItem()->y(), hlPosY);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsGridView::changeFlow()
+{
+ QmlView *canvas = createView(SRCDIR "/data/gridview.qml");
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsGridView *gridview = findItem<QmlGraphicsGridView>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ // Confirm items positioned correctly and indexes correct
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), qreal((i%3)*80));
+ QCOMPARE(item->y(), qreal((i/3)*60));
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ ctxt->setContextProperty("testTopToBottom", QVariant(true));
+ QTest::qWait(500);
+
+ // Confirm items positioned correctly and indexes correct
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), qreal((i/5)*80));
+ QCOMPARE(item->y(), qreal((i%5)*60));
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsGridView::defaultValues()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/gridview3.qml"));
+ QmlGraphicsGridView *obj = qobject_cast<QmlGraphicsGridView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->model() == QVariant());
+ QVERIFY(obj->delegate() == 0);
+ QCOMPARE(obj->currentIndex(), -1);
+ QVERIFY(obj->currentItem() == 0);
+ QCOMPARE(obj->count(), 0);
+ QVERIFY(obj->highlight() == 0);
+ QVERIFY(obj->highlightItem() == 0);
+ QCOMPARE(obj->highlightFollowsCurrentItem(), true);
+ QVERIFY(obj->flow() == 0);
+ QCOMPARE(obj->isWrapEnabled(), false);
+ QCOMPARE(obj->cacheBuffer(), 0);
+ QCOMPARE(obj->cellWidth(), 100); //### Should 100 be the default?
+ QCOMPARE(obj->cellHeight(), 100);
+ delete obj;
+}
+
+void tst_QmlGraphicsGridView::properties()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/gridview2.qml"));
+ QmlGraphicsGridView *obj = qobject_cast<QmlGraphicsGridView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->model() != QVariant());
+ QVERIFY(obj->delegate() != 0);
+ QCOMPARE(obj->currentIndex(), 0);
+ QVERIFY(obj->currentItem() != 0);
+ QCOMPARE(obj->count(), 4);
+ QVERIFY(obj->highlight() != 0);
+ QVERIFY(obj->highlightItem() != 0);
+ QCOMPARE(obj->highlightFollowsCurrentItem(), false);
+ QVERIFY(obj->flow() == 0);
+ QCOMPARE(obj->isWrapEnabled(), true);
+ QCOMPARE(obj->cacheBuffer(), 200);
+ QCOMPARE(obj->cellWidth(), 100);
+ QCOMPARE(obj->cellHeight(), 100);
+ delete obj;
+}
+
+void tst_QmlGraphicsGridView::positionViewAtIndex()
+{
+ QmlView *canvas = createView(SRCDIR "/data/gridview.qml");
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsGridView *gridview = findItem<QmlGraphicsGridView>(canvas->root(), "grid");
+ QVERIFY(gridview != 0);
+
+ QmlGraphicsItem *viewport = gridview->viewport();
+ QVERIFY(viewport != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), (i%3)*80.);
+ QCOMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position on a currently visible item
+ gridview->positionViewAtIndex(4);
+ QCOMPARE(gridview->viewportY(), 60.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), (i%3)*80.);
+ QCOMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position on an item beyond the visible items
+ gridview->positionViewAtIndex(21);
+ QCOMPARE(gridview->viewportY(), 420.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), (i%3)*80.);
+ QCOMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position on an item that would leave empty space if positioned at the top
+ gridview->positionViewAtIndex(31);
+ QCOMPARE(gridview->viewportY(), 520.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), (i%3)*80.);
+ QCOMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position at the beginning again
+ gridview->positionViewAtIndex(0);
+ QCOMPARE(gridview->viewportY(), 0.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), (i%3)*80.);
+ QCOMPARE(item->y(), (i/3)*60.);
+ }
+
+ delete canvas;
+}
+
+QmlView *tst_QmlGraphicsGridView::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QmlGraphicsGridView::findItem(QmlGraphicsItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QGraphicsObject::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QmlContext *context = QmlEngine::contextForObject(item);
+ if (context) {
+ if (context->contextProperty("index").toInt() == index) {
+ return static_cast<T*>(item);
+ }
+ }
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+template<typename T>
+QList<T*> tst_QmlGraphicsGridView::findItems(QmlGraphicsItem *parent, const QString &objectName)
+{
+ QList<T*> items;
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QGraphicsObject::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ items.append(static_cast<T*>(item));
+ //qDebug() << " found:" << item;
+ }
+ items += findItems<T>(item, objectName);
+ }
+
+ return items;
+}
+
+void tst_QmlGraphicsGridView::dumpTree(QmlGraphicsItem *parent, int depth)
+{
+ static QString padding(" ");
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ QmlContext *context = QmlEngine::contextForObject(item);
+ qDebug() << padding.left(depth*2) << item << (context ? context->contextProperty("index").toInt() : -1);
+ dumpTree(item, depth+1);
+ }
+}
+
+
+QTEST_MAIN(tst_QmlGraphicsGridView)
+
+#include "tst_qmlgraphicsgridview.moc"
diff --git a/tests/auto/declarative/qmlgraphicsimage/data/colors.png b/tests/auto/declarative/qmlgraphicsimage/data/colors.png
new file mode 100644
index 0000000..dfb62f3
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsimage/data/colors.png
Binary files differ
diff --git a/tests/auto/declarative/qmlgraphicsimage/qmlgraphicsimage.pro b/tests/auto/declarative/qmlgraphicsimage/qmlgraphicsimage.pro
new file mode 100644
index 0000000..b5f7f83
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsimage/qmlgraphicsimage.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui network
+macx:CONFIG -= app_bundle
+
+HEADERS += ../shared/testhttpserver.h
+SOURCES += tst_qmlgraphicsimage.cpp ../shared/testhttpserver.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp b/tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp
new file mode 100644
index 0000000..79dc290
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QTextDocument>
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QDir>
+
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicsimage_p.h>
+#include <private/qmlgraphicsimagebase_p.h>
+#include <private/qmlgraphicsloader_p.h>
+#include <QtDeclarative/qmlcontext.h>
+
+#include "../shared/testhttpserver.h"
+
+
+#define SERVER_PORT 14445
+#define SERVER_ADDR "http://127.0.0.1:14445"
+
+#define TRY_WAIT(expr) \
+ do { \
+ for (int ii = 0; ii < 6; ++ii) { \
+ if ((expr)) break; \
+ QTest::qWait(50); \
+ } \
+ QVERIFY((expr)); \
+ } while (false)
+
+
+class tst_qmlgraphicsimage : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicsimage();
+
+private slots:
+ void noSource();
+ void imageSource();
+ void imageSource_data();
+ void clearSource();
+ void resized();
+ void smooth();
+ void pixmap();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlgraphicsimage::tst_qmlgraphicsimage()
+{
+}
+
+void tst_qmlgraphicsimage::noSource()
+{
+ QString componentStr = "import Qt 4.6\nImage { source: \"\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsImage *obj = qobject_cast<QmlGraphicsImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->source(), QUrl());
+ QVERIFY(obj->status() == QmlGraphicsImage::Null);
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+ QCOMPARE(obj->fillMode(), QmlGraphicsImage::Stretch);
+ QCOMPARE(obj->progress(), 0.0);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsimage::imageSource_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<bool>("remote");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << false << "";
+ QTest::newRow("local not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString() << false
+ << "Cannot open QUrl( \"" + QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString() + "\" ) ";
+ QTest::newRow("remote") << SERVER_ADDR "/colors.png" << true << "";
+ QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << true
+ << "\"Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found\" ";
+}
+
+void tst_qmlgraphicsimage::imageSource()
+{
+ QFETCH(QString, source);
+ QFETCH(bool, remote);
+ QFETCH(QString, error);
+
+ TestHTTPServer server(SERVER_PORT);
+ if (remote) {
+ QVERIFY(server.isValid());
+ server.serveDirectory(SRCDIR "/data");
+ }
+
+ if (!error.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
+
+ QString componentStr = "import Qt 4.6\nImage { source: \"" + source + "\" }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsImage *obj = qobject_cast<QmlGraphicsImage*>(component.create());
+ QVERIFY(obj != 0);
+
+ if (remote)
+ TRY_WAIT(obj->status() == QmlGraphicsImage::Loading);
+
+ QCOMPARE(obj->source(), remote ? source : QUrl(source));
+
+ if (error.isEmpty()) {
+ TRY_WAIT(obj->status() == QmlGraphicsImage::Ready);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+ QCOMPARE(obj->fillMode(), QmlGraphicsImage::Stretch);
+ QCOMPARE(obj->progress(), 1.0);
+ } else {
+ TRY_WAIT(obj->status() == QmlGraphicsImage::Error);
+ }
+
+ delete obj;
+}
+
+void tst_qmlgraphicsimage::clearSource()
+{
+ QString componentStr = "import Qt 4.6\nImage { source: srcImage }";
+ QmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.png"));
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsImage *obj = qobject_cast<QmlGraphicsImage*>(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->status() == QmlGraphicsImage::Ready);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+ QCOMPARE(obj->progress(), 1.0);
+
+ ctxt->setContextProperty("srcImage", "");
+ QVERIFY(obj->source().isEmpty());
+ QVERIFY(obj->status() == QmlGraphicsImage::Null);
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+ QCOMPARE(obj->progress(), 0.0);
+}
+
+void tst_qmlgraphicsimage::resized()
+{
+ QString componentStr = "import Qt 4.6\nImage { source: \"" SRCDIR "/data/colors.png\"; width: 300; height: 300 }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsImage *obj = qobject_cast<QmlGraphicsImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->fillMode(), QmlGraphicsImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsimage::smooth()
+{
+ QString componentStr = "import Qt 4.6\nImage { source: \"" SRCDIR "/data/colors.png\"; smooth: true; width: 300; height: 300 }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsImage *obj = qobject_cast<QmlGraphicsImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->smooth(), true);
+ QCOMPARE(obj->fillMode(), QmlGraphicsImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qmlgraphicsimage::pixmap()
+{
+ QString componentStr = "import Qt 4.6\nImage { pixmap: testPixmap }";
+
+ QPixmap pixmap;
+ QmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("testPixmap", pixmap);
+
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+
+ QmlGraphicsImage *obj = qobject_cast<QmlGraphicsImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->source(), QUrl());
+ QVERIFY(obj->status() == QmlGraphicsImage::Null);
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+ QCOMPARE(obj->fillMode(), QmlGraphicsImage::Stretch);
+ QCOMPARE(obj->progress(), 0.0);
+ QVERIFY(obj->pixmap().isNull());
+
+ pixmap = QPixmap(SRCDIR "/data/colors.png");
+ ctxt->setContextProperty("testPixmap", pixmap);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+ QVERIFY(obj->status() == QmlGraphicsImage::Ready);
+
+ delete obj;
+}
+
+QTEST_MAIN(tst_qmlgraphicsimage)
+
+#include "tst_qmlgraphicsimage.moc"
diff --git a/tests/auto/declarative/qmlgraphicsitem/data/keynavigation.qml b/tests/auto/declarative/qmlgraphicsitem/data/keynavigation.qml
new file mode 100644
index 0000000..9281a17
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsitem/data/keynavigation.qml
@@ -0,0 +1,39 @@
+import Qt 4.6
+
+Grid {
+ columns: 2
+ width: 100; height: 100
+ Rectangle {
+ id: item1
+ objectName: "item1"
+ focus: true
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.right: item2
+ KeyNavigation.down: item3
+ }
+ Rectangle {
+ id: item2
+ objectName: "item2"
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.left: item1
+ KeyNavigation.down: item4
+ }
+ Rectangle {
+ id: item3
+ objectName: "item3"
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.right: item4
+ KeyNavigation.up: item1
+ }
+ Rectangle {
+ id: item4
+ objectName: "item4"
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.left: item3
+ KeyNavigation.up: item2
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsitem/data/keys.qml b/tests/auto/declarative/qmlgraphicsitem/data/keys.qml
new file mode 100644
index 0000000..f3c1f7b
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsitem/data/keys.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Item {
+ focus: true
+ Keys.onPressed: keysTestObject.keyPress(event.key, event.text, event.modifiers)
+ Keys.onReleased: { keysTestObject.keyRelease(event.key, event.text, event.modifiers); event.accepted = true; }
+ Keys.onReturnPressed: keysTestObject.keyPress(event.key, "Return", event.modifiers)
+ Keys.onDigit0Pressed: keysTestObject.keyPress(event.key, event.text, event.modifiers)
+ Keys.onDigit9Pressed: { event.accepted = false; keysTestObject.keyPress(event.key, event.text, event.modifiers) }
+ Keys.forwardTo: [ item2 ]
+ Keys.enabled: enableKeyHanding
+
+ Item {
+ id: item2
+ Keys.onPressed: keysTestObject.forwardedKey(event.key)
+ Keys.onReleased: keysTestObject.forwardedKey(event.key)
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro b/tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro
new file mode 100644
index 0000000..ddabf9a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicsitem.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp b/tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp
new file mode 100644
index 0000000..c671dae
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlview.h>
+#include <qmlgraphicsitem.h>
+
+class tst_QmlGraphicsItem : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsItem();
+
+private slots:
+ void keys();
+ void keyNavigation();
+
+private:
+ template<typename T>
+ T *findItem(QmlGraphicsItem *parent, const QString &objectName);
+};
+
+class KeysTestObject : public QObject
+{
+ Q_OBJECT
+public:
+ KeysTestObject() : mKey(0), mModifiers(0), mForwardedKey(0) {}
+
+ void reset() {
+ mKey = 0;
+ mText = QString();
+ mModifiers = 0;
+ mForwardedKey = 0;
+ }
+
+public slots:
+ void keyPress(int key, QString text, int modifiers) {
+ mKey = key;
+ mText = text;
+ mModifiers = modifiers;
+ }
+ void keyRelease(int key, QString text, int modifiers) {
+ mKey = key;
+ mText = text;
+ mModifiers = modifiers;
+ }
+ void forwardedKey(int key) {
+ mForwardedKey = key;
+ }
+
+public:
+ int mKey;
+ QString mText;
+ int mModifiers;
+ int mForwardedKey;
+
+private:
+};
+
+
+tst_QmlGraphicsItem::tst_QmlGraphicsItem()
+{
+}
+
+void tst_QmlGraphicsItem::keys()
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ canvas->setUrl(QUrl::fromLocalFile(SRCDIR "/data/keys.qml"));
+
+ KeysTestObject *testObject = new KeysTestObject;
+ canvas->rootContext()->setContextProperty("keysTestObject", testObject);
+
+ canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
+
+ canvas->execute();
+ canvas->show();
+ qApp->processEvents();
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(!key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_Return));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
+ QCOMPARE(testObject->mText, QLatin1String("Return"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_0));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_0));
+ QCOMPARE(testObject->mText, QLatin1String("0"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_9));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_9));
+ QCOMPARE(testObject->mText, QLatin1String("9"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(!key.isAccepted());
+
+ testObject->reset();
+
+ canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(false));
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, 0);
+ QVERIFY(!key.isAccepted());
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QmlGraphicsItem::keyNavigation()
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ canvas->setUrl(QUrl::fromLocalFile(SRCDIR "/data/keynavigation.qml"));
+ canvas->execute();
+ canvas->show();
+ qApp->processEvents();
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(canvas->root(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // right
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item2");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // down
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // left
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item3");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // up
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+}
+
+template<typename T>
+T *tst_QmlGraphicsItem::findItem(QmlGraphicsItem *parent, const QString &objectName)
+{
+ if (!parent)
+ return 0;
+
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QGraphicsObject::children().count() << "children";
+ for (int i = 0; i < parent->QGraphicsObject::children().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->QGraphicsObject::children().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ return static_cast<T*>(item);
+ item = findItem<T>(item, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+
+
+QTEST_MAIN(tst_QmlGraphicsItem)
+
+#include "tst_qmlgraphicsitem.moc"
diff --git a/tests/auto/declarative/qmlgraphicslistview/data/itemlist.qml b/tests/auto/declarative/qmlgraphicslistview/data/itemlist.qml
new file mode 100644
index 0000000..e6b5c8f
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicslistview/data/itemlist.qml
@@ -0,0 +1,43 @@
+// This example demonstrates placing items in a view using
+// a VisualItemModel
+
+import Qt 4.6
+
+Rectangle {
+ color: "lightgray"
+ width: 240
+ height: 320
+
+ VisualItemModel {
+ id: itemModel
+ objectName: "itemModel"
+ Rectangle {
+ objectName: "item1"
+ height: view.height; width: view.width; color: "#FFFEF0"
+ Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ }
+ Rectangle {
+ objectName: "item2"
+ height: view.height; width: view.width; color: "#F0FFF7"
+ Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ }
+ Rectangle {
+ objectName: "item3"
+ height: view.height; width: view.width; color: "#F4F0FF"
+ Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ }
+ }
+
+ ListView {
+ id: view
+ objectName: "view"
+ anchors.fill: parent
+ anchors.bottomMargin: 30
+ model: itemModel
+ preferredHighlightBegin: 0
+ preferredHighlightEnd: 0
+ highlightRangeMode: "StrictlyEnforceRange"
+ orientation: ListView.Horizontal
+ flickDeceleration: 2000
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicslistview/data/listview-enforcerange.qml b/tests/auto/declarative/qmlgraphicslistview/data/listview-enforcerange.qml
new file mode 100644
index 0000000..46fddae
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicslistview/data/listview-enforcerange.qml
@@ -0,0 +1,55 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ Component {
+ id: myDelegate
+ Item {
+ id: wrapper
+ objectName: "wrapper"
+ height: 20
+ width: 240
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 120
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ }
+ }
+
+ Component {
+ id: myHighlight
+ Rectangle {
+ color: "lightsteelblue"
+ }
+ }
+
+ ListView {
+ id: list
+ objectName: "list"
+ width: 240
+ height: 320
+ model: testModel
+ delegate: myDelegate
+ highlight: myHighlight
+ preferredHighlightBegin: 100
+ preferredHighlightEnd: 100
+ highlightRangeMode: "StrictlyEnforceRange"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicslistview/data/listview-initCurrent.qml b/tests/auto/declarative/qmlgraphicslistview/data/listview-initCurrent.qml
new file mode 100644
index 0000000..74f5ef4
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicslistview/data/listview-initCurrent.qml
@@ -0,0 +1,50 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 20
+ width: 240
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 120
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ color: ListView.isCurrentItem ? "lightsteelblue" : "white"
+ }
+ }
+ ]
+ ListView {
+ id: list
+ objectName: "list"
+ focus: true
+ currentIndex: 3
+ width: 240
+ height: 320
+ keyNavigationWraps: testWrap
+ delegate: myDelegate
+ highlightMoveSpeed: 1000
+ model: testModel
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicslistview/data/listview-sections.qml b/tests/auto/declarative/qmlgraphicslistview/data/listview-sections.qml
new file mode 100644
index 0000000..4b5bea6
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicslistview/data/listview-sections.qml
@@ -0,0 +1,59 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Item {
+ id: wrapper
+ objectName: "wrapper"
+ height: ListView.prevSection != ListView.section ? 40 : 20;
+ width: 240
+ Rectangle {
+ y: wrapper.ListView.prevSection != wrapper.ListView.section ? 20 : 0
+ height: 20
+ width: parent.width
+ color: wrapper.ListView.isCurrentItem ? "lightsteelblue" : "white"
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 120
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ }
+ Rectangle {
+ color: "#99bb99"
+ height: wrapper.ListView.prevSection != wrapper.ListView.section ? 20 : 0
+ width: parent.width
+ visible: wrapper.ListView.prevSection != wrapper.ListView.section ? true : false
+ Text { text: wrapper.ListView.section }
+ }
+ }
+ }
+ ]
+ ListView {
+ id: list
+ objectName: "list"
+ width: 240
+ height: 320
+ model: testModel
+ delegate: myDelegate
+ section.property: "number"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicslistview/data/listview.qml b/tests/auto/declarative/qmlgraphicslistview/data/listview.qml
new file mode 100644
index 0000000..99b3db6
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicslistview/data/listview.qml
@@ -0,0 +1,119 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ function checkProperties() {
+ testObject.error = false;
+ if (list.model != testModel) {
+ console.log("model property incorrect");
+ testObject.error = true;
+ }
+ if (!testObject.animate && list.delegate != myDelegate) {
+ console.log("delegate property incorrect - expected myDelegate");
+ testObject.error = true;
+ }
+ if (testObject.animate && list.delegate != animatedDelegate) {
+ console.log("delegate property incorrect - expected animatedDelegate");
+ testObject.error = true;
+ }
+ if (testObject.invalidHighlight && list.highlight != invalidHl) {
+ console.log("highlight property incorrect - expected invalidHl");
+ testObject.error = true;
+ }
+ if (!testObject.invalidHighlight && list.highlight != myHighlight) {
+ console.log("highlight property incorrect - expected myHighlight");
+ testObject.error = true;
+ }
+ }
+ resources: [
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 20
+ width: 240
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 120
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ color: ListView.isCurrentItem ? "lightsteelblue" : "white"
+ }
+ },
+ Component {
+ id: animatedDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 20
+ width: 240
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 120
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ color: ListView.isCurrentItem ? "lightsteelblue" : "white"
+ ListView.onRemove: SequentialAnimation {
+ ScriptAction { script: console.log("Fix PropertyAction with attached properties") }
+/*
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true }
+ NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing: "easeInOutQuad" }
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+*/
+ }
+ }
+ },
+ Component {
+ id: myHighlight
+ Rectangle { color: "green" }
+ },
+ Component {
+ id: invalidHl
+ EaseFollow {}
+ }
+ ]
+ ListView {
+ id: list
+ objectName: "list"
+ focus: true
+ width: 240
+ height: 320
+ model: testModel
+ delegate: testObject.animate ? animatedDelegate : myDelegate
+ highlight: testObject.invalidHighlight ? invalidHl : myHighlight
+ highlightMoveSpeed: 1000
+ highlightResizeSpeed: 1000
+ cacheBuffer: testObject.cacheBuffer
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicslistview/qmlgraphicslistview.pro b/tests/auto/declarative/qmlgraphicslistview/qmlgraphicslistview.pro
new file mode 100644
index 0000000..f00de39
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicslistview/qmlgraphicslistview.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicslistview.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp b/tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp
new file mode 100644
index 0000000..6f97030
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp
@@ -0,0 +1,1378 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <private/qlistmodelinterface_p.h>
+#include <qmlview.h>
+#include <private/qmlgraphicslistview_p.h>
+#include <private/qmlgraphicstext_p.h>
+#include <private/qmlgraphicsvisualitemmodel_p.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+
+class tst_QmlGraphicsListView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsListView();
+
+private slots:
+ // Test both QListModelInterface and QAbstractItemModel model types
+ void qListModelInterface_items();
+ void qAbstractItemModel_items();
+
+ void qListModelInterface_changed();
+ void qAbstractItemModel_changed();
+
+ void qListModelInterface_inserted();
+ void qAbstractItemModel_inserted();
+
+ void qListModelInterface_removed();
+ void qAbstractItemModel_removed();
+
+ void qListModelInterface_moved();
+ void qAbstractItemModel_moved();
+
+ void qListModelInterface_clear();
+ void qAbstractItemModel_clear();
+
+ void itemList();
+ void currentIndex();
+ void enforceRange();
+ void spacing();
+ void sections();
+ void cacheBuffer();
+ void positionViewAtIndex();
+
+private:
+ template <class T> void items();
+ template <class T> void changed();
+ template <class T> void inserted();
+ template <class T> void removed(bool animated);
+ template <class T> void moved();
+ template <class T> void clear();
+ QmlView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QmlGraphicsItem *parent, const QString &id, int index=-1);
+ template<typename T>
+ QList<T*> findItems(QmlGraphicsItem *parent, const QString &objectName);
+ void dumpTree(QmlGraphicsItem *parent, int depth = 0);
+};
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool error READ error WRITE setError NOTIFY changedError)
+ Q_PROPERTY(bool animate READ animate NOTIFY changedAnim)
+ Q_PROPERTY(bool invalidHighlight READ invalidHighlight NOTIFY changedHl)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer NOTIFY changedCacheBuffer)
+
+public:
+ TestObject(QObject *parent = 0)
+ : QObject(parent), mError(true), mAnimate(false), mInvalidHighlight(false)
+ , mCacheBuffer(0) {}
+
+ bool error() const { return mError; }
+ void setError(bool err) { mError = err; emit changedError(); }
+
+ bool animate() const { return mAnimate; }
+ void setAnimate(bool anim) { mAnimate = anim; emit changedAnim(); }
+
+ bool invalidHighlight() const { return mInvalidHighlight; }
+ void setInvalidHighlight(bool invalid) { mInvalidHighlight = invalid; emit changedHl(); }
+
+ int cacheBuffer() const { return mCacheBuffer; }
+ void setCacheBuffer(int buffer) { mCacheBuffer = buffer; emit changedCacheBuffer(); }
+
+signals:
+ void changedError();
+ void changedAnim();
+ void changedHl();
+ void changedCacheBuffer();
+
+public:
+ bool mError;
+ bool mAnimate;
+ bool mInvalidHighlight;
+ int mCacheBuffer;
+};
+
+class TestModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
+ ~TestModel() {}
+
+ enum Roles { Name, Number };
+
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ int count() const { return list.count(); }
+
+ QList<int> roles() const { return QList<int>() << Name << Number; }
+ QString toString(int role) const {
+ switch(role) {
+ case Name:
+ return "name";
+ case Number:
+ return "number";
+ default:
+ return "";
+ }
+ }
+
+ QVariant data(int index, int role) const
+ {
+ if (role==0)
+ return list.at(index).first;
+ if (role==1)
+ return list.at(index).second;
+ return QVariant();
+ }
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const {
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case Name:
+ info = list.at(index).first;
+ break;
+ case Number:
+ info = list.at(index).second;
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+ }
+
+ void addItem(const QString &name, const QString &number) {
+ list.append(QPair<QString,QString>(name, number));
+ emit itemsInserted(list.count()-1, 1);
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit itemsInserted(index, 1);
+ }
+
+ void removeItem(int index) {
+ list.removeAt(index);
+ emit itemsRemoved(index, 1);
+ }
+
+ void moveItem(int from, int to) {
+ list.move(from, to);
+ emit itemsMoved(from, to, 1);
+ }
+
+ void modifyItem(int index, const QString &name, const QString &number) {
+ list[index] = QPair<QString,QString>(name, number);
+ emit itemsChanged(index, 1, roles());
+ }
+
+ void clear() {
+ int count = list.count();
+ list.clear();
+ emit itemsRemoved(0, count);
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+class TestModel2 : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel2(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ emit endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+ void clear() {
+ int count = list.count();
+ emit beginRemoveRows(QModelIndex(), 0, count-1);
+ list.clear();
+ emit endRemoveRows();
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QmlGraphicsListView::tst_QmlGraphicsListView()
+{
+}
+
+template <class T>
+void tst_QmlGraphicsListView::items()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ QVERIFY(listview->highlightItem() != 0);
+ QCOMPARE(listview->count(), model.count());
+ QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ // current item should be first item
+ QCOMPARE(listview->currentItem(), findItem<QmlGraphicsItem>(viewport, "wrapper", 0));
+
+ for (int i = 0; i < model.count(); ++i) {
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ // switch to other delegate
+ testObject->setAnimate(true);
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+ QVERIFY(listview->currentItem());
+
+ // set invalid highlight
+ testObject->setInvalidHighlight(true);
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+ QVERIFY(listview->currentItem());
+ QVERIFY(listview->highlightItem() == 0);
+
+ // back to normal highlight
+ testObject->setInvalidHighlight(false);
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+ QVERIFY(listview->currentItem());
+ QVERIFY(listview->highlightItem() != 0);
+
+ // set an empty model and confirm that items are destroyed
+ T model2;
+ ctxt->setContextProperty("testModel", &model2);
+
+ // Allow deleteLaters to process
+ QTest::qWait(500);
+
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ QVERIFY(itemCount == 0);
+
+ QCOMPARE(listview->highlightResizeSpeed(), 1000.0);
+ QCOMPARE(listview->highlightMoveSpeed(), 1000.0);
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QmlGraphicsListView::changed()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsFlickable *listview = findItem<QmlGraphicsFlickable>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.modifyItem(1, "Will", "9876");
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QmlGraphicsListView::inserted()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.insertItem(1, "Will", "9876");
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(), i*20.0);
+ }
+
+ model.insertItem(0, "Foo", "1111"); // zero index, and current item
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ name = findItem<QmlGraphicsText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ QCOMPARE(listview->currentIndex(), 1);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(), i*20.0);
+ }
+
+ for (int i = model.count(); i < 30; ++i)
+ model.insertItem(i, "Hello", QString::number(i));
+ QTest::qWait(500);
+
+ listview->setViewportY(80);
+ QTest::qWait(500);
+
+ // Insert item outside visible area
+ model.insertItem(1, "Hello", "1324");
+ QTest::qWait(500);
+
+ QVERIFY(listview->viewportY() == 80);
+
+ // Confirm items positioned correctly
+ for (int i = 5; i < 5+15; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.0 - 20.0);
+ }
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QmlGraphicsListView::removed(bool animated)
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ testObject->setAnimate(animated);
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.removeItem(1);
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->y() == i*20);
+ }
+
+ // Remove first item (which is the current item);
+ model.removeItem(0); // post: top item starts at 20
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ name = findItem<QmlGraphicsText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(),i*20.0 + 20.0);
+ }
+
+ // Remove items not visible
+ model.removeItem(18);
+ // let transitions settle.
+ QTest::qWait(500);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(),i*20.0+20.0);
+ }
+
+ // Remove items before visible
+ listview->setViewportY(80);
+ listview->setCurrentIndex(10);
+
+ model.removeItem(1); // post: top item will be at 40
+ // let transitions settle.
+ QTest::qWait(500);
+
+ // Confirm items positioned correctly
+ for (int i = 2; i < 18; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(),40+i*20.0);
+ }
+
+ // Remove current index
+ QVERIFY(listview->currentIndex() == 9);
+ QmlGraphicsItem *oldCurrent = listview->currentItem();
+ model.removeItem(9);
+ QTest::qWait(500);
+
+ QCOMPARE(listview->currentIndex(), 9);
+ QVERIFY(listview->currentItem() != oldCurrent);
+
+ listview->setViewportY(40); // That's the top now
+ // let transitions settle.
+ QTest::qWait(500);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(),40+i*20.0);
+ }
+
+ // remove current item beyond visible items.
+ listview->setCurrentIndex(20);
+ QTest::qWait(500);
+ listview->setViewportY(40);
+ model.removeItem(20);
+ QTest::qWait(500);
+
+ QCOMPARE(listview->currentIndex(), 20);
+ QVERIFY(listview->currentItem() != 0);
+
+ // remove item before current, but visible
+ listview->setCurrentIndex(8);
+ QTest::qWait(500);
+ oldCurrent = listview->currentItem();
+ model.removeItem(6);
+ QTest::qWait(500);
+
+ QCOMPARE(listview->currentIndex(), 7);
+ QVERIFY(listview->currentItem() == oldCurrent);
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QmlGraphicsListView::clear()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.clear();
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ QVERIFY(listview->count() == 0);
+ QVERIFY(listview->currentItem() == 0);
+ QVERIFY(listview->viewportY() == 0);
+
+ delete canvas;
+}
+
+
+template <class T>
+void tst_QmlGraphicsListView::moved()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.moveItem(1, 4);
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ name = findItem<QmlGraphicsText>(viewport, "textName", 4);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(4));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", 4);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(4));
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->y() == i*20);
+ }
+
+ listview->setViewportY(80);
+
+ // move outside visible area
+ model.moveItem(1, 18);
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ // Confirm items positioned correctly and indexes correct
+ for (int i = 3; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.0 + 20);
+ name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ // move from outside visible into visible
+ model.moveItem(20, 4);
+
+ // let transitions settle.
+ QTest::qWait(500);
+
+ // Confirm items positioned correctly and indexes correct
+ for (int i = 3; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.0 + 20);
+ name = findItem<QmlGraphicsText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ number = findItem<QmlGraphicsText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::enforceRange()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview-enforcerange.qml");
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QCOMPARE(listview->preferredHighlightBegin(), 100.0);
+ QCOMPARE(listview->preferredHighlightEnd(), 100.0);
+ QCOMPARE(listview->highlightRangeMode(), QmlGraphicsListView::StrictlyEnforceRange);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ // view should be positioned at the top of the range.
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(listview->viewportY(), -100.0);
+
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ // Check currentIndex is updated when viewport moves
+ listview->setViewportY(20);
+ QTest::qWait(500);
+
+ QCOMPARE(listview->currentIndex(), 6);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::spacing()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->y() == i*20);
+ }
+
+ listview->setSpacing(10);
+ QVERIFY(listview->spacing() == 10);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->y() == i*30);
+ }
+
+ listview->setSpacing(0);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.0);
+ }
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::sections()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview-sections.qml");
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i/5));
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ QVERIFY(item);
+ QCOMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20));
+ }
+
+ // Remove section boundary
+ model.removeItem(5);
+
+ // New section header created
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", 5);
+ QVERIFY(item);
+ QCOMPARE(item->height(), 40.0);
+
+ model.insertItem(3, "New Item", "0");
+
+ // Section header moved
+ item = findItem<QmlGraphicsItem>(viewport, "wrapper", 5);
+ QVERIFY(item);
+ QCOMPARE(item->height(), 20.0);
+
+ item = findItem<QmlGraphicsItem>(viewport, "wrapper", 6);
+ QVERIFY(item);
+ QCOMPARE(item->height(), 40.0);
+
+ // insert item which will become a section header
+ model.insertItem(6, "Replace header", "1");
+
+ item = findItem<QmlGraphicsItem>(viewport, "wrapper", 6);
+ QVERIFY(item);
+ QCOMPARE(item->height(), 40.0);
+
+ item = findItem<QmlGraphicsItem>(viewport, "wrapper", 7);
+ QVERIFY(item);
+ QCOMPARE(item->height(), 20.0);
+
+ QCOMPARE(listview->currentSection(), QString("0"));
+
+ listview->setViewportY(140);
+ QCOMPARE(listview->currentSection(), QString("1"));
+
+ listview->setViewportY(20);
+ QCOMPARE(listview->currentSection(), QString("0"));
+
+ item = findItem<QmlGraphicsItem>(viewport, "wrapper", 1);
+ QVERIFY(item);
+ QCOMPARE(item->height(), 20.0);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::currentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testWrap", QVariant(false));
+
+ QString filename(SRCDIR "/data/listview-initCurrent.qml");
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ QTest::qWait(500);
+
+ // current item should be third item
+ QCOMPARE(listview->currentIndex(), 3);
+ QCOMPARE(listview->currentItem(), findItem<QmlGraphicsItem>(viewport, "wrapper", 3));
+ QCOMPARE(listview->highlightItem()->y(), listview->currentItem()->y());
+
+ // no wrap
+ listview->setCurrentIndex(0);
+ QCOMPARE(listview->currentIndex(), 0);
+
+ listview->incrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 1);
+ listview->decrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 0);
+
+ listview->decrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 0);
+
+ // with wrap
+ ctxt->setContextProperty("testWrap", QVariant(true));
+ QVERIFY(listview->isWrapEnabled());
+
+ listview->decrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), model.count()-1);
+
+ QTest::qWait(1000);
+ QCOMPARE(listview->viewportY(), 279.0);
+
+ listview->incrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 0);
+
+ QTest::qWait(1000);
+ QCOMPARE(listview->viewportY(), 0.0);
+
+ // Test keys
+ canvas->show();
+ qApp->processEvents();
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(listview->currentIndex(), 1);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(listview->currentIndex(), 0);
+
+ // turn off auto highlight
+ listview->setHighlightFollowsCurrentItem(false);
+ QVERIFY(listview->highlightFollowsCurrentItem() == false);
+
+ QTest::qWait(500);
+ QVERIFY(listview->highlightItem());
+ qreal hlPos = listview->highlightItem()->y();
+
+ listview->setCurrentIndex(4);
+ QTest::qWait(500);
+ QCOMPARE(listview->highlightItem()->y(), hlPos);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::itemList()
+{
+ QmlView *canvas = createView(SRCDIR "/data/itemlist.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "view");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ QmlGraphicsVisualItemModel *model = canvas->root()->findChild<QmlGraphicsVisualItemModel*>("itemModel");
+ QVERIFY(model != 0);
+
+ QVERIFY(model->count() == 3);
+ QCOMPARE(listview->currentIndex(), 0);
+
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "item1");
+ QVERIFY(item);
+ QCOMPARE(item->x(), 0.0);
+
+ QmlGraphicsText *text = findItem<QmlGraphicsText>(viewport, "text1");
+ QVERIFY(text);
+ QCOMPARE(text->text(), QLatin1String("index: 0"));
+
+ listview->setCurrentIndex(2);
+ QTest::qWait(1000);
+
+ item = findItem<QmlGraphicsItem>(viewport, "item3");
+ QVERIFY(item);
+ QCOMPARE(item->x(), 480.0);
+
+ text = findItem<QmlGraphicsText>(viewport, "text3");
+ QVERIFY(text);
+ QCOMPARE(text->text(), QLatin1String("index: 2"));
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::cacheBuffer()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+ QVERIFY(listview->delegate() != 0);
+ QVERIFY(listview->model() != 0);
+ QVERIFY(listview->highlight() != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->y() == i*20);
+ }
+
+ testObject->setCacheBuffer(400);
+ QVERIFY(listview->cacheBuffer() == 400);
+
+ int newItemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ QVERIFY(newItemCount > itemCount);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < newItemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->y() == i*20);
+ }
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::positionViewAtIndex()
+{
+ QmlView *canvas = createView(SRCDIR "/data/listview.qml");
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsListView *listview = findItem<QmlGraphicsListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QmlGraphicsItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.);
+ }
+
+ // Position on a currently visible item
+ listview->positionViewAtIndex(3);
+ QCOMPARE(listview->viewportY(), 60.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.);
+ }
+
+ // Position on an item beyond the visible items
+ listview->positionViewAtIndex(22);
+ QCOMPARE(listview->viewportY(), 440.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.);
+ }
+
+ // Position on an item that would leave empty space if positioned at the top
+ listview->positionViewAtIndex(28);
+ QCOMPARE(listview->viewportY(), 480.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.);
+ }
+
+ // Position at the beginning again
+ listview->positionViewAtIndex(0);
+ QCOMPARE(listview->viewportY(), 0.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QmlGraphicsItem>(viewport, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(viewport, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->y(), i*20.);
+ }
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsListView::qListModelInterface_items()
+{
+ items<TestModel>();
+}
+
+void tst_QmlGraphicsListView::qAbstractItemModel_items()
+{
+ items<TestModel2>();
+}
+
+void tst_QmlGraphicsListView::qListModelInterface_changed()
+{
+ changed<TestModel>();
+}
+
+void tst_QmlGraphicsListView::qAbstractItemModel_changed()
+{
+ changed<TestModel2>();
+}
+
+void tst_QmlGraphicsListView::qListModelInterface_inserted()
+{
+ inserted<TestModel>();
+}
+
+void tst_QmlGraphicsListView::qAbstractItemModel_inserted()
+{
+ inserted<TestModel2>();
+}
+
+void tst_QmlGraphicsListView::qListModelInterface_removed()
+{
+ removed<TestModel>(false);
+ removed<TestModel>(true);
+}
+
+void tst_QmlGraphicsListView::qAbstractItemModel_removed()
+{
+ removed<TestModel2>(false);
+ removed<TestModel2>(true);
+}
+
+void tst_QmlGraphicsListView::qListModelInterface_moved()
+{
+ moved<TestModel>();
+}
+
+void tst_QmlGraphicsListView::qAbstractItemModel_moved()
+{
+ moved<TestModel2>();
+}
+
+void tst_QmlGraphicsListView::qListModelInterface_clear()
+{
+ clear<TestModel>();
+}
+
+void tst_QmlGraphicsListView::qAbstractItemModel_clear()
+{
+ clear<TestModel2>();
+}
+
+QmlView *tst_QmlGraphicsListView::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QmlGraphicsListView::findItem(QmlGraphicsItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QGraphicsObject::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QmlExpression e(qmlContext(item), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+template<typename T>
+QList<T*> tst_QmlGraphicsListView::findItems(QmlGraphicsItem *parent, const QString &objectName)
+{
+ QList<T*> items;
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QGraphicsObject::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ items.append(static_cast<T*>(item));
+ items += findItems<T>(item, objectName);
+ }
+
+ return items;
+}
+
+void tst_QmlGraphicsListView::dumpTree(QmlGraphicsItem *parent, int depth)
+{
+ static QString padding(" ");
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ qDebug() << padding.left(depth*2) << item;
+ dumpTree(item, depth+1);
+ }
+}
+
+
+QTEST_MAIN(tst_QmlGraphicsListView)
+
+#include "tst_qmlgraphicslistview.moc"
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/GraphicsWidget250x250.qml b/tests/auto/declarative/qmlgraphicsloader/data/GraphicsWidget250x250.qml
new file mode 100644
index 0000000..627c7df
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/GraphicsWidget250x250.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QGraphicsWidget {
+ size: "250x250"
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/NoResize.qml b/tests/auto/declarative/qmlgraphicsloader/data/NoResize.qml
new file mode 100644
index 0000000..cfbb55a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/NoResize.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+Loader {
+ resizeMode: "NoResize"
+ width: 200; height: 80
+ source: "Rect120x60.qml"
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/NoResizeGraphicsWidget.qml b/tests/auto/declarative/qmlgraphicsloader/data/NoResizeGraphicsWidget.qml
new file mode 100644
index 0000000..0704e18
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/NoResizeGraphicsWidget.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Loader {
+ resizeMode: Loader.NoResize
+ source: "GraphicsWidget250x250.qml"
+ width: 200
+ height: 80
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/Rect120x60.qml b/tests/auto/declarative/qmlgraphicsloader/data/Rect120x60.qml
new file mode 100644
index 0000000..aa4b0c2
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/Rect120x60.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Rectangle {
+ width: 120
+ height:60
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/SetSourceComponent.qml b/tests/auto/declarative/qmlgraphicsloader/data/SetSourceComponent.qml
new file mode 100644
index 0000000..1db56c4
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/SetSourceComponent.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Item {
+ Component { id: comp; Rectangle { width: 100; height: 50 } }
+ Loader { sourceComponent: comp }
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/SizeGraphicsWidgetToLoader.qml b/tests/auto/declarative/qmlgraphicsloader/data/SizeGraphicsWidgetToLoader.qml
new file mode 100644
index 0000000..97c72f4
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/SizeGraphicsWidgetToLoader.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Loader {
+ resizeMode: Loader.SizeItemToLoader
+ width: 200
+ height: 80
+ source: "GraphicsWidget250x250.qml"
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/SizeLoaderToGraphicsWidget.qml b/tests/auto/declarative/qmlgraphicsloader/data/SizeLoaderToGraphicsWidget.qml
new file mode 100644
index 0000000..cb72f05
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/SizeLoaderToGraphicsWidget.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Loader {
+ resizeMode: Loader.SizeLoaderToItem
+ source: "GraphicsWidget250x250.qml"
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/SizeToItem.qml b/tests/auto/declarative/qmlgraphicsloader/data/SizeToItem.qml
new file mode 100644
index 0000000..b52fa03
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/SizeToItem.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Loader {
+ resizeMode: "SizeLoaderToItem"
+ source: "Rect120x60.qml"
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/data/SizeToLoader.qml b/tests/auto/declarative/qmlgraphicsloader/data/SizeToLoader.qml
new file mode 100644
index 0000000..1a107e1
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/data/SizeToLoader.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+Loader {
+ resizeMode: "SizeItemToLoader"
+ width: 200; height: 80
+ source: "Rect120x60.qml"
+}
diff --git a/tests/auto/declarative/qmlgraphicsloader/qmlgraphicsloader.pro b/tests/auto/declarative/qmlgraphicsloader/qmlgraphicsloader.pro
new file mode 100644
index 0000000..4837075
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/qmlgraphicsloader.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui network
+macx:CONFIG -= app_bundle
+
+INCLUDEPATH += ../shared/
+HEADERS += ../shared/testhttpserver.h
+SOURCES += tst_qmlgraphicsloader.cpp \
+ ../shared/testhttpserver.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
diff --git a/tests/auto/declarative/qmlgraphicsloader/tst_qmlgraphicsloader.cpp b/tests/auto/declarative/qmlgraphicsloader/tst_qmlgraphicsloader.cpp
new file mode 100644
index 0000000..43f58c1
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsloader/tst_qmlgraphicsloader.cpp
@@ -0,0 +1,456 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtGui/QGraphicsWidget>
+#include <QtGui/QGraphicsScene>
+
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicsloader_p.h>
+#include "testhttpserver.h"
+
+#define SERVER_PORT 14445
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
+}
+
+#define TRY_WAIT(expr) \
+ do { \
+ for (int ii = 0; ii < 6; ++ii) { \
+ if ((expr)) break; \
+ QTest::qWait(50); \
+ } \
+ QVERIFY((expr)); \
+ } while (false)
+
+class tst_QmlGraphicsLoader : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsLoader();
+
+private slots:
+ void url();
+ void invalidUrl();
+ void component();
+ void clear();
+ void urlToComponent();
+ void componentToUrl();
+ void sizeLoaderToItem();
+ void sizeItemToLoader();
+ void noResize();
+ void sizeLoaderToGraphicsWidget();
+ void sizeGraphicsWidgetToLoader();
+ void noResizeGraphicsWidget();
+ void networkRequestUrl();
+ void failNetworkRequest();
+// void networkComponent();
+
+private:
+ QmlEngine engine;
+};
+
+
+tst_QmlGraphicsLoader::tst_QmlGraphicsLoader()
+{
+}
+
+void tst_QmlGraphicsLoader::url()
+{
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nLoader { source: \"Rect120x60.qml\" }"), TEST_FILE(""));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QVERIFY(loader->item());
+ QVERIFY(loader->source() == QUrl::fromLocalFile(SRCDIR "/data/Rect120x60.qml"));
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QmlGraphicsLoader::Ready);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+
+ delete loader;
+}
+
+void tst_QmlGraphicsLoader::component()
+{
+ QmlComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(component.create());
+ QVERIFY(item);
+
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(item->QGraphicsObject::children().at(1));
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QmlGraphicsLoader::Ready);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+
+ delete loader;
+}
+
+void tst_QmlGraphicsLoader::invalidUrl()
+{
+ QTest::ignoreMessage(QtWarningMsg, QString("(:-1: File error for URL " + QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml").toString() + ") ").toUtf8().constData());
+
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nLoader { source: \"IDontExist.qml\" }"), TEST_FILE(""));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QmlGraphicsLoader::Error);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 0);
+
+ delete loader;
+}
+
+void tst_QmlGraphicsLoader::clear()
+{
+ {
+ QmlComponent component(&engine);
+ component.setData(QByteArray(
+ "import Qt 4.6\n"
+ " Loader { id: loader\n"
+ " source: 'Rect120x60.qml'\n"
+ " Timer { interval: 200; running: true; onTriggered: loader.source = '' }\n"
+ " }")
+ , TEST_FILE(""));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+
+ QTest::qWait(500);
+
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(loader->status(), QmlGraphicsLoader::Null);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 0);
+
+ delete loader;
+ }
+ {
+ QmlComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(component.create());
+ QVERIFY(item);
+
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(item->QGraphicsObject::children().at(1));
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+
+ loader->setSourceComponent(0);
+
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(loader->status(), QmlGraphicsLoader::Null);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 0);
+
+ delete loader;
+ }
+}
+
+void tst_QmlGraphicsLoader::urlToComponent()
+{
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\n"
+ "Loader {\n"
+ " id: loader\n"
+ " Component { id: myComp; Rectangle { width: 10; height: 10 } }\n"
+ " source: \"Rect120x60.qml\"\n"
+ " Timer { interval: 100; running: true; onTriggered: loader.sourceComponent = myComp }\n"
+ "}" )
+ , TEST_FILE(""));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QTest::qWait(500);
+ QVERIFY(loader != 0);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+ QCOMPARE(loader->width(), 10.0);
+ QCOMPARE(loader->height(), 10.0);
+
+ delete loader;
+}
+
+void tst_QmlGraphicsLoader::componentToUrl()
+{
+ QmlComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(component.create());
+ QVERIFY(item);
+
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(item->QGraphicsObject::children().at(1));
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+
+ loader->setSource(TEST_FILE("/Rect120x60.qml"));
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+ QCOMPARE(loader->width(), 120.0);
+ QCOMPARE(loader->height(), 60.0);
+
+ delete loader;
+}
+
+void tst_QmlGraphicsLoader::sizeLoaderToItem()
+{
+ QmlComponent component(&engine, TEST_FILE("/SizeToItem.qml"));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QVERIFY(loader->resizeMode() == QmlGraphicsLoader::SizeLoaderToItem);
+ QCOMPARE(loader->width(), 120.0);
+ QCOMPARE(loader->height(), 60.0);
+
+ // Check resize
+ QmlGraphicsItem *rect = qobject_cast<QmlGraphicsItem*>(loader->item());
+ QVERIFY(rect);
+ rect->setWidth(150);
+ rect->setHeight(45);
+ QCOMPARE(loader->width(), 150.0);
+ QCOMPARE(loader->height(), 45.0);
+
+ // Switch mode
+ loader->setResizeMode(QmlGraphicsLoader::SizeItemToLoader);
+ loader->setWidth(180);
+ loader->setHeight(30);
+ QCOMPARE(rect->width(), 180.0);
+ QCOMPARE(rect->height(), 30.0);
+}
+
+void tst_QmlGraphicsLoader::sizeItemToLoader()
+{
+ QmlComponent component(&engine, TEST_FILE("/SizeToLoader.qml"));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QVERIFY(loader->resizeMode() == QmlGraphicsLoader::SizeItemToLoader);
+ QCOMPARE(loader->width(), 200.0);
+ QCOMPARE(loader->height(), 80.0);
+
+ QmlGraphicsItem *rect = qobject_cast<QmlGraphicsItem*>(loader->item());
+ QVERIFY(rect);
+ QCOMPARE(rect->width(), 200.0);
+ QCOMPARE(rect->height(), 80.0);
+
+ // Check resize
+ loader->setWidth(180);
+ loader->setHeight(30);
+ QCOMPARE(rect->width(), 180.0);
+ QCOMPARE(rect->height(), 30.0);
+
+ // Switch mode
+ loader->setResizeMode(QmlGraphicsLoader::SizeLoaderToItem);
+ rect->setWidth(160);
+ rect->setHeight(45);
+ QCOMPARE(loader->width(), 160.0);
+ QCOMPARE(loader->height(), 45.0);
+}
+
+void tst_QmlGraphicsLoader::noResize()
+{
+ QmlComponent component(&engine, TEST_FILE("/NoResize.qml"));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QCOMPARE(loader->width(), 200.0);
+ QCOMPARE(loader->height(), 80.0);
+
+ QmlGraphicsItem *rect = qobject_cast<QmlGraphicsItem*>(loader->item());
+ QVERIFY(rect);
+ QCOMPARE(rect->width(), 120.0);
+ QCOMPARE(rect->height(), 60.0);
+}
+
+void tst_QmlGraphicsLoader::sizeLoaderToGraphicsWidget()
+{
+ QmlComponent component(&engine, TEST_FILE("/SizeLoaderToGraphicsWidget.qml"));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QGraphicsScene scene;
+ scene.addItem(loader);
+
+ QVERIFY(loader != 0);
+ QVERIFY(loader->resizeMode() == QmlGraphicsLoader::SizeLoaderToItem);
+ QCOMPARE(loader->width(), 250.0);
+ QCOMPARE(loader->height(), 250.0);
+
+ // Check resize
+ QGraphicsWidget *widget = qobject_cast<QGraphicsWidget*>(loader->item());
+ QVERIFY(widget);
+ widget->resize(QSizeF(150,45));
+ QCOMPARE(loader->width(), 150.0);
+ QCOMPARE(loader->height(), 45.0);
+
+ // Switch mode
+ loader->setResizeMode(QmlGraphicsLoader::SizeItemToLoader);
+ loader->setWidth(180);
+ loader->setHeight(30);
+ QCOMPARE(widget->size().width(), 180.0);
+ QCOMPARE(widget->size().height(), 30.0);
+}
+
+void tst_QmlGraphicsLoader::sizeGraphicsWidgetToLoader()
+{
+ QmlComponent component(&engine, TEST_FILE("/SizeGraphicsWidgetToLoader.qml"));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QGraphicsScene scene;
+ scene.addItem(loader);
+
+ QVERIFY(loader != 0);
+ QVERIFY(loader->resizeMode() == QmlGraphicsLoader::SizeItemToLoader);
+ QCOMPARE(loader->width(), 200.0);
+ QCOMPARE(loader->height(), 80.0);
+
+ QGraphicsWidget *widget = qobject_cast<QGraphicsWidget*>(loader->item());
+ QVERIFY(widget);
+ QCOMPARE(widget->size().width(), 200.0);
+ QCOMPARE(widget->size().height(), 80.0);
+
+ // Check resize
+ loader->setWidth(180);
+ loader->setHeight(30);
+ QCOMPARE(widget->size().width(), 180.0);
+ QCOMPARE(widget->size().height(), 30.0);
+
+ // Switch mode
+ loader->setResizeMode(QmlGraphicsLoader::SizeLoaderToItem);
+ widget->resize(QSizeF(160,45));
+ QCOMPARE(loader->width(), 160.0);
+ QCOMPARE(loader->height(), 45.0);
+}
+
+void tst_QmlGraphicsLoader::noResizeGraphicsWidget()
+{
+ QmlComponent component(&engine, TEST_FILE("/NoResizeGraphicsWidget.qml"));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QGraphicsScene scene;
+ scene.addItem(loader);
+
+ QVERIFY(loader != 0);
+ QCOMPARE(loader->width(), 200.0);
+ QCOMPARE(loader->height(), 80.0);
+
+ QGraphicsWidget *widget = qobject_cast<QGraphicsWidget*>(loader->item());
+ QVERIFY(widget);
+ QCOMPARE(widget->size().width(), 250.0);
+ QCOMPARE(widget->size().height(), 250.0);
+}
+
+void tst_QmlGraphicsLoader::networkRequestUrl()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory("data");
+
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nLoader { source: \"http://127.0.0.1:14445/Rect120x60.qml\" }"), TEST_FILE(""));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+
+ TRY_WAIT(loader->status() == QmlGraphicsLoader::Ready);
+
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+
+ delete loader;
+}
+
+/* XXX Component waits until all dependencies are loaded. Is this actually possible?
+void tst_QmlGraphicsLoader::networkComponent()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory("slowdata", TestHTTPServer::Delay);
+
+ QmlComponent component(&engine);
+ component.setData(QByteArray(
+ "import Qt 4.6\n"
+ "import \"http://127.0.0.1:14445/\" as NW\n"
+ "Item {\n"
+ " Component { id: comp; NW.SlowRect {} }\n"
+ " Loader { sourceComponent: comp } }")
+ , TEST_FILE(""));
+
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(component.create());
+ QVERIFY(item);
+
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(item->QGraphicsObject::children().at(1));
+ QVERIFY(loader);
+ TRY_WAIT(loader->status() == QmlGraphicsLoader::Ready);
+
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QmlGraphicsLoader::Ready);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1);
+
+ delete loader;
+}
+*/
+
+void tst_QmlGraphicsLoader::failNetworkRequest()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory("data");
+
+ QTest::ignoreMessage(QtWarningMsg, "(:-1: Network error for URL http://127.0.0.1:14445/IDontExist.qml) ");
+
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nLoader { source: \"http://127.0.0.1:14445/IDontExist.qml\" }"), TEST_FILE(""));
+ QmlGraphicsLoader *loader = qobject_cast<QmlGraphicsLoader*>(component.create());
+ QVERIFY(loader != 0);
+
+ TRY_WAIT(loader->status() == QmlGraphicsLoader::Error);
+
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 0);
+
+ delete loader;
+}
+
+QTEST_MAIN(tst_QmlGraphicsLoader)
+
+#include "tst_qmlgraphicsloader.moc"
diff --git a/tests/auto/declarative/qmlgraphicsparticles/data/particle.png b/tests/auto/declarative/qmlgraphicsparticles/data/particle.png
new file mode 100644
index 0000000..defbde5
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsparticles/data/particle.png
Binary files differ
diff --git a/tests/auto/declarative/qmlgraphicsparticles/data/particles.qml b/tests/auto/declarative/qmlgraphicsparticles/data/particles.qml
new file mode 100644
index 0000000..c58927e
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsparticles/data/particles.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+Rectangle{
+ width: 100
+ height: 100
+ color: "black"
+ objectName: "rect"
+ Particles { id: particles
+ objectName: "particles"
+ width:1; height:1; anchors.centerIn: parent; opacity: 1
+ lifeSpan: 100; lifeSpanDeviation: 20; count:1000;
+ fadeInDuration: 20; fadeOutDuration: 20; count: -1; emissionRate: 1000
+ angle: 0; angleDeviation: 360; velocity: 500; velocityDeviation:30
+ source: "particle.png"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsparticles/qmlgraphicsparticles.pro b/tests/auto/declarative/qmlgraphicsparticles/qmlgraphicsparticles.pro
new file mode 100644
index 0000000..94eeb4e
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsparticles/qmlgraphicsparticles.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicsparticles.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsparticles/tst_qmlgraphicsparticles.cpp b/tests/auto/declarative/qmlgraphicsparticles/tst_qmlgraphicsparticles.cpp
new file mode 100644
index 0000000..5458d68
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsparticles/tst_qmlgraphicsparticles.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <qmlview.h>
+#include <private/qmlgraphicsparticles_p.h>
+
+class tst_QmlGraphicsParticles : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsParticles();
+
+private slots:
+ void properties();
+ void runs();
+private:
+ QmlView *createView(const QString &filename);
+
+};
+
+tst_QmlGraphicsParticles::tst_QmlGraphicsParticles()
+{
+}
+
+void tst_QmlGraphicsParticles::properties()
+{
+ QmlView *canvas = createView(SRCDIR "/data/particles.qml");
+ QVERIFY(canvas->root());
+ QmlGraphicsParticles* particles = canvas->root()->findChild<QmlGraphicsParticles*>("particles");
+ QVERIFY(particles);
+
+ particles->setSource(QUrl::fromLocalFile(SRCDIR "/data/particle.png"));
+ QCOMPARE(particles->source(), QUrl::fromLocalFile(SRCDIR "/data/particle.png"));
+
+ particles->setLifeSpanDeviation(1000);
+ QCOMPARE(particles->lifeSpanDeviation(), 1000);
+
+ particles->setFadeInDuration(1000);
+ QCOMPARE(particles->fadeInDuration(), 1000);
+
+ particles->setFadeOutDuration(1000);
+ QCOMPARE(particles->fadeOutDuration(), 1000);
+
+ particles->setAngle(100.0);
+ QCOMPARE(particles->angle(), 100.0);
+
+ particles->setAngleDeviation(100.0);
+ QCOMPARE(particles->angleDeviation(), 100.0);
+
+ particles->setVelocity(100.0);
+ QCOMPARE(particles->velocity(), 100.0);
+
+ particles->setVelocityDeviation(100.0);
+ QCOMPARE(particles->velocityDeviation(), 100.0);
+
+ particles->setEmissionVariance(0.5);
+ QCOMPARE(particles->emissionVariance(),0.5);
+
+ particles->setEmissionRate(12);
+ QCOMPARE(particles->emissionRate(), 12);
+}
+
+void tst_QmlGraphicsParticles::runs()
+{
+ QmlView *canvas = createView(SRCDIR "/data/particles.qml");
+ QVERIFY(canvas->root());
+ QmlGraphicsParticles* particles = canvas->root()->findChild<QmlGraphicsParticles*>("particles");
+ QVERIFY(particles);
+ QTest::qWait(1000);//Run for one second. Test passes if it doesn't crash.
+}
+
+QmlView *tst_QmlGraphicsParticles::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+ canvas->execute();
+
+ return canvas;
+}
+QTEST_MAIN(tst_QmlGraphicsParticles)
+
+#include "tst_qmlgraphicsparticles.moc"
diff --git a/tests/auto/declarative/qmlgraphicspathview/data/datamodel.qml b/tests/auto/declarative/qmlgraphicspathview/data/datamodel.qml
new file mode 100644
index 0000000..8d07db2
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/data/datamodel.qml
@@ -0,0 +1,36 @@
+import Qt 4.6
+
+PathView {
+ id: pathview
+ objectName: "pathview"
+ width: 240; height: 320
+ pathItemCount: testObject.pathItemCount
+
+ function checkProperties() {
+ testObject.error = false;
+ if (testObject.useModel && pathview.model != testData) {
+ console.log("model property incorrect");
+ testObject.error = true;
+ }
+ }
+
+ model: testObject.useModel ? testData : 0
+
+ delegate: Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ width: 20; height: 20; color: name
+ Text {
+ objectName: "myText"
+ text: name
+ }
+ }
+ }
+
+ path: Path {
+ startX: 120; startY: 20;
+ PathLine { x: 120; y: 300 }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspathview/data/path.qml b/tests/auto/declarative/qmlgraphicspathview/data/path.qml
new file mode 100644
index 0000000..7e82a48
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/data/path.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Path {
+ startX: 120; startY: 100
+
+ PathAttribute { name: "scale"; value: 1.0 }
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathPercent { value: 0.3 }
+ PathLine { x: 120; y: 100 }
+ PathCubic {
+ x: 180; y: 0; control1X: -10; control1Y: 90
+ control2X: 210; control2Y: 90
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspathview/data/pathview.qml b/tests/auto/declarative/qmlgraphicspathview/data/pathview.qml
new file mode 100644
index 0000000..8fa8d59
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/data/pathview.qml
@@ -0,0 +1,66 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: delegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 20
+ width: 60
+ color: "white"
+ border.color: "black"
+ Text {
+ text: index
+ }
+ Text {
+ x: 20
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 40
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ }
+ }
+ ]
+ PathView {
+ id: view
+ objectName: "view"
+ width: 240
+ height: 320
+ model: testModel
+ delegate: delegate
+ snapPosition: 0.01
+ path: Path {
+ startY: 120
+ startX: 160
+ PathQuad {
+ y: 120
+ x: 80
+ controlY: 330
+ controlX: 100
+ }
+ PathLine {
+ y: 160
+ x: 20
+ }
+ PathCubic {
+ y: 120
+ x: 160
+ control1Y: 0
+ control1X: 100
+ control2Y: 000
+ control2X: 200
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspathview/data/pathview1.qml b/tests/auto/declarative/qmlgraphicspathview/data/pathview1.qml
new file mode 100644
index 0000000..b3b0a9a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/data/pathview1.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+PathView {
+}
diff --git a/tests/auto/declarative/qmlgraphicspathview/data/pathview2.qml b/tests/auto/declarative/qmlgraphicspathview/data/pathview2.qml
new file mode 100644
index 0000000..0d5c98b
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/data/pathview2.qml
@@ -0,0 +1,57 @@
+import Qt 4.6
+
+PathView {
+ id: photoPathView; model: rssModel; delegate: photoDelegate
+ y: 100; width: 800; height: 330; pathItemCount: 10; z: 1
+
+ path: Path {
+ startX: -50; startY: 40;
+
+ PathAttribute { name: "scale"; value: 0.5 }
+ PathAttribute { name: "angle"; value: -45 }
+
+ PathCubic {
+ x: 400; y: 220
+ control1X: 140; control1Y: 40
+ control2X: 210; control2Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 1.2 }
+ PathAttribute { name: "angle"; value: 0 }
+
+ PathCubic {
+ x: 850; y: 40
+ control2X: 660; control2Y: 40
+ control1X: 590; control1Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 0.5 }
+ PathAttribute { name: "angle"; value: 45 }
+ }
+
+ model: ListModel {
+ id: rssModel
+ ListElement { lColor: "red" }
+ ListElement { lColor: "green" }
+ ListElement { lColor: "yellow" }
+ ListElement { lColor: "blue" }
+ ListElement { lColor: "purple" }
+ ListElement { lColor: "gray" }
+ ListElement { lColor: "brown" }
+ ListElement { lColor: "thistle" }
+ }
+
+ delegate: Component {
+ id: photoDelegate
+ Rectangle {
+ id: wrapper
+ width: 85; height: 85; color: lColor
+ scale: wrapper.PathView.scale
+
+ transform: Rotation {
+ id: itemRotation; origin.x: wrapper.width/2; origin.y: wrapper.height/2
+ axis.y: 1; axis.z: 0; angle: wrapper.PathView.angle
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspathview/data/pathview3.qml b/tests/auto/declarative/qmlgraphicspathview/data/pathview3.qml
new file mode 100644
index 0000000..412cca2
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/data/pathview3.qml
@@ -0,0 +1,57 @@
+import Qt 4.6
+
+PathView {
+ id: photoPathView; model: rssModel; delegate: photoDelegate
+ y: 100; width: 800; height: 330; pathItemCount: 4; offset: 10
+ dragMargin: 24; snapPosition: 50
+
+ path: Path {
+ startX: -50; startY: 40;
+
+ PathAttribute { name: "scale"; value: 0.5 }
+ PathAttribute { name: "angle"; value: -45 }
+
+ PathCubic {
+ x: 400; y: 220
+ control1X: 140; control1Y: 40
+ control2X: 210; control2Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 1.2 }
+ PathAttribute { name: "angle"; value: 0 }
+
+ PathCubic {
+ x: 850; y: 40
+ control2X: 660; control2Y: 40
+ control1X: 590; control1Y: 220
+ }
+
+ PathAttribute { name: "scale"; value: 0.5 }
+ PathAttribute { name: "angle"; value: 45 }
+ }
+
+ model: ListModel {
+ id: rssModel
+ ListElement { lColor: "red" }
+ ListElement { lColor: "green" }
+ ListElement { lColor: "yellow" }
+ ListElement { lColor: "blue" }
+ ListElement { lColor: "purple" }
+ ListElement { lColor: "gray" }
+ ListElement { lColor: "brown" }
+ ListElement { lColor: "thistle" }
+ }
+
+ delegate: Component {
+ id: photoDelegate
+ Rectangle {
+ id: wrapper
+ width: 85; height: 85; color: lColor
+
+ transform: Rotation {
+ id: itemRotation; origin.x: wrapper.width/2; origin.y: wrapper.height/2
+ axis.y: 1; axis.z: 0
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspathview/qmlgraphicspathview.pro b/tests/auto/declarative/qmlgraphicspathview/qmlgraphicspathview.pro
new file mode 100644
index 0000000..142a256
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/qmlgraphicspathview.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicspathview.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp b/tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp
new file mode 100644
index 0000000..4c2ecbd
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp
@@ -0,0 +1,494 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <private/qmlgraphicspathview_p.h>
+#include <private/qmlgraphicspath_p.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlview.h>
+#include <QtDeclarative/private/qmlgraphicstext_p.h>
+#include <QtDeclarative/private/qmlgraphicsrectangle_p.h>
+#include <QAbstractListModel>
+#include <QFile>
+#include <private/qmlvaluetype_p.h>
+#include "../../../shared/util.h"
+
+class tst_QmlGraphicsPathView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsPathView();
+
+private slots:
+ void initValues();
+ void items();
+ void dataModel();
+ void pathview2();
+ void pathview3();
+ void path();
+ void pathMoved();
+
+private:
+ QmlView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QmlGraphicsItem *parent, const QString &objectName, int index=-1);
+ template<typename T>
+ QList<T*> findItems(QmlGraphicsItem *parent, const QString &objectName);
+};
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool error READ error WRITE setError)
+ Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
+ Q_PROPERTY(int pathItemCount READ pathItemCount NOTIFY pathItemCountChanged)
+
+public:
+ TestObject() : QObject(), mError(true), mUseModel(true), mPathItemCount(-1) {}
+
+ bool error() const { return mError; }
+ void setError(bool err) { mError = err; }
+
+ bool useModel() const { return mUseModel; }
+ void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
+
+ int pathItemCount() const { return mPathItemCount; }
+ void setPathItemCount(int count) { mPathItemCount = count; emit pathItemCountChanged(); }
+
+signals:
+ void useModelChanged();
+ void pathItemCountChanged();
+
+private:
+ bool mError;
+ bool mUseModel;
+ int mPathItemCount;
+};
+
+class TestModel : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ emit endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+tst_QmlGraphicsPathView::tst_QmlGraphicsPathView()
+{
+}
+
+void tst_QmlGraphicsPathView::initValues()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview1.qml"));
+ QmlGraphicsPathView *obj = qobject_cast<QmlGraphicsPathView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->path() == 0);
+ QVERIFY(obj->delegate() == 0);
+ QCOMPARE(obj->model(), QVariant());
+ QCOMPARE(obj->currentIndex(), 0);
+ QCOMPARE(obj->offset(), 0.);
+ QCOMPARE(obj->snapPosition(), 0.);
+ QCOMPARE(obj->dragMargin(), 0.);
+ QCOMPARE(obj->count(), 0);
+ QCOMPARE(obj->pathItemCount(), -1);
+}
+
+void tst_QmlGraphicsPathView::items()
+{
+ QmlView *canvas = createView(SRCDIR "/data/pathview.qml");
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsPathView *pathview = findItem<QmlGraphicsPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ QCOMPARE(pathview->childItems().count(), model.count()); // assumes all are visible
+
+ for (int i = 0; i < model.count(); ++i) {
+ QmlGraphicsText *name = findItem<QmlGraphicsText>(pathview, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QmlGraphicsText *number = findItem<QmlGraphicsText>(pathview, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsPathView::pathview2()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview2.qml"));
+ QmlGraphicsPathView *obj = qobject_cast<QmlGraphicsPathView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->path() != 0);
+ QVERIFY(obj->delegate() != 0);
+ QVERIFY(obj->model() != QVariant());
+ QCOMPARE(obj->currentIndex(), 0);
+ QCOMPARE(obj->offset(), 0.);
+ QCOMPARE(obj->snapPosition(), 0.);
+ QCOMPARE(obj->dragMargin(), 0.);
+ QCOMPARE(obj->count(), 8);
+ QCOMPARE(obj->pathItemCount(), 10);
+}
+
+void tst_QmlGraphicsPathView::pathview3()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview3.qml"));
+ QmlGraphicsPathView *obj = qobject_cast<QmlGraphicsPathView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->path() != 0);
+ QVERIFY(obj->delegate() != 0);
+ QVERIFY(obj->model() != QVariant());
+ QCOMPARE(obj->currentIndex(), 0);
+ QCOMPARE(obj->offset(), 50.); // ???
+ QCOMPARE(obj->snapPosition(), 0.5); // ???
+ QCOMPARE(obj->dragMargin(), 24.);
+ QCOMPARE(obj->count(), 8);
+ QCOMPARE(obj->pathItemCount(), 4);
+}
+
+void tst_QmlGraphicsPathView::path()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/path.qml"));
+ QmlGraphicsPath *obj = qobject_cast<QmlGraphicsPath*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->startX(), 120.);
+ QCOMPARE(obj->startY(), 100.);
+ QVERIFY(obj->path() != QPainterPath());
+
+ QList<QmlGraphicsPathElement*> *list = obj->pathElements();
+ QCOMPARE(list->count(), 5);
+
+ QmlGraphicsPathAttribute* attr = qobject_cast<QmlGraphicsPathAttribute*>(list->at(0));
+ QVERIFY(attr != 0);
+ QCOMPARE(attr->name(), QString("scale"));
+ QCOMPARE(attr->value(), 1.0);
+
+ QmlGraphicsPathQuad* quad = qobject_cast<QmlGraphicsPathQuad*>(list->at(1));
+ QVERIFY(quad != 0);
+ QCOMPARE(quad->x(), 120.);
+ QCOMPARE(quad->y(), 25.);
+ QCOMPARE(quad->controlX(), 260.);
+ QCOMPARE(quad->controlY(), 75.);
+
+ QmlGraphicsPathPercent* perc = qobject_cast<QmlGraphicsPathPercent*>(list->at(2));
+ QVERIFY(perc != 0);
+ QCOMPARE(perc->value(), 0.3);
+
+ QmlGraphicsPathLine* line = qobject_cast<QmlGraphicsPathLine*>(list->at(3));
+ QVERIFY(line != 0);
+ QCOMPARE(line->x(), 120.);
+ QCOMPARE(line->y(), 100.);
+
+ QmlGraphicsPathCubic* cubic = qobject_cast<QmlGraphicsPathCubic*>(list->at(4));
+ QVERIFY(cubic != 0);
+ QCOMPARE(cubic->x(), 180.);
+ QCOMPARE(cubic->y(), 0.);
+ QCOMPARE(cubic->control1X(), -10.);
+ QCOMPARE(cubic->control1Y(), 90.);
+ QCOMPARE(cubic->control2X(), 210.);
+ QCOMPARE(cubic->control2Y(), 90.);
+}
+
+void tst_QmlGraphicsPathView::dataModel()
+{
+ QmlView *canvas = createView(SRCDIR "/data/datamodel.qml");
+
+ QmlContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ TestModel model;
+ model.addItem("red", "1");
+ model.addItem("green", "2");
+ model.addItem("blue", "3");
+ model.addItem("purple", "4");
+ model.addItem("gray", "5");
+ model.addItem("brown", "6");
+ model.addItem("yellow", "7");
+ model.addItem("thistle", "8");
+ model.addItem("cyan", "9");
+
+ ctxt->setContextProperty("testData", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsPathView *pathview = qobject_cast<QmlGraphicsPathView*>(canvas->root());
+ QVERIFY(pathview != 0);
+
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(pathview, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->x(), 110.0);
+ QCOMPARE(item->y(), 10.0);
+
+ model.insertItem(4, "orange", "10");
+
+ int itemCount = findItems<QmlGraphicsItem>(pathview, "wrapper").count();
+ QCOMPARE(itemCount, 10);
+
+ QmlGraphicsText *text = findItem<QmlGraphicsText>(pathview, "myText", 4);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(4));
+
+ model.removeItem(2);
+ text = findItem<QmlGraphicsText>(pathview, "myText", 2);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(2));
+
+ testObject->setPathItemCount(5);
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ itemCount = findItems<QmlGraphicsItem>(pathview, "wrapper").count();
+ QCOMPARE(itemCount, 5);
+
+ QmlGraphicsRectangle *testItem = findItem<QmlGraphicsRectangle>(pathview, "wrapper", 4);
+ QVERIFY(testItem != 0);
+ testItem = findItem<QmlGraphicsRectangle>(pathview, "wrapper", 5);
+ QVERIFY(testItem == 0);
+
+ model.insertItem(2, "pink", "2");
+
+ itemCount = findItems<QmlGraphicsItem>(pathview, "wrapper").count();
+ QCOMPARE(itemCount, 5);
+
+ text = findItem<QmlGraphicsText>(pathview, "myText", 2);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(2));
+
+ model.removeItem(3);
+ itemCount = findItems<QmlGraphicsItem>(pathview, "wrapper").count();
+ QCOMPARE(itemCount, 5);
+ text = findItem<QmlGraphicsText>(pathview, "myText", 3);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(3));
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsPathView::pathMoved()
+{
+ QmlView *canvas = createView(SRCDIR "/data/pathview.qml");
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsPathView *pathview = findItem<QmlGraphicsPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ QmlGraphicsRectangle *firstItem = findItem<QmlGraphicsRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QmlGraphicsPath *path = qobject_cast<QmlGraphicsPath*>(pathview->path());
+ QVERIFY(path);
+ QPointF start = path->pointAt(0.0);
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(firstItem->width()/2);
+ offset.setY(firstItem->height()/2);
+ QCOMPARE(firstItem->pos() + offset, start);
+ pathview->setOffset(10);
+ QTest::qWait(1000);//Moving is animated?
+
+ for(int i=0; i<model.count(); i++){
+ QmlGraphicsRectangle *curItem = findItem<QmlGraphicsRectangle>(pathview, "wrapper", i);
+ QCOMPARE(curItem->pos() + offset, path->pointAt(0.1 + i*0.25));
+ }
+
+ pathview->setOffset(100);
+ QTest::qWait(1000);//Moving is animated?
+ QCOMPARE(firstItem->pos() + offset, start);
+
+ delete canvas;
+}
+
+QmlView *tst_QmlGraphicsPathView::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+ */
+template<typename T>
+T *tst_QmlGraphicsPathView::findItem(QmlGraphicsItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QmlExpression e(qmlContext(item), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+template<typename T>
+QList<T*> tst_QmlGraphicsPathView::findItems(QmlGraphicsItem *parent, const QString &objectName)
+{
+ QList<T*> items;
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QGraphicsObject::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ items.append(static_cast<T*>(item));
+ items += findItems<T>(item, objectName);
+ }
+
+ return items;
+}
+
+QTEST_MAIN(tst_QmlGraphicsPathView)
+
+#include "tst_qmlgraphicspathview.moc"
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/grid-animated.qml b/tests/auto/declarative/qmlgraphicspositioners/data/grid-animated.qml
new file mode 100644
index 0000000..022019c
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/grid-animated.qml
@@ -0,0 +1,60 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Grid {
+ columns: 3
+ add: Transition {
+ NumberAnimation {
+ matchProperties: "x,y";
+ }
+ }
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x,y";
+ }
+ }
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ x: -100
+ y: -100
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ x: -100
+ y: -100
+ opacity: 0
+ color: "green"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "three"
+ color: "blue"
+ x: -100
+ y: -100
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "four"
+ color: "cyan"
+ x: -100
+ y: -100
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "five"
+ color: "magenta"
+ x: -100
+ y: -100
+ width: 50
+ height: 50
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/grid-spacing.qml b/tests/auto/declarative/qmlgraphicspositioners/data/grid-spacing.qml
new file mode 100644
index 0000000..5b4a30d
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/grid-spacing.qml
@@ -0,0 +1,40 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Grid {
+ columns: 3
+ spacing: 4
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rectangle {
+ objectName: "three"
+ color: "blue"
+ width: 50
+ height: 20
+ }
+ Rectangle {
+ objectName: "four"
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "five"
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/grid.qml b/tests/auto/declarative/qmlgraphicspositioners/data/grid.qml
new file mode 100644
index 0000000..830df6a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/grid.qml
@@ -0,0 +1,39 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Grid {
+ columns: 3
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "green"
+ width: 20
+ height: 50
+ }
+ Rectangle {
+ objectName: "three"
+ color: "blue"
+ width: 50
+ height: 20
+ }
+ Rectangle {
+ objectName: "four"
+ color: "cyan"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "five"
+ color: "magenta"
+ width: 10
+ height: 10
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/horizontal-animated.qml b/tests/auto/declarative/qmlgraphicspositioners/data/horizontal-animated.qml
new file mode 100644
index 0000000..eba165c
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/horizontal-animated.qml
@@ -0,0 +1,40 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Row {
+ add: Transition {
+ NumberAnimation {
+ matchProperties: "x";
+ }
+ }
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "x";
+ }
+ }
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ x: -100;
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "blue"
+ x: -100;
+ opacity: 0
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "three"
+ x: -100;
+ color: "green"
+ width: 50
+ height: 50
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/horizontal-spacing.qml b/tests/auto/declarative/qmlgraphicspositioners/data/horizontal-spacing.qml
new file mode 100644
index 0000000..32bf775
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/horizontal-spacing.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Row {
+ spacing: 10
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rectangle {
+ objectName: "three"
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/horizontal.qml b/tests/auto/declarative/qmlgraphicspositioners/data/horizontal.qml
new file mode 100644
index 0000000..06ae151
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/horizontal.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Row {
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rectangle {
+ objectName: "three"
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/repeater.qml b/tests/auto/declarative/qmlgraphicspositioners/data/repeater.qml
new file mode 100644
index 0000000..2bc5e94
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/repeater.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Row {
+ Repeater{ model: 3;
+ delegate: Component {
+ Rectangle {
+ color: "red"
+ width: 50
+ height: 50
+ z: {if(index == 0){2;}else if(index == 1){1;} else{3;}}
+ objectName: {if(index == 0){"one";}else if(index == 1){"two";} else{"three";}}
+
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/vertical-animated.qml b/tests/auto/declarative/qmlgraphicspositioners/data/vertical-animated.qml
new file mode 100644
index 0000000..8e3abbd
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/vertical-animated.qml
@@ -0,0 +1,40 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Column {
+ add: Transition {
+ NumberAnimation {
+ matchProperties: "y";
+ }
+ }
+ move: Transition {
+ NumberAnimation {
+ matchProperties: "y";
+ }
+ }
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ y: -100
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "blue"
+ y: -100
+ opacity: 0
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "three"
+ color: "red"
+ y: -100
+ width: 50
+ height: 50
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/vertical-spacing.qml b/tests/auto/declarative/qmlgraphicspositioners/data/vertical-spacing.qml
new file mode 100644
index 0000000..69a8256
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/vertical-spacing.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Column {
+ spacing: 10
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rectangle {
+ objectName: "three"
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/data/vertical.qml b/tests/auto/declarative/qmlgraphicspositioners/data/vertical.qml
new file mode 100644
index 0000000..856c180
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/data/vertical.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+Item {
+ width: 640
+ height: 480
+ Column {
+ Rectangle {
+ objectName: "one"
+ color: "red"
+ width: 50
+ height: 50
+ }
+ Rectangle {
+ objectName: "two"
+ color: "red"
+ width: 20
+ height: 10
+ }
+ Rectangle {
+ objectName: "three"
+ color: "red"
+ width: 40
+ height: 20
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicspositioners/qmlgraphicspositioners.pro b/tests/auto/declarative/qmlgraphicspositioners/qmlgraphicspositioners.pro
new file mode 100644
index 0000000..d151026
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/qmlgraphicspositioners.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlgraphicspositioners.cpp
+macx:CONFIG -= app_bundle
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicspositioners/tst_qmlgraphicspositioners.cpp b/tests/auto/declarative/qmlgraphicspositioners/tst_qmlgraphicspositioners.cpp
new file mode 100644
index 0000000..da541c8
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicspositioners/tst_qmlgraphicspositioners.cpp
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <private/qlistmodelinterface_p.h>
+#include <qmlview.h>
+#include <private/qmlgraphicsrectangle_p.h>
+#include <qmlexpression.h>
+
+class tst_QmlGraphicsPositioners : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsPositioners();
+
+private slots:
+ void test_horizontal();
+ void test_horizontal_spacing();
+ void test_horizontal_animated();
+ void test_vertical();
+ void test_vertical_spacing();
+ void test_vertical_animated();
+ void test_grid();
+ void test_grid_spacing();
+ void test_grid_animated();
+
+ void test_repeater();
+private:
+ QmlView *createView(const QString &filename);
+};
+
+tst_QmlGraphicsPositioners::tst_QmlGraphicsPositioners()
+{
+}
+
+void tst_QmlGraphicsPositioners::test_horizontal()
+{
+ QmlView *canvas = createView(SRCDIR "/data/horizontal.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+}
+
+void tst_QmlGraphicsPositioners::test_horizontal_spacing()
+{
+ QmlView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 60.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 90.0);
+ QCOMPARE(three->y(), 0.0);
+}
+
+void tst_QmlGraphicsPositioners::test_horizontal_animated()
+{
+ QmlView *canvas = createView(SRCDIR "/data/horizontal-animated.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ //Note that they animate in
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->x(), -100.0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->x(), -100.0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->x(), -100.0);
+
+ QTest::qWait(300);//Let the animation complete
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->opacity(), 0.0);
+ QCOMPARE(two->x(), -100.0);//Not 'in' yet
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 0.0);
+
+ //Add 'two'
+ two->setOpacity(1.0);
+ QCOMPARE(two->opacity(), 1.0);
+ QTest::qWait(0);//Let the animation start
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(three->x(), 50.0);
+ QTest::qWait(300);//Let the animation complete
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(three->x(), 100.0);
+}
+
+void tst_QmlGraphicsPositioners::test_vertical()
+{
+ QmlView *canvas = createView(SRCDIR "/data/vertical.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 60.0);
+}
+
+void tst_QmlGraphicsPositioners::test_vertical_spacing()
+{
+ QmlView *canvas = createView(SRCDIR "/data/vertical-spacing.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 60.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 80.0);
+}
+
+void tst_QmlGraphicsPositioners::test_vertical_animated()
+{
+ QmlView *canvas = createView(SRCDIR "/data/vertical-animated.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QTest::qWait(0);//Let the animation start
+ //Note that they animate in
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->y(), -100.0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->y(), -100.0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->y(), -100.0);
+
+ QTest::qWait(300);//Let the animation complete
+
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(two->opacity(), 0.0);
+ QCOMPARE(two->y(), -100.0);//Not 'in' yet
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+
+ //Add 'two'
+ two->setOpacity(1.0);
+ QCOMPARE(two->opacity(), 1.0);
+ QTest::qWait(0);//Let the animation start
+ QCOMPARE(two->y(), -100.0);
+ QCOMPARE(three->y(), 50.0);
+ QTest::qWait(300);//Let the animation complete
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->y(), 100.0);
+
+}
+
+void tst_QmlGraphicsPositioners::test_grid()
+{
+ QmlView *canvas = createView("data/grid.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+ QmlGraphicsRectangle *four = canvas->root()->findChild<QmlGraphicsRectangle*>("four");
+ QVERIFY(four != 0);
+ QmlGraphicsRectangle *five = canvas->root()->findChild<QmlGraphicsRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
+}
+
+void tst_QmlGraphicsPositioners::test_grid_spacing()
+{
+ QmlView *canvas = createView("data/grid-spacing.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+ QmlGraphicsRectangle *four = canvas->root()->findChild<QmlGraphicsRectangle*>("four");
+ QVERIFY(four != 0);
+ QmlGraphicsRectangle *five = canvas->root()->findChild<QmlGraphicsRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 54.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 78.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 54.0);
+ QCOMPARE(five->x(), 54.0);
+ QCOMPARE(five->y(), 54.0);
+}
+
+void tst_QmlGraphicsPositioners::test_grid_animated()
+{
+ QmlView *canvas = createView(SRCDIR "/data/grid-animated.qml");
+ canvas->execute();
+ qApp->processEvents();
+
+ QTest::qWait(0);//Let the animation start
+ //Note that all animate in
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(one->y(), -100.0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->x(), -100.0);
+ QCOMPARE(three->y(), -100.0);
+
+ QmlGraphicsRectangle *four = canvas->root()->findChild<QmlGraphicsRectangle*>("four");
+ QVERIFY(four != 0);
+ QCOMPARE(four->x(), -100.0);
+ QCOMPARE(four->y(), -100.0);
+
+ QmlGraphicsRectangle *five = canvas->root()->findChild<QmlGraphicsRectangle*>("five");
+ QVERIFY(five != 0);
+ QCOMPARE(five->x(), -100.0);
+ QCOMPARE(five->y(), -100.0);
+
+ QTest::qWait(300);//Let the animation complete
+
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(two->opacity(), 0.0);
+ QCOMPARE(two->y(), -100.0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(four->x(), 100.0);
+ QCOMPARE(five->y(), 50.0);
+ QCOMPARE(five->x(), 0.0);
+
+ //Add 'two'
+ two->setOpacity(1.0);
+ QCOMPARE(two->opacity(), 1.0);
+ QTest::qWait(0);//Let the animation start
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 100.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(five->x(), 0.0);
+ QCOMPARE(five->y(), 50.0);
+ QTest::qWait(300);//Let the animation complete
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(three->x(), 100.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
+
+}
+
+void tst_QmlGraphicsPositioners::test_repeater()
+{
+ QmlView *canvas = createView("data/repeater.qml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRectangle *one = canvas->root()->findChild<QmlGraphicsRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QmlGraphicsRectangle *two = canvas->root()->findChild<QmlGraphicsRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QmlGraphicsRectangle *three = canvas->root()->findChild<QmlGraphicsRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 100.0);
+ QCOMPARE(three->y(), 0.0);
+}
+
+QmlView *tst_QmlGraphicsPositioners::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setQml(xml, filename);
+
+ return canvas;
+}
+
+
+QTEST_MAIN(tst_QmlGraphicsPositioners)
+
+#include "tst_qmlgraphicspositioners.moc"
diff --git a/tests/auto/declarative/qmlgraphicsrepeater/data/intmodel.qml b/tests/auto/declarative/qmlgraphicsrepeater/data/intmodel.qml
new file mode 100644
index 0000000..cf1fb4d
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsrepeater/data/intmodel.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+ objectName: "container"
+ width: 240
+ height: 320
+ color: "white"
+
+ function checkProperties() {
+ testObject.error = false;
+ if (repeater.delegate != comp) {
+ console.log("delegate property incorrect");
+ testObject.error = true;
+ }
+ }
+
+ Component {
+ id: comp
+ Item{}
+ }
+
+ Repeater {
+ id: repeater
+ objectName: "repeater"
+ model: testData
+ delegate: comp
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsrepeater/data/itemlist.qml b/tests/auto/declarative/qmlgraphicsrepeater/data/itemlist.qml
new file mode 100644
index 0000000..fc6b34c
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsrepeater/data/itemlist.qml
@@ -0,0 +1,49 @@
+// This example demonstrates placing items in a view using
+// a VisualItemModel
+
+import Qt 4.6
+
+Rectangle {
+ color: "lightgray"
+ width: 240
+ height: 320
+
+ function checkProperties() {
+ testObject.error = false;
+ if (testObject.useModel && view.model != itemModel) {
+ console.log("model property incorrect");
+ testObject.error = true;
+ }
+ }
+
+ VisualItemModel {
+ id: itemModel
+ objectName: "itemModel"
+ Rectangle {
+ objectName: "item1"
+ height: view.height; width: view.width; color: "#FFFEF0"
+ Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ }
+ Rectangle {
+ objectName: "item2"
+ height: view.height; width: view.width; color: "#F0FFF7"
+ Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ }
+ Rectangle {
+ objectName: "item3"
+ height: view.height; width: view.width; color: "#F4F0FF"
+ Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ }
+ }
+
+ Column {
+ objectName: "container"
+ Repeater {
+ id: view
+ objectName: "repeater"
+ anchors.fill: parent
+ anchors.bottomMargin: 30
+ model: testObject.useModel ? itemModel : 0
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsrepeater/data/objlist.qml b/tests/auto/declarative/qmlgraphicsrepeater/data/objlist.qml
new file mode 100644
index 0000000..e6d0acb
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsrepeater/data/objlist.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+ objectName: "container"
+ width: 240
+ height: 320
+ color: "white"
+ Repeater {
+ id: repeater
+ objectName: "repeater"
+ model: testData
+ property int errors: 0
+ property int instantiated: 0
+ Component {
+ Item{
+ Component.onCompleted: {if(index!=model.idx) repeater.errors += 1; repeater.instantiated++}
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsrepeater/data/repeater.qml b/tests/auto/declarative/qmlgraphicsrepeater/data/repeater.qml
new file mode 100644
index 0000000..7d83230
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsrepeater/data/repeater.qml
@@ -0,0 +1,28 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+ objectName: "container"
+ width: 240
+ height: 320
+ color: "white"
+ Text {
+ text: "Zero"
+ }
+ Repeater {
+ id: repeater
+ objectName: "repeater"
+ width: 240
+ height: 320
+ model: testData
+ Component {
+ Text {
+ y: index*20
+ text: modelData
+ }
+ }
+ }
+ Text {
+ text: "Last"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsrepeater/data/repeater2.qml b/tests/auto/declarative/qmlgraphicsrepeater/data/repeater2.qml
new file mode 100644
index 0000000..c3c3260
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsrepeater/data/repeater2.qml
@@ -0,0 +1,35 @@
+import Qt 4.6
+
+Rectangle {
+ width: 240
+ height: 320
+ color: "white"
+ Component {
+ id: myDelegate
+ Item {
+ objectName: "myDelegate"
+ height: 20
+ Text {
+ y: index*20
+ text: name
+ }
+ Text {
+ y: index*20
+ x: 100
+ text: number
+ }
+ }
+ }
+ Column {
+ id: container
+ objectName: "container"
+ Repeater {
+ id: repeater
+ objectName: "repeater"
+ width: 240
+ height: 320
+ delegate: myDelegate
+ model: testData
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsrepeater/qmlgraphicsrepeater.pro b/tests/auto/declarative/qmlgraphicsrepeater/qmlgraphicsrepeater.pro
new file mode 100644
index 0000000..0a10ec6
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsrepeater/qmlgraphicsrepeater.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicsrepeater.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsrepeater/tst_qmlgraphicsrepeater.cpp b/tests/auto/declarative/qmlgraphicsrepeater/tst_qmlgraphicsrepeater.cpp
new file mode 100644
index 0000000..4297901
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsrepeater/tst_qmlgraphicsrepeater.cpp
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <private/qlistmodelinterface_p.h>
+#include <qmlview.h>
+#include <private/qmlgraphicsrepeater_p.h>
+#include <private/qmlgraphicstext_p.h>
+#include <qmlcontext.h>
+
+class tst_QmlGraphicsRepeater : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsRepeater();
+
+private slots:
+ void numberModel();
+ void objectList();
+ void stringList();
+ void dataModel();
+ void itemModel();
+
+private:
+ QmlView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QmlGraphicsItem *parent, const QString &id);
+};
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool error READ error WRITE setError)
+ Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
+
+public:
+ TestObject() : QObject(), mError(true), mUseModel(false) {}
+
+ bool error() const { return mError; }
+ void setError(bool err) { mError = err; }
+
+ bool useModel() const { return mUseModel; }
+ void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
+
+signals:
+ void useModelChanged();
+
+private:
+ bool mError;
+ bool mUseModel;
+};
+
+class TestModel : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ emit endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+tst_QmlGraphicsRepeater::tst_QmlGraphicsRepeater()
+{
+}
+
+void tst_QmlGraphicsRepeater::numberModel()
+{
+ QmlView *canvas = createView(SRCDIR "/data/intmodel.qml");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testData", 5);
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRepeater *repeater = findItem<QmlGraphicsRepeater>(canvas->root(), "repeater");
+ QVERIFY(repeater != 0);
+ QCOMPARE(repeater->parentItem()->childItems().count(), 5+1);
+
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsRepeater::objectList()
+{
+ QmlView *canvas = createView(SRCDIR "/data/objlist.qml");
+
+ QObjectList* data = new QObjectList;
+ for(int i=0; i<100; i++){
+ *data << new QObject();
+ data->back()->setProperty("idx", i);
+ }
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testData", QVariant::fromValue<QObjectList*>(data));
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRepeater *repeater = findItem<QmlGraphicsRepeater>(canvas->root(), "repeater");
+ QVERIFY(repeater != 0);
+ QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data
+ QCOMPARE(repeater->property("instantiated").toInt(), 100);
+}
+
+/*
+The Repeater element creates children at its own position in its parent's
+stacking order. In this test we insert a repeater between two other Text
+elements to test this.
+*/
+void tst_QmlGraphicsRepeater::stringList()
+{
+ QmlView *canvas = createView(SRCDIR "/data/repeater.qml");
+
+ QStringList data;
+ data << "One";
+ data << "Two";
+ data << "Three";
+ data << "Four";
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testData", data);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRepeater *repeater = findItem<QmlGraphicsRepeater>(canvas->root(), "repeater");
+ QVERIFY(repeater != 0);
+
+ QmlGraphicsItem *container = findItem<QmlGraphicsItem>(canvas->root(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->childItems().count(), data.count() + 3);
+
+ bool saw_repeater = false;
+ for (int i = 0; i < container->childItems().count(); ++i) {
+
+ if (i == 0) {
+ QmlGraphicsText *name = qobject_cast<QmlGraphicsText*>(container->childItems().at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), QLatin1String("Zero"));
+ } else if (i == container->childItems().count() - 2) {
+ // The repeater itself
+ QmlGraphicsRepeater *rep = qobject_cast<QmlGraphicsRepeater*>(container->childItems().at(i));
+ QCOMPARE(rep, repeater);
+ saw_repeater = true;
+ continue;
+ } else if (i == container->childItems().count() - 1) {
+ QmlGraphicsText *name = qobject_cast<QmlGraphicsText*>(container->childItems().at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), QLatin1String("Last"));
+ } else {
+ QmlGraphicsText *name = qobject_cast<QmlGraphicsText*>(container->childItems().at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), data.at(i-1));
+ }
+ }
+ QVERIFY(saw_repeater);
+
+ delete canvas;
+}
+
+void tst_QmlGraphicsRepeater::dataModel()
+{
+ QmlView *canvas = createView(SRCDIR "/data/repeater2.qml");
+ QmlContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ TestModel testModel;
+ testModel.addItem("one", "1");
+ testModel.addItem("two", "2");
+ testModel.addItem("three", "3");
+
+ ctxt->setContextProperty("testData", &testModel);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRepeater *repeater = findItem<QmlGraphicsRepeater>(canvas->root(), "repeater");
+ QVERIFY(repeater != 0);
+
+ QmlGraphicsItem *container = findItem<QmlGraphicsItem>(canvas->root(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->childItems().count(), 4);
+
+ testModel.addItem("four", "4");
+ QCOMPARE(container->childItems().count(), 5);
+
+ testModel.removeItem(2);
+ QCOMPARE(container->childItems().count(), 4);
+}
+
+void tst_QmlGraphicsRepeater::itemModel()
+{
+ QmlView *canvas = createView(SRCDIR "/data/itemlist.qml");
+ QmlContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QmlGraphicsRepeater *repeater = findItem<QmlGraphicsRepeater>(canvas->root(), "repeater");
+ QVERIFY(repeater != 0);
+
+ QmlGraphicsItem *container = findItem<QmlGraphicsItem>(canvas->root(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->childItems().count(), 1);
+
+ testObject->setUseModel(true);
+ QMetaObject::invokeMethod(canvas->root(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ QCOMPARE(container->childItems().count(), 4);
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item1");
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item2");
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(2))->objectName() == "item3");
+ QVERIFY(container->childItems().at(3) == repeater);
+
+ delete canvas;
+}
+
+
+QmlView *tst_QmlGraphicsRepeater::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = file.readAll();
+ canvas->setQml(qml, filename);
+
+ return canvas;
+}
+
+template<typename T>
+T *tst_QmlGraphicsRepeater::findItem(QmlGraphicsItem *parent, const QString &objectName)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ if (mo.cast(parent) && (objectName.isEmpty() || parent->objectName() == objectName))
+ return static_cast<T*>(parent);
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem*>(parent->childItems().at(i));
+ if (!child)
+ continue;
+ QmlGraphicsItem *item = findItem<T>(child, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QmlGraphicsRepeater)
+
+#include "tst_qmlgraphicsrepeater.moc"
diff --git a/tests/auto/declarative/qmlgraphicstext/qmlgraphicstext.pro b/tests/auto/declarative/qmlgraphicstext/qmlgraphicstext.pro
new file mode 100644
index 0000000..1d8c59f
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstext/qmlgraphicstext.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicstext.cpp
diff --git a/tests/auto/declarative/qmlgraphicstext/tst_qmlgraphicstext.cpp b/tests/auto/declarative/qmlgraphicstext/tst_qmlgraphicstext.cpp
new file mode 100644
index 0000000..4626fe6
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstext/tst_qmlgraphicstext.cpp
@@ -0,0 +1,844 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QTextDocument>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicstext_p.h>
+#include <private/qmlvaluetype_p.h>
+#include <QFontMetrics>
+#include <QGraphicsSceneMouseEvent>
+#include <qmath.h>
+
+class tst_qmlgraphicstext : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicstext();
+
+private slots:
+ void text();
+ void width();
+ void wrap();
+ void elide();
+ void textFormat();
+
+ // ### these tests may be trivial
+ void horizontalAlignment();
+ void verticalAlignment();
+ void font();
+ void style();
+ void color();
+ void smooth();
+
+ // QmlFontValueType
+ void weight();
+ void underline();
+ void overline();
+ void strikeout();
+ void capitalization();
+ void letterSpacing();
+ void wordSpacing();
+
+ void clickLink();
+
+private:
+ QStringList standard;
+ QStringList richText;
+
+ QStringList horizontalAlignmentmentStrings;
+ QStringList verticalAlignmentmentStrings;
+
+ QList<Qt::Alignment> verticalAlignmentments;
+ QList<Qt::Alignment> horizontalAlignmentments;
+
+ QStringList styleStrings;
+ QList<QmlGraphicsText::TextStyle> styles;
+
+ QStringList colorStrings;
+
+ QmlEngine engine;
+};
+
+tst_qmlgraphicstext::tst_qmlgraphicstext()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog";
+
+ richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ horizontalAlignmentmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ verticalAlignmentmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ horizontalAlignmentments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ verticalAlignmentments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ styleStrings << "Normal"
+ << "Outline"
+ << "Raised"
+ << "Sunken";
+
+ styles << QmlGraphicsText::Normal
+ << QmlGraphicsText::Outline
+ << QmlGraphicsText::Raised
+ << QmlGraphicsText::Sunken;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+void tst_qmlgraphicstext::text()
+{
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData("import Qt 4.6\nText { text: \"\" }", QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), QString(""));
+ QVERIFY(textObject->width() == 0);
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), standard.at(i));
+ QVERIFY(textObject->width() > 0);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QString expected = richText.at(i);
+ QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
+ QVERIFY(textObject->width() > 0);
+ }
+}
+
+void tst_qmlgraphicstext::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData("import Qt 4.6\nText { text: \"\" }", QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 0.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test
+
+ QFont f;
+ QFontMetricsF fm(f);
+ qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+ metricWidth = qCeil(metricWidth);
+
+ QString componentStr = "import Qt 4.6\nText { text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), qreal(metricWidth));
+ QVERIFY(textObject->textFormat() == QmlGraphicsText::AutoText); // setting text doesn't change format
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test
+
+ QTextDocument document;
+ document.setHtml(richText.at(i));
+ document.setDocumentMargin(0);
+
+ int documentWidth = document.idealWidth();
+
+ QString componentStr = "import Qt 4.6\nText { text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), qreal(documentWidth));
+ QVERIFY(textObject->textFormat() == QmlGraphicsText::AutoText); // setting text doesn't change format
+ }
+}
+
+void tst_qmlgraphicstext::wrap()
+{
+ int textHeight = 0;
+ // for specified width and wrap set true
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData("import Qt 4.6\nText { text: \"Hello\"; wrap: true; width: 300 }", QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+ textHeight = textObject->height();
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->wrap() == true);
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { wrap: true; width: 30; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 30.);
+ QVERIFY(textObject->height() > textHeight);
+
+ int oldHeight = textObject->height();
+ textObject->setWidth(100);
+ QVERIFY(textObject->height() < oldHeight);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { wrap: true; width: 30; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 30.);
+ QVERIFY(textObject->height() > textHeight);
+ }
+
+}
+
+void tst_qmlgraphicstext::elide()
+{
+ for (QmlGraphicsText::TextElideMode m = QmlGraphicsText::ElideLeft; m<=QmlGraphicsText::ElideNone; m=QmlGraphicsText::TextElideMode(int(m)+1)) {
+ const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
+ QString elide = "elide: Text." + QString(elidename[int(m)]) + ";";
+
+ // XXX Poor coverage.
+
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData(("import Qt 4.6\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->elideMode(), m);
+ QCOMPARE(textObject->width(), 100.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->elideMode(), m);
+ QCOMPARE(textObject->width(), 100.);
+ }
+
+ // richtext - does nothing
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->elideMode(), m);
+ QCOMPARE(textObject->width(), 100.);
+ }
+ }
+}
+
+void tst_qmlgraphicstext::textFormat()
+{
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData("import Qt 4.6\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QmlGraphicsText::RichText);
+ }
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData("import Qt 4.6\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QmlGraphicsText::PlainText);
+ }
+}
+
+//the alignment tests may be trivial o.oa
+void tst_qmlgraphicstext::horizontalAlignment()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
+ }
+ }
+
+}
+
+void tst_qmlgraphicstext::verticalAlignment()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
+ }
+ }
+
+}
+
+void tst_qmlgraphicstext::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "import Qt 4.6\nText { font.pointSize: 40; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().pointSize(), 40);
+ QCOMPARE(textObject->font().bold(), false);
+ QCOMPARE(textObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nText { font.pixelSize: 40; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().pixelSize(), 40);
+ QCOMPARE(textObject->font().bold(), false);
+ QCOMPARE(textObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nText { font.bold: true; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().bold(), true);
+ QCOMPARE(textObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nText { font.italic: true; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().italic(), true);
+ QCOMPARE(textObject->font().bold(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().family(), QString("Helvetica"));
+ QCOMPARE(textObject->font().bold(), false);
+ QCOMPARE(textObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nText { font.family: \"\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().family(), QString(""));
+ }
+}
+
+void tst_qmlgraphicstext::style()
+{
+ //test style
+ for (int i = 0; i < styles.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->style(), (int)styles.at(i));
+ QCOMPARE(textObject->styleColor(), QColor("white"));
+ }
+}
+
+void tst_qmlgraphicstext::color()
+{
+ //test style
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor());
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
+ // default color to black?
+ QCOMPARE(textObject->color(), QColor("black"));
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ for (int j = 0; j < colorStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nText { color: \"" + colorStrings.at(i) + "\"; styleColor: \"" + colorStrings.at(j) + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
+ }
+ }
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "import Qt 4.6\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), testColor);
+ }
+}
+
+void tst_qmlgraphicstext::smooth()
+{
+ for (int i = 0; i < standard.size(); i++)
+ {
+ {
+ QString componentStr = "import Qt 4.6\nText { smooth: true; text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), true);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"" + standard.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), false);
+ }
+ }
+ for (int i = 0; i < richText.size(); i++)
+ {
+ {
+ QString componentStr = "import Qt 4.6\nText { smooth: true; text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), true);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"" + richText.at(i) + "\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), false);
+ }
+ }
+}
+
+void tst_qmlgraphicstext::weight()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().weight(), (int)QmlFontValueType::Normal);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { font.weight: \"Bold\"; text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().weight(), (int)QmlFontValueType::Bold);
+ }
+}
+
+void tst_qmlgraphicstext::underline()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().underline(), false);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { font.underline: true; text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().underline(), true);
+ }
+}
+
+void tst_qmlgraphicstext::overline()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().overline(), false);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { font.overline: true; text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().overline(), true);
+ }
+}
+
+void tst_qmlgraphicstext::strikeout()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().strikeOut(), false);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { font.strikeout: true; text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().strikeOut(), true);
+ }
+}
+
+void tst_qmlgraphicstext::capitalization()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QmlFontValueType::MixedCase);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QmlFontValueType::AllUppercase);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QmlFontValueType::AllLowercase);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QmlFontValueType::SmallCaps);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QmlFontValueType::Capitalize);
+ }
+}
+
+void tst_qmlgraphicstext::letterSpacing()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().letterSpacing(), 0.0);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.letterSpacing: -50 }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().letterSpacing(), -50.);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.letterSpacing: 200 }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().letterSpacing(), 200.);
+ }
+}
+
+void tst_qmlgraphicstext::wordSpacing()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().wordSpacing(), 0.0);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().wordSpacing(), -50.);
+ }
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().wordSpacing(), 200.);
+ }
+}
+
+class EventSender : public QGraphicsItem
+{
+public:
+ void sendEvent(QEvent *event) { sceneEvent(event); }
+};
+
+class LinkTest : public QObject
+{
+ Q_OBJECT
+public:
+ LinkTest() {}
+
+ QString link;
+
+public slots:
+ void linkClicked(QString l) { link = l; }
+};
+
+void tst_qmlgraphicstext::clickLink()
+{
+ {
+ QString componentStr = "import Qt 4.6\nText { text: \"<a href=\\\"http://qt.nokia.com\\\">Hello world!</a>\" }";
+ QmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlGraphicsText *textObject = qobject_cast<QmlGraphicsText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+
+ LinkTest test;
+ QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
+
+ {
+ QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
+ me.setPos(QPointF(textObject->x()/2, textObject->y()/2));
+ me.setButton(Qt::LeftButton);
+ static_cast<EventSender*>(static_cast<QGraphicsItem*>(textObject))->sendEvent(&me);
+ }
+
+ {
+ QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMouseRelease);
+ me.setPos(QPointF(textObject->x()/2, textObject->y()/2));
+ me.setButton(Qt::LeftButton);
+ static_cast<EventSender*>(static_cast<QGraphicsItem*>(textObject))->sendEvent(&me);
+ }
+
+ QCOMPARE(test.link, QLatin1String("http://qt.nokia.com"));
+ }
+}
+
+QTEST_MAIN(tst_qmlgraphicstext)
+
+#include "tst_qmlgraphicstext.moc"
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/cursorTest.qml b/tests/auto/declarative/qmlgraphicstextedit/data/cursorTest.qml
new file mode 100644
index 0000000..e5df8f1
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/cursorTest.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Rectangle { width: 300; height: 300; color: "white"
+ TextEdit { text: "Hello world!"; id: textEditObject; objectName: "textEditObject"
+ resources: [ Component { id:cursor; Item { id:cursorInstance; objectName: "cursorInstance" } } ]
+ cursorDelegate: cursor
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/http/ErrItem.qml b/tests/auto/declarative/qmlgraphicstextedit/data/http/ErrItem.qml
new file mode 100644
index 0000000..34b3883
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/http/ErrItem.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+Item{
+ Fungus{
+ palatable: false;
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/http/NormItem.qml b/tests/auto/declarative/qmlgraphicstextedit/data/http/NormItem.qml
new file mode 100644
index 0000000..718cb71
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/http/NormItem.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Item {
+ objectName: "delegateOkay"
+ Rectangle { }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTest.qml b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTest.qml
new file mode 100644
index 0000000..3c31e11
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTest.qml
@@ -0,0 +1,22 @@
+import Qt 4.6
+
+Rectangle { width: 300; height: 300; color: "white"
+ resources: [
+ Component { id:cursorFail; FailItem { objectName: "delegateFail" } },
+ Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
+ Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } },
+ Component { id:cursorErr; ErrItem { objectName: "delegateErrorA" } }
+ ]
+ TextEdit {
+ cursorDelegate: cursorFail
+ }
+ TextEdit {
+ cursorDelegate: cursorWait
+ }
+ TextEdit {
+ cursorDelegate: cursorNorm
+ }
+ TextEdit {
+ cursorDelegate: cursorErr
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail1.qml b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail1.qml
new file mode 100644
index 0000000..a44aec2
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail1.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Rectangle { width: 300; height: 300; color: "white"
+ resources: [
+ Component { id:cursorFail; FailItem { objectName: "delegateFail" } },
+ Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
+ Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } }
+ ]
+ TextEdit {
+ cursorDelegate: cursorFail
+ }
+ TextEdit {
+ cursorDelegate: cursorWait
+ }
+ TextEdit {
+ cursorDelegate: cursorNorm
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail2.qml b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail2.qml
new file mode 100644
index 0000000..57d3e47
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestFail2.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Rectangle { width: 300; height: 300; color: "white"
+ resources: [
+ Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
+ Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } },
+ Component { id:cursorErr; ErrItem { objectName: "delegateErrorA" } }
+ ]
+ TextEdit {
+ cursorDelegate: cursorWait
+ }
+ TextEdit {
+ cursorDelegate: cursorNorm
+ }
+ TextEdit {
+ cursorDelegate: cursorErr
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestPass.qml b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestPass.qml
new file mode 100644
index 0000000..a44e867
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/http/cursorHttpTestPass.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Rectangle { width: 300; height: 300; color: "white"
+ resources: [
+ Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
+ Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } }
+ ]
+ TextEdit {
+ cursorDelegate: cursorWait
+ text: "Hello"
+ }
+ TextEdit {
+ objectName: "textEditObject"
+ cursorDelegate: cursorNorm
+ focus: true;
+ text: "Hello"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/httpfail/FailItem.qml b/tests/auto/declarative/qmlgraphicstextedit/data/httpfail/FailItem.qml
new file mode 100644
index 0000000..ddbf526
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/httpfail/FailItem.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Item {
+ Rectangle { }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/httpslow/WaitItem.qml b/tests/auto/declarative/qmlgraphicstextedit/data/httpslow/WaitItem.qml
new file mode 100644
index 0000000..ddbf526
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/httpslow/WaitItem.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Item {
+ Rectangle { }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/inputmethodhints.qml b/tests/auto/declarative/qmlgraphicstextedit/data/inputmethodhints.qml
new file mode 100644
index 0000000..c3d4c16
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/inputmethodhints.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+TextEdit {
+ text: "Hello world!"
+ inputMethodHints: Qt.ImhNoPredictiveText
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/navigation.qml b/tests/auto/declarative/qmlgraphicstextedit/data/navigation.qml
new file mode 100644
index 0000000..8d7dbbc
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/navigation.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+Rectangle {
+ property var myInput: input
+
+ width: 800; height: 600; color: "blue"
+
+ Item {
+ id: firstItem;
+ KeyNavigation.right: input
+ }
+
+ TextEdit { id: input; focus: true
+ KeyNavigation.left: firstItem
+ KeyNavigation.right: lastItem
+ KeyNavigation.up: firstItem
+ KeyNavigation.down: lastItem
+ }
+ Item {
+ id: lastItem
+ KeyNavigation.left: input
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/data/readOnly.qml b/tests/auto/declarative/qmlgraphicstextedit/data/readOnly.qml
new file mode 100644
index 0000000..103a627
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/data/readOnly.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+Rectangle {
+ property var myInput: input
+
+ width: 800; height: 600; color: "blue"
+
+ TextEdit { id: input; focus: true
+ readOnly: true
+ text: "I am the very model of a modern major general.\n"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextedit/qmlgraphicstextedit.pro b/tests/auto/declarative/qmlgraphicstextedit/qmlgraphicstextedit.pro
new file mode 100644
index 0000000..a129120
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/qmlgraphicstextedit.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui network
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicstextedit.cpp ../shared/testhttpserver.cpp
+HEADERS += ../shared/testhttpserver.h
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicstextedit/tst_qmlgraphicstextedit.cpp b/tests/auto/declarative/qmlgraphicstextedit/tst_qmlgraphicstextedit.cpp
new file mode 100644
index 0000000..a197ced
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextedit/tst_qmlgraphicstextedit.cpp
@@ -0,0 +1,807 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include "../../../shared/util.h"
+#include "../shared/testhttpserver.h"
+#include <math.h>
+#include <QFile>
+#include <QTextDocument>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicstextedit_p.h>
+#include <QFontMetrics>
+#include <QmlView>
+#include <QStyle>
+#include <QInputContext>
+
+class tst_qmlgraphicstextedit : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicstextedit();
+
+private slots:
+ void text();
+ void width();
+ void wrap();
+ void textFormat();
+
+ // ### these tests may be trivial
+ void hAlign();
+ void vAlign();
+ void font();
+ void color();
+ void textMargin();
+ void persistentSelection();
+ void focusOnPress();
+ void selection();
+ void inputMethodHints();
+
+ void cursorDelegate();
+ void delegateLoading();
+ void navigation();
+ void readOnly();
+ void sendRequestSoftwareInputPanelEvent();
+
+private:
+ void simulateKey(QmlView *, int key);
+ QmlView *createView(const QString &filename);
+
+ QStringList standard;
+ QStringList richText;
+
+ QStringList hAlignmentStrings;
+ QStringList vAlignmentStrings;
+
+ QList<Qt::Alignment> vAlignments;
+ QList<Qt::Alignment> hAlignments;
+
+ QStringList colorStrings;
+
+ QmlEngine engine;
+};
+
+tst_qmlgraphicstextedit::tst_qmlgraphicstextedit()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog";
+
+ richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ hAlignmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ vAlignmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ hAlignments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ vAlignments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+void tst_qmlgraphicstextedit::text()
+{
+ {
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData("import Qt 4.6\nTextEdit { text: \"\" }", QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), QString(""));
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), standard.at(i));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QString actual = textEditObject->text();
+ QString expected = richText.at(i);
+ actual.replace(QRegExp(".*<body[^>]*>"),"");
+ actual.replace(QRegExp("(<[^>]*>)+"),"<>");
+ expected.replace(QRegExp("(<[^>]*>)+"),"<>");
+ QCOMPARE(actual.simplified(),expected.simplified());
+ }
+}
+
+void tst_qmlgraphicstextedit::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData("import Qt 4.6\nTextEdit { text: \"\" }", QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 1.);//+1 for cursor
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ QFontMetricsF fm(f);
+ qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+ metricWidth = floor(metricWidth);
+
+ QString componentStr = "import Qt 4.6\nTextEdit { text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), qreal(metricWidth + 1 + 3));//+3 is the current way of accounting for space between cursor and last character.
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QTextDocument document;
+ document.setHtml(richText.at(i));
+ document.setDocumentMargin(0);
+
+ int documentWidth = document.idealWidth();
+
+ QString componentStr = "import Qt 4.6\nTextEdit { text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), qreal(documentWidth + 1 + 3));
+ }
+}
+
+void tst_qmlgraphicstextedit::wrap()
+{
+ // for specified width and wrap set true
+ {
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData("import Qt 4.6\nTextEdit { text: \"\"; wrap: true; width: 300 }", QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { wrap: true; width: 300; text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { wrap: true; width: 300; text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+}
+
+void tst_qmlgraphicstextedit::textFormat()
+{
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData("import Qt 4.6\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
+ QmlGraphicsTextEdit *textObject = qobject_cast<QmlGraphicsTextEdit*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QmlGraphicsTextEdit::RichText);
+ }
+ {
+ QmlComponent textComponent(&engine);
+ textComponent.setData("import Qt 4.6\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
+ QmlGraphicsTextEdit *textObject = qobject_cast<QmlGraphicsTextEdit*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QmlGraphicsTextEdit::PlainText);
+ }
+}
+
+//the alignment tests may be trivial o.oa
+void tst_qmlgraphicstextedit::hAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qmlgraphicstextedit::vAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qmlgraphicstextedit::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { font.pointSize: 40; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().pointSize(), 40);
+ QCOMPARE(textEditObject->font().bold(), false);
+ QCOMPARE(textEditObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { font.bold: true; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().bold(), true);
+ QCOMPARE(textEditObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { font.italic: true; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().italic(), true);
+ QCOMPARE(textEditObject->font().bold(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
+ QCOMPARE(textEditObject->font().bold(), false);
+ QCOMPARE(textEditObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { font.family: \"\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().family(), QString(""));
+ }
+}
+
+void tst_qmlgraphicstextedit::color()
+{
+ //test normal
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
+ }
+
+ //test selection
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
+ }
+
+ //test selected text
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
+ }
+
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "import Qt 4.6\nTextEdit { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->color(), testColor);
+ }
+}
+
+void tst_qmlgraphicstextedit::textMargin()
+{
+ for(qreal i=0; i<=10; i+=0.3){
+ QString componentStr = "import Qt 4.6\nTextEdit { textMargin: " + QString::number(i) + "; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->textMargin(), i);
+ }
+}
+
+void tst_qmlgraphicstextedit::persistentSelection()
+{
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { persistentSelection: true; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->persistentSelection(), true);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { persistentSelection: false; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->persistentSelection(), false);
+ }
+}
+
+void tst_qmlgraphicstextedit::focusOnPress()
+{
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { focusOnPress: true; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->focusOnPress(), true);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextEdit { focusOnPress: false; text: \"Hello World\" }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->focusOnPress(), false);
+ }
+}
+
+void tst_qmlgraphicstextedit::selection()
+{
+ QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
+ QString componentStr = "import Qt 4.6\nTextEdit { text: \""+ testStr +"\"; }";
+ QmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+
+
+ //Test selection follows cursor
+ for(int i=0; i<= testStr.size(); i++) {
+ textEditObject->setCursorPosition(i);
+ QCOMPARE(textEditObject->cursorPosition(), i);
+ QCOMPARE(textEditObject->selectionStart(), i);
+ QCOMPARE(textEditObject->selectionEnd(), i);
+ QVERIFY(textEditObject->selectedText().isNull());
+ }
+
+ textEditObject->setCursorPosition(0);
+ QVERIFY(textEditObject->cursorPosition() == 0);
+ QVERIFY(textEditObject->selectionStart() == 0);
+ QVERIFY(textEditObject->selectionEnd() == 0);
+ QVERIFY(textEditObject->selectedText().isNull());
+
+ //Test selection
+ for(int i=0; i<= testStr.size(); i++) {
+ textEditObject->setSelectionEnd(i);
+ QCOMPARE(testStr.mid(0,i), textEditObject->selectedText());
+ }
+ for(int i=0; i<= testStr.size(); i++) {
+ textEditObject->setSelectionStart(i);
+ QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText());
+ }
+
+ textEditObject->setCursorPosition(0);
+ QVERIFY(textEditObject->cursorPosition() == 0);
+ QVERIFY(textEditObject->selectionStart() == 0);
+ QVERIFY(textEditObject->selectionEnd() == 0);
+ QVERIFY(textEditObject->selectedText().isNull());
+
+ for(int i=0; i< testStr.size(); i++) {
+ textEditObject->setSelectionStart(i);
+ QCOMPARE(textEditObject->selectionEnd(), i);
+ QCOMPARE(testStr.mid(i,0), textEditObject->selectedText());
+ textEditObject->setSelectionEnd(i+1);
+ QCOMPARE(textEditObject->selectionStart(), i);
+ QCOMPARE(testStr.mid(i,1), textEditObject->selectedText());
+ }
+
+ for(int i= testStr.size() - 1; i>0; i--) {
+ textEditObject->setSelectionEnd(i);
+ QCOMPARE(testStr.mid(i,0), textEditObject->selectedText());
+ textEditObject->setSelectionStart(i-1);
+ QCOMPARE(testStr.mid(i-1,1), textEditObject->selectedText());
+ }
+
+ //Test Error Ignoring behaviour
+ textEditObject->setCursorPosition(0);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->setSelectionStart(-10);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->setSelectionStart(100);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->setSelectionEnd(-10);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->setSelectionEnd(100);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->setSelectionStart(0);
+ textEditObject->setSelectionEnd(10);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->setSelectionStart(-10);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->setSelectionStart(100);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->setSelectionEnd(-10);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->setSelectionEnd(100);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+}
+
+void tst_qmlgraphicstextedit::inputMethodHints()
+{
+ QmlView *canvas = createView(SRCDIR "/data/inputmethodhints.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+
+ QVERIFY(canvas->root() != 0);
+ QmlGraphicsTextEdit *textEditObject = qobject_cast<QmlGraphicsTextEdit *>(canvas->root());
+ QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
+ textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
+ QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly);
+}
+
+void tst_qmlgraphicstextedit::cursorDelegate()
+{
+ QmlView* view = createView(SRCDIR "/data/cursorTest.qml");
+ view->execute();
+ view->show();
+ view->setFocus();
+ QmlGraphicsTextEdit *textEditObject = view->root()->findChild<QmlGraphicsTextEdit*>("textEditObject");
+ QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject->findChild<QmlGraphicsItem*>("cursorInstance"));
+ //Test Delegate gets created
+ textEditObject->setFocus(true);
+ QmlGraphicsItem* delegateObject = textEditObject->findChild<QmlGraphicsItem*>("cursorInstance");
+ QVERIFY(delegateObject);
+ //Test Delegate gets moved
+ for(int i=0; i<= textEditObject->text().length(); i++){
+ textEditObject->setCursorPosition(i);
+ QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y()));
+ }
+ textEditObject->setCursorPosition(0);
+ QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y()));
+ //Test Delegate gets deleted
+ textEditObject->setCursorDelegate(0);
+ QVERIFY(!textEditObject->findChild<QmlGraphicsItem*>("cursorInstance"));
+}
+
+void tst_qmlgraphicstextedit::delegateLoading()
+{
+ TestHTTPServer server(42332);
+ server.serveDirectory(SRCDIR "/data/httpfail", TestHTTPServer::Disconnect);
+ server.serveDirectory(SRCDIR "/data/httpslow", TestHTTPServer::Delay);
+ server.serveDirectory(SRCDIR "/data/http");
+ QmlView* view = new QmlView(0);
+ view->setUrl(QUrl("http://localhost:42332/cursorHttpTestPass.qml"));
+ view->execute();
+ view->show();
+ view->setFocus();
+ QTRY_VERIFY(view->root());//Wait for loading to finish.
+ QmlGraphicsTextEdit *textEditObject = view->root()->findChild<QmlGraphicsTextEdit*>("textEditObject");
+ // view->root()->dumpObjectTree();
+ QVERIFY(textEditObject != 0);
+ textEditObject->setFocus(true);
+ QmlGraphicsItem *delegate;
+ delegate = view->root()->findChild<QmlGraphicsItem*>("delegateOkay");
+ QVERIFY(delegate);
+ delegate = view->root()->findChild<QmlGraphicsItem*>("delegateSlow");
+ QVERIFY(delegate);
+ view->setUrl(QUrl("http://localhost:42332/cursorHttpTestFail1.qml"));
+ view->execute();
+ view->show();
+ view->setFocus();
+ delegate = view->root()->findChild<QmlGraphicsItem*>("delegateOkay");
+ QVERIFY(delegate);
+ delegate = view->root()->findChild<QmlGraphicsItem*>("delegateFail");
+ QVERIFY(!delegate);
+ view->setUrl(QUrl("http://localhost:42332/cursorHttpTestFail2.qml"));
+ view->execute();
+ view->show();
+ view->setFocus();
+ delegate = view->root()->findChild<QmlGraphicsItem*>("delegateOkay");
+ QVERIFY(delegate);
+ delegate = view->root()->findChild<QmlGraphicsItem*>("delegateErrorA");
+ QVERIFY(!delegate);
+ //ErrorB should get a component which is ready but component.create() returns null
+ //Not sure how to accomplish this with QmlGraphicsTextEdits cursor delegate
+ //###This could be a case of overzealous defensive programming
+ //delegate = view->root()->findChild<QmlGraphicsItem*>("delegateErrorB");
+ //QVERIFY(!delegate);
+}
+
+/*
+TextEdit element should only handle left/right keys until the cursor reaches
+the extent of the text, then they should ignore the keys.
+*/
+void tst_qmlgraphicstextedit::navigation()
+{
+ QmlView *canvas = createView(SRCDIR "/data/navigation.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+
+ QVERIFY(canvas->root() != 0);
+
+ QmlGraphicsItem *input = qobject_cast<QmlGraphicsItem *>(qvariant_cast<QObject *>(canvas->root()->property("myInput")));
+
+ QVERIFY(input != 0);
+ QTRY_VERIFY(input->hasFocus() == true);
+ simulateKey(canvas, Qt::Key_Left);
+ QVERIFY(input->hasFocus() == false);
+ simulateKey(canvas, Qt::Key_Right);
+ QVERIFY(input->hasFocus() == true);
+ simulateKey(canvas, Qt::Key_Right);
+ QVERIFY(input->hasFocus() == false);
+ simulateKey(canvas, Qt::Key_Left);
+ QVERIFY(input->hasFocus() == true);
+}
+
+void tst_qmlgraphicstextedit::readOnly()
+{
+ QmlView *canvas = createView(SRCDIR "/data/readOnly.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+
+ QVERIFY(canvas->root() != 0);
+
+ QmlGraphicsTextEdit *edit = qobject_cast<QmlGraphicsTextEdit *>(qvariant_cast<QObject *>(canvas->root()->property("myInput")));
+
+ QVERIFY(edit != 0);
+ QTRY_VERIFY(edit->hasFocus() == true);
+ QVERIFY(edit->isReadOnly() == true);
+ QString initial = edit->text();
+ for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
+ simulateKey(canvas, k);
+ simulateKey(canvas, Qt::Key_Return);
+ simulateKey(canvas, Qt::Key_Space);
+ simulateKey(canvas, Qt::Key_Escape);
+ QCOMPARE(edit->text(), initial);
+}
+
+void tst_qmlgraphicstextedit::simulateKey(QmlView *view, int key)
+{
+ QKeyEvent press(QKeyEvent::KeyPress, key, 0);
+ QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
+
+ QApplication::sendEvent(view, &press);
+ QApplication::sendEvent(view, &release);
+}
+
+QmlView *tst_qmlgraphicstextedit::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setQml(xml, filename);
+ return canvas;
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : softwareInputPanelEventReceived(false) {}
+ ~MyInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+
+ bool isComposing() const { return false; }
+
+ bool filterEvent( const QEvent *event )
+ {
+ if (event->type() == QEvent::RequestSoftwareInputPanel)
+ softwareInputPanelEventReceived = true;
+ return QInputContext::filterEvent(event);
+ }
+ bool softwareInputPanelEventReceived;
+};
+
+void tst_qmlgraphicstextedit::sendRequestSoftwareInputPanelEvent()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ MyInputContext ic;
+ view.viewport()->setInputContext(&ic);
+ QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
+ view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
+ if ((behavior != QStyle::RSIP_OnMouseClick))
+ QSKIP("This test need to have a style with RSIP_OnMouseClick", SkipSingle);
+ QmlGraphicsTextEdit edit;
+ edit.setText("Hello world");
+ edit.setPos(0, 0);
+ scene.addItem(&edit);
+ view.show();
+ qApp->setAutoSipEnabled(true);
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
+ QApplication::processEvents();
+ QCOMPARE(ic.softwareInputPanelEventReceived, true);
+}
+QTEST_MAIN(tst_qmlgraphicstextedit)
+
+#include "tst_qmlgraphicstextedit.moc"
diff --git a/tests/auto/declarative/qmlgraphicstextinput/data/cursorTest.qml b/tests/auto/declarative/qmlgraphicstextinput/data/cursorTest.qml
new file mode 100644
index 0000000..ddc98cc
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/data/cursorTest.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+Rectangle { width: 300; height: 300; color: "white"
+ TextInput { text: "Hello world!"; id: textInputObject; objectName: "textInputObject"
+ resources: [ Component { id:cursor; Item { id:cursorInstance; objectName: "cursorInstance";} } ]
+ cursorDelegate: cursor
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextinput/data/inputmethodhints.qml b/tests/auto/declarative/qmlgraphicstextinput/data/inputmethodhints.qml
new file mode 100644
index 0000000..b404682
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/data/inputmethodhints.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+TextInput {
+ text: "Hello world!"
+ inputMethodHints: Qt.ImhNoPredictiveText
+}
diff --git a/tests/auto/declarative/qmlgraphicstextinput/data/masks.qml b/tests/auto/declarative/qmlgraphicstextinput/data/masks.qml
new file mode 100644
index 0000000..08a857c
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/data/masks.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+TextInput{
+ focus: true
+ objectName: "myInput"
+ inputMask: "HHHHhhhh; "
+}
diff --git a/tests/auto/declarative/qmlgraphicstextinput/data/maxLength.qml b/tests/auto/declarative/qmlgraphicstextinput/data/maxLength.qml
new file mode 100644
index 0000000..7cbeadd
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/data/maxLength.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+TextInput{
+ focus: true
+ objectName: "myInput"
+ maximumLength: 10
+}
diff --git a/tests/auto/declarative/qmlgraphicstextinput/data/navigation.qml b/tests/auto/declarative/qmlgraphicstextinput/data/navigation.qml
new file mode 100644
index 0000000..7a2e914
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/data/navigation.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+Rectangle {
+ property var myInput: input
+
+ width: 800; height: 600; color: "blue"
+
+ Item {
+ id: firstItem;
+ KeyNavigation.right: input
+ }
+
+ TextInput { id: input; focus: true
+ KeyNavigation.left: firstItem
+ KeyNavigation.right: lastItem
+ KeyNavigation.up: firstItem
+ KeyNavigation.down: lastItem
+ }
+ Item {
+ id: lastItem
+ KeyNavigation.left: input
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextinput/data/readOnly.qml b/tests/auto/declarative/qmlgraphicstextinput/data/readOnly.qml
new file mode 100644
index 0000000..c47371a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/data/readOnly.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+Rectangle {
+ property var myInput: input
+
+ width: 800; height: 600; color: "blue"
+
+ TextInput { id: input; focus: true
+ readOnly: true
+ text: "I am the very model of a modern major general.\n"
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicstextinput/data/validators.qml b/tests/auto/declarative/qmlgraphicstextinput/data/validators.qml
new file mode 100644
index 0000000..673790d
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/data/validators.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+Item {
+ property var intInput: intInput
+ property var dblInput: dblInput
+ property var strInput: strInput
+
+ width: 800; height: 600;
+
+ Column{
+ TextInput { id: intInput;
+ validator: QIntValidator{top: 11; bottom: 2}
+ }
+ TextInput { id: dblInput;
+ validator: QDoubleValidator{top: 12.12; bottom: 2.93; decimals: 2; notation: QDoubleValidator.StandardNotation}
+ }
+ TextInput { id: strInput;
+ //Requires QTBUG-8025 to be implemented first
+ //validator: QRegExpValidator { regExp: /[a-zA-z]{2,4}/;}
+ }
+ }
+
+}
diff --git a/tests/auto/declarative/qmlgraphicstextinput/qmlgraphicstextinput.pro b/tests/auto/declarative/qmlgraphicstextinput/qmlgraphicstextinput.pro
new file mode 100644
index 0000000..fd75fec
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/qmlgraphicstextinput.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicstextinput.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicstextinput/tst_qmlgraphicstextinput.cpp b/tests/auto/declarative/qmlgraphicstextinput/tst_qmlgraphicstextinput.cpp
new file mode 100644
index 0000000..906dbc2
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicstextinput/tst_qmlgraphicstextinput.cpp
@@ -0,0 +1,655 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include "../../../shared/util.h"
+#include <QtDeclarative/qmlengine.h>
+#include <QFile>
+#include <QtDeclarative/qmlview.h>
+#include <private/qmlgraphicstextinput_p.h>
+#include <QDebug>
+#include <QStyle>
+#include <QInputContext>
+
+class tst_qmlgraphicstextinput : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicstextinput();
+
+private slots:
+ void text();
+ void width();
+ void font();
+ void color();
+ void selection();
+
+ void maxLength();
+ void masks();
+ void validators();
+ void inputMethodHints();
+
+ void cursorDelegate();
+ void navigation();
+ void readOnly();
+
+ void sendRequestSoftwareInputPanelEvent();
+
+private:
+ void simulateKey(QmlView *, int key);
+ QmlView *createView(const QString &filename);
+
+ QmlEngine engine;
+ QStringList standard;
+ QStringList colorStrings;
+};
+
+tst_qmlgraphicstextinput::tst_qmlgraphicstextinput()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "It's supercalifragisiticexpialidocious!"
+ << "Hello, world!";
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+}
+
+void tst_qmlgraphicstextinput::text()
+{
+ {
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData("import Qt 4.6\nTextInput { text: \"\" }", QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->text(), QString(""));
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { text: \"" + standard.at(i) + "\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->text(), standard.at(i));
+ }
+
+}
+
+void tst_qmlgraphicstextinput::width()
+{
+ // uses Font metrics to find the width for standard
+ {
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData("import Qt 4.6\nTextInput { text: \"\" }", QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->width(), 1.);//1 for the cursor
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ QFontMetricsF fm(f);
+ qreal metricWidth = fm.width(standard.at(i));
+
+ QString componentStr = "import Qt 4.6\nTextInput { text: \"" + standard.at(i) + "\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->width(), qreal(metricWidth) + 1.);//1 for the cursor
+ }
+}
+
+void tst_qmlgraphicstextinput::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { font.pointSize: 40; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().pointSize(), 40);
+ QCOMPARE(textinputObject->font().bold(), false);
+ QCOMPARE(textinputObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { font.bold: true; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().bold(), true);
+ QCOMPARE(textinputObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { font.italic: true; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().italic(), true);
+ QCOMPARE(textinputObject->font().bold(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
+ QCOMPARE(textinputObject->font().bold(), false);
+ QCOMPARE(textinputObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { font.family: \"\"; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().family(), QString(""));
+ }
+}
+
+void tst_qmlgraphicstextinput::color()
+{
+ //test color
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
+ }
+
+ //test selection color
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
+ }
+
+ //test selected text color
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import Qt 4.6\nTextInput { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
+ }
+
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "import Qt 4.6\nTextInput { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->color(), testColor);
+ }
+}
+
+void tst_qmlgraphicstextinput::selection()
+{
+ QString testStr = standard[0];
+ QString componentStr = "import Qt 4.6\nTextInput { text: \""+ testStr +"\"; }";
+ QmlComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+
+
+ //Test selection follows cursor
+ for(int i=0; i<= testStr.size(); i++) {
+ textinputObject->setCursorPosition(i);
+ QCOMPARE(textinputObject->cursorPosition(), i);
+ QCOMPARE(textinputObject->selectionStart(), i);
+ QCOMPARE(textinputObject->selectionEnd(), i);
+ QVERIFY(textinputObject->selectedText().isNull());
+ }
+
+ textinputObject->setCursorPosition(0);
+ QVERIFY(textinputObject->cursorPosition() == 0);
+ QVERIFY(textinputObject->selectionStart() == 0);
+ QVERIFY(textinputObject->selectionEnd() == 0);
+ QVERIFY(textinputObject->selectedText().isNull());
+
+ //Test selection
+ for(int i=0; i<= testStr.size(); i++) {
+ textinputObject->setSelectionEnd(i);
+ QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
+ }
+ for(int i=0; i<= testStr.size(); i++) {
+ textinputObject->setSelectionStart(i);
+ QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
+ }
+
+ textinputObject->setCursorPosition(0);
+ QVERIFY(textinputObject->cursorPosition() == 0);
+ QVERIFY(textinputObject->selectionStart() == 0);
+ QVERIFY(textinputObject->selectionEnd() == 0);
+ QVERIFY(textinputObject->selectedText().isNull());
+
+ for(int i=0; i< testStr.size(); i++) {
+ textinputObject->setSelectionStart(i);
+ QCOMPARE(textinputObject->selectionEnd(), i);
+ QCOMPARE(testStr.mid(i,0), textinputObject->selectedText());
+ textinputObject->setSelectionEnd(i+1);
+ QCOMPARE(textinputObject->selectionStart(), i);
+ QCOMPARE(testStr.mid(i,1), textinputObject->selectedText());
+ }
+
+ for(int i= testStr.size() - 1; i>0; i--) {
+ textinputObject->setSelectionEnd(i);
+ QCOMPARE(testStr.mid(i,0), textinputObject->selectedText());
+ textinputObject->setSelectionStart(i-1);
+ QCOMPARE(testStr.mid(i-1,1), textinputObject->selectedText());
+ }
+
+ //Test Error Ignoring behaviour
+ textinputObject->setCursorPosition(0);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->setSelectionStart(-10);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->setSelectionStart(100);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->setSelectionEnd(-10);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->setSelectionEnd(100);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->setSelectionStart(0);
+ textinputObject->setSelectionEnd(10);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->setSelectionStart(-10);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->setSelectionStart(100);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->setSelectionEnd(-10);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->setSelectionEnd(100);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+}
+
+void tst_qmlgraphicstextinput::maxLength()
+{
+ //QString componentStr = "import Qt 4.6\nTextInput { maximumLength: 10; }";
+ QmlView *canvas = createView(SRCDIR "/data/maxLength.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+ QVERIFY(canvas->root() != 0);
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput *>(canvas->root());
+ QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject->text().isEmpty());
+ QVERIFY(textinputObject->maxLength() == 10);
+ foreach(const QString &str, standard){
+ QVERIFY(textinputObject->text().length() <= 10);
+ textinputObject->setText(str);
+ QVERIFY(textinputObject->text().length() <= 10);
+ }
+
+ textinputObject->setText("");
+ QTRY_VERIFY(textinputObject->hasFocus() == true);
+ for(int i=0; i<20; i++){
+ QCOMPARE(textinputObject->text().length(), qMin(i,10));
+ //simulateKey(canvas, Qt::Key_A);
+ QTest::keyPress(canvas, Qt::Key_A);
+ QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
+ }
+}
+
+void tst_qmlgraphicstextinput::masks()
+{
+ //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
+ //QString componentStr = "import Qt 4.6\nTextInput { inputMask: 'HHHHhhhh'; }";
+ QmlView *canvas = createView(SRCDIR "/data/masks.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+ QVERIFY(canvas->root() != 0);
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput *>(canvas->root());
+ QVERIFY(textinputObject != 0);
+ QTRY_VERIFY(textinputObject->hasFocus() == true);
+ QVERIFY(textinputObject->text().length() == 0);
+ QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
+ for(int i=0; i<10; i++){
+ QCOMPARE(qMin(i,8), textinputObject->text().length());
+ QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
+ //simulateKey(canvas, Qt::Key_A);
+ QTest::keyPress(canvas, Qt::Key_A);
+ QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
+ }
+}
+
+void tst_qmlgraphicstextinput::validators()
+{
+ // Note that this test assumes that the validators are working properly
+ // so you may need to run their tests first. All validators are checked
+ // here to ensure that their exposure to QML is working.
+
+ QmlView *canvas = createView(SRCDIR "/data/validators.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+
+ QVERIFY(canvas->root() != 0);
+
+ QmlGraphicsTextInput *intInput = qobject_cast<QmlGraphicsTextInput *>(qvariant_cast<QObject *>(canvas->root()->property("intInput")));
+ QVERIFY(intInput);
+ intInput->setFocus(true);
+ QTRY_VERIFY(intInput->hasFocus());
+ QTest::keyPress(canvas, Qt::Key_1);
+ QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QCOMPARE(intInput->text(), QLatin1String("1"));
+ QCOMPARE(intInput->hasAcceptableInput(), false);
+ QTest::keyPress(canvas, Qt::Key_2);
+ QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
+ QCOMPARE(intInput->text(), QLatin1String("1"));
+ QCOMPARE(intInput->hasAcceptableInput(), false);
+ QTest::keyPress(canvas, Qt::Key_1);
+ QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QCOMPARE(intInput->text(), QLatin1String("11"));
+ QCOMPARE(intInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_0);
+ QTest::keyRelease(canvas, Qt::Key_0, Qt::NoModifier ,10);
+ QCOMPARE(intInput->text(), QLatin1String("11"));
+ QCOMPARE(intInput->hasAcceptableInput(), true);
+
+ QmlGraphicsTextInput *dblInput = qobject_cast<QmlGraphicsTextInput *>(qvariant_cast<QObject *>(canvas->root()->property("dblInput")));
+ QTRY_VERIFY(dblInput);
+ dblInput->setFocus(true);
+ QVERIFY(dblInput->hasFocus() == true);
+ QTest::keyPress(canvas, Qt::Key_1);
+ QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QCOMPARE(dblInput->text(), QLatin1String("1"));
+ QCOMPARE(dblInput->hasAcceptableInput(), false);
+ QTest::keyPress(canvas, Qt::Key_2);
+ QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
+ QCOMPARE(dblInput->text(), QLatin1String("12"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_Period);
+ QTest::keyRelease(canvas, Qt::Key_Period, Qt::NoModifier ,10);
+ QCOMPARE(dblInput->text(), QLatin1String("12."));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_1);
+ QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QCOMPARE(dblInput->text(), QLatin1String("12.1"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_1);
+ QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QCOMPARE(dblInput->text(), QLatin1String("12.11"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_1);
+ QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QCOMPARE(dblInput->text(), QLatin1String("12.11"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+
+ QmlGraphicsTextInput *strInput = qobject_cast<QmlGraphicsTextInput *>(qvariant_cast<QObject *>(canvas->root()->property("strInput")));
+ QTRY_VERIFY(strInput);
+ strInput->setFocus(true);
+ QVERIFY(strInput->hasFocus() == true);
+ QTest::keyPress(canvas, Qt::Key_1);
+ QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QEXPECT_FAIL("","Will not work until QTBUG-8025 is resolved", Abort);
+ QCOMPARE(strInput->text(), QLatin1String(""));
+ QCOMPARE(strInput->hasAcceptableInput(), false);
+ QTest::keyPress(canvas, Qt::Key_A);
+ QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QCOMPARE(strInput->text(), QLatin1String("a"));
+ QCOMPARE(strInput->hasAcceptableInput(), false);
+ QTest::keyPress(canvas, Qt::Key_A);
+ QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QCOMPARE(strInput->text(), QLatin1String("aa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_A);
+ QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QCOMPARE(strInput->text(), QLatin1String("aaa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_A);
+ QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QCOMPARE(strInput->text(), QLatin1String("aaaa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+ QTest::keyPress(canvas, Qt::Key_A);
+ QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QCOMPARE(strInput->text(), QLatin1String("aaaa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+}
+
+void tst_qmlgraphicstextinput::inputMethodHints()
+{
+ QmlView *canvas = createView(SRCDIR "/data/inputmethodhints.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+
+ QVERIFY(canvas->root() != 0);
+ QmlGraphicsTextInput *textinputObject = qobject_cast<QmlGraphicsTextInput *>(canvas->root());
+ QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject->inputMethodHints() & Qt::ImhNoPredictiveText);
+ textinputObject->setInputMethodHints(Qt::ImhUppercaseOnly);
+ QVERIFY(textinputObject->inputMethodHints() & Qt::ImhUppercaseOnly);
+}
+
+/*
+TextInput element should only handle left/right keys until the cursor reaches
+the extent of the text, then they should ignore the keys.
+*/
+void tst_qmlgraphicstextinput::navigation()
+{
+ QmlView *canvas = createView(SRCDIR "/data/navigation.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+
+ QVERIFY(canvas->root() != 0);
+
+ QmlGraphicsItem *input = qobject_cast<QmlGraphicsItem *>(qvariant_cast<QObject *>(canvas->root()->property("myInput")));
+
+ QVERIFY(input != 0);
+ QTRY_VERIFY(input->hasFocus() == true);
+ simulateKey(canvas, Qt::Key_Left);
+ QVERIFY(input->hasFocus() == false);
+ simulateKey(canvas, Qt::Key_Right);
+ QVERIFY(input->hasFocus() == true);
+ simulateKey(canvas, Qt::Key_Right);
+ QVERIFY(input->hasFocus() == false);
+ simulateKey(canvas, Qt::Key_Left);
+ QVERIFY(input->hasFocus() == true);
+}
+
+void tst_qmlgraphicstextinput::cursorDelegate()
+{
+ QmlView* view = createView(SRCDIR "/data/cursorTest.qml");
+ view->execute();
+ view->show();
+ view->setFocus();
+ QmlGraphicsTextInput *textInputObject = view->root()->findChild<QmlGraphicsTextInput*>("textInputObject");
+ QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject->findChild<QmlGraphicsItem*>("cursorInstance"));
+ //Test Delegate gets created
+ textInputObject->setFocus(true);
+ QmlGraphicsItem* delegateObject = textInputObject->findChild<QmlGraphicsItem*>("cursorInstance");
+ QVERIFY(delegateObject);
+ //Test Delegate gets moved
+ for(int i=0; i<= textInputObject->text().length(); i++){
+ textInputObject->setCursorPosition(i);
+ //+5 is because the TextInput cursorRect is just a 10xHeight area centered on cursor position
+ QCOMPARE(textInputObject->cursorRect().x() + 5, qRound(delegateObject->x()));
+ QCOMPARE(textInputObject->cursorRect().y(), qRound(delegateObject->y()));
+ }
+ textInputObject->setCursorPosition(0);
+ QCOMPARE(textInputObject->cursorRect().x()+5, qRound(delegateObject->x()));
+ QCOMPARE(textInputObject->cursorRect().y(), qRound(delegateObject->y()));
+ //Test Delegate gets deleted
+ textInputObject->setCursorDelegate(0);
+ QVERIFY(!textInputObject->findChild<QmlGraphicsItem*>("cursorInstance"));
+}
+
+void tst_qmlgraphicstextinput::readOnly()
+{
+ QmlView *canvas = createView(SRCDIR "/data/readOnly.qml");
+ canvas->execute();
+ canvas->show();
+ canvas->setFocus();
+
+ QVERIFY(canvas->root() != 0);
+
+ QmlGraphicsTextInput *input = qobject_cast<QmlGraphicsTextInput *>(qvariant_cast<QObject *>(canvas->root()->property("myInput")));
+
+ QVERIFY(input != 0);
+ QTRY_VERIFY(input->hasFocus() == true);
+ QVERIFY(input->isReadOnly() == true);
+ QString initial = input->text();
+ for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
+ simulateKey(canvas, k);
+ simulateKey(canvas, Qt::Key_Return);
+ simulateKey(canvas, Qt::Key_Space);
+ simulateKey(canvas, Qt::Key_Escape);
+ QCOMPARE(input->text(), initial);
+}
+
+void tst_qmlgraphicstextinput::simulateKey(QmlView *view, int key)
+{
+ QKeyEvent press(QKeyEvent::KeyPress, key, 0);
+ QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
+
+ QApplication::sendEvent(view, &press);
+ QApplication::sendEvent(view, &release);
+}
+
+QmlView *tst_qmlgraphicstextinput::createView(const QString &filename)
+{
+ QmlView *canvas = new QmlView(0);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setQml(xml, filename);
+
+ return canvas;
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : softwareInputPanelEventReceived(false) {}
+ ~MyInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+
+ bool isComposing() const { return false; }
+
+ bool filterEvent( const QEvent *event )
+ {
+ if (event->type() == QEvent::RequestSoftwareInputPanel)
+ softwareInputPanelEventReceived = true;
+ return QInputContext::filterEvent(event);
+ }
+ bool softwareInputPanelEventReceived;
+};
+
+void tst_qmlgraphicstextinput::sendRequestSoftwareInputPanelEvent()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ MyInputContext ic;
+ view.viewport()->setInputContext(&ic);
+ QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
+ view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
+ if ((behavior != QStyle::RSIP_OnMouseClick))
+ QSKIP("This test need to have a style with RSIP_OnMouseClick", SkipSingle);
+ QmlGraphicsTextInput input;
+ input.setText("Hello world");
+ input.setPos(0, 0);
+ scene.addItem(&input);
+ view.show();
+ qApp->setAutoSipEnabled(true);
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
+ QApplication::processEvents();
+ QCOMPARE(ic.softwareInputPanelEventReceived, true);
+}
+
+QTEST_MAIN(tst_qmlgraphicstextinput)
+
+#include "tst_qmlgraphicstextinput.moc"
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/basic.html b/tests/auto/declarative/qmlgraphicswebview/data/basic.html
new file mode 100644
index 0000000..22e3e24
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/basic.html
@@ -0,0 +1,17 @@
+<html>
+<head><title>Basic</title>
+<link rel="icon" sizes="48x48" href="basic.png">
+<script type="text/javascript">
+<!--
+window.onload = function(){ window.status = "status here"; }
+// -->
+</script>
+</head>
+<body leftmargin="0" marginwidth="0">
+<table width="123">
+<tbody>
+<tr><td>This is a basic test.</td></tr>
+</tbody>
+</table>
+</body>
+</html>
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/basic.ico b/tests/auto/declarative/qmlgraphicswebview/data/basic.ico
new file mode 100644
index 0000000..8f3d05e
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/basic.ico
Binary files differ
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/basic.png b/tests/auto/declarative/qmlgraphicswebview/data/basic.png
new file mode 100644
index 0000000..35717cc
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/basic.png
Binary files differ
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/basic.qml b/tests/auto/declarative/qmlgraphicswebview/data/basic.qml
new file mode 100644
index 0000000..5394837
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/basic.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+WebView {
+ url: "basic.html"
+}
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/elements.html b/tests/auto/declarative/qmlgraphicswebview/data/elements.html
new file mode 100644
index 0000000..9236867
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/elements.html
@@ -0,0 +1,14 @@
+<body leftmargin=0 topmargin=0>
+<table width="300px" border=1 cellpadding=0 cellspacing=0>
+<tr>
+<td align=center width=25%%><p>A</p></td>
+<td width=75% height=50px>
+ <table width=100% border=1 cellpadding=0 cellspacing=0>
+ <tr>
+ <td align=center width=50% height=50px><p>B</p></td>
+ <td align=center width=50% height=50px><p>C</p></td>
+ </tr>
+ </table>
+</td>
+</tr>
+</table>
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/elements.qml b/tests/auto/declarative/qmlgraphicswebview/data/elements.qml
new file mode 100644
index 0000000..7c030e6
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/elements.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+WebView {
+ url: "elements.html"
+ width: 310
+ height: 100
+}
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/forward.html b/tests/auto/declarative/qmlgraphicswebview/data/forward.html
new file mode 100644
index 0000000..030446a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/forward.html
@@ -0,0 +1,12 @@
+<html>
+<head><title>Forward</title>
+<link rel="icon" sizes="48x48" href="basic.png">
+</head>
+<body leftmargin="0" marginwidth="0">
+<table width="123">
+<tbody>
+<tr><td>This is more.</td></tr>
+</tbody>
+</table>
+</body>
+</html>
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/javaScript.html b/tests/auto/declarative/qmlgraphicswebview/data/javaScript.html
new file mode 100644
index 0000000..35270bc
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/javaScript.html
@@ -0,0 +1,11 @@
+<html>
+<head><title>JavaScript</title>
+<link rel="icon" sizes="48x48" href="basic.png">
+<script type="text/javascript">
+<!--
+window.onload = function(){ window.status = "status here"; }
+// -->
+</script>
+</head>
+<body>
+This is a JS test.
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/javaScript.qml b/tests/auto/declarative/qmlgraphicswebview/data/javaScript.qml
new file mode 100644
index 0000000..07eee88
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/javaScript.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+WebView {
+ url: "javaScript.html"
+ javaScriptWindowObjects: [
+ QtObject {
+ property string qmlprop: "qmlvalue"
+ WebView.windowObjectName: "myjsname"
+ }
+ ]
+}
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/loadError.qml b/tests/auto/declarative/qmlgraphicswebview/data/loadError.qml
new file mode 100644
index 0000000..1460f30
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/loadError.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+WebView {
+ url: "does-not-exist.html"
+}
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/newwindows.html b/tests/auto/declarative/qmlgraphicswebview/data/newwindows.html
new file mode 100644
index 0000000..dd541f9
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/newwindows.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+<script type="text/javascript">
+<!--
+function clickTheLink()
+{
+ var ev = document.createEvent('MouseEvents');
+ ev.initEvent( "click", true, false );
+ document.getElementById('thelink').dispatchEvent(ev);
+}
+// -->
+</script>
+</head>
+<h1>Multiple windows...</h1>
+
+<a id=thelink target="_blank" href="newwindows.html">Popup!</a>
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/newwindows.qml b/tests/auto/declarative/qmlgraphicswebview/data/newwindows.qml
new file mode 100644
index 0000000..b8524af
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/newwindows.qml
@@ -0,0 +1,32 @@
+// Demonstrates opening new WebViews from HTML
+
+import Qt 4.6
+
+Grid {
+ columns: 3
+ id: pages
+ height: 300; width: 600
+ property int total: 0
+
+ Component {
+ id: webViewPage
+ Rectangle {
+ width: webView.width
+ height: webView.height
+ border.color: "gray"
+
+ WebView {
+ id: webView
+ newWindowComponent: webViewPage
+ newWindowParent: pages
+ url: "newwindows.html"
+ Timer {
+ interval: 10; running: webView.status==WebView.Ready && total<4; repeat: false;
+ onTriggered: {total++; webView.evaluateJavaScript("clickTheLink()")}
+ }
+ }
+ }
+ }
+
+ Loader { sourceComponent: webViewPage }
+}
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/pixelCache.html b/tests/auto/declarative/qmlgraphicswebview/data/pixelCache.html
new file mode 100644
index 0000000..9412674
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/pixelCache.html
@@ -0,0 +1,10 @@
+<html>
+<body topmargin=0 leftmargin=0>
+<table width=120 cellpadding=0 cellspacing=0>
+<tr><td>
+<h1>Pixel Cache</h1>
+This test is for the pixel cache. Because this is a long document,
+as it scrolls, more of the document will need to be rendered.
+If the pixelCacheSize is small, the first parts of the document will
+no longer be in the cache when it returns.
+</table>
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/pixelCache.qml b/tests/auto/declarative/qmlgraphicswebview/data/pixelCache.qml
new file mode 100644
index 0000000..08e4d65
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/pixelCache.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyWebView {
+ anchors.fill: parent
+ url: "pixelCache.html"
+}
diff --git a/tests/auto/declarative/qmlgraphicswebview/data/sethtml.qml b/tests/auto/declarative/qmlgraphicswebview/data/sethtml.qml
new file mode 100644
index 0000000..063b5a8
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/data/sethtml.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+WebView {
+ html: "<p>This is a <b>string</b> set on the WebView"
+}
diff --git a/tests/auto/declarative/qmlgraphicswebview/qmlgraphicswebview.pro b/tests/auto/declarative/qmlgraphicswebview/qmlgraphicswebview.pro
new file mode 100644
index 0000000..a590616
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/qmlgraphicswebview.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+contains(QT_CONFIG,webkit): QT += webkit
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicswebview.cpp testtypes.cpp
+HEADERS += testtypes.h
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicswebview/testtypes.cpp b/tests/auto/declarative/qmlgraphicswebview/testtypes.cpp
new file mode 100644
index 0000000..e21f286
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/testtypes.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "testtypes.h"
+
+void MyWebView::drawContents(QPainter *p, const QRect &r)
+{
+ pp += r.width()*r.height();
+ QmlGraphicsWebView::drawContents(p,r);
+}
+
+QML_DEFINE_TYPE(Test,1,0,MyWebView,MyWebView);
diff --git a/tests/auto/declarative/qmlgraphicswebview/testtypes.h b/tests/auto/declarative/qmlgraphicswebview/testtypes.h
new file mode 100644
index 0000000..7ab7c78
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/testtypes.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TESTTYPES_H
+#define TESTTYPES_H
+
+#include <private/qmlgraphicswebview_p.h>
+
+class MyWebView : public QmlGraphicsWebView
+{
+ Q_OBJECT
+ Q_PROPERTY(int pixelsPainted READ pixelsPainted);
+
+public:
+ MyWebView() : pp(0) {}
+
+ int pixelsPainted() const { return pp; }
+
+ void drawContents(QPainter *p, const QRect &r);
+
+private:
+ int pp;
+};
+
+QML_DECLARE_TYPE(MyWebView);
+
+#endif // TESTTYPES_H
diff --git a/tests/auto/declarative/qmlgraphicswebview/tst_qmlgraphicswebview.cpp b/tests/auto/declarative/qmlgraphicswebview/tst_qmlgraphicswebview.cpp
new file mode 100644
index 0000000..6996a6c
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicswebview/tst_qmlgraphicswebview.cpp
@@ -0,0 +1,393 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include "../../../shared/util.h"
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicswebview_p.h>
+#include <private/qmlgraphicswebview_p_p.h>
+#include <private/qmlgraphicspositioners_p.h>
+#include <QtWebKit/qwebpage.h>
+#include <QtWebKit/qwebframe.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtGui/qpainter.h>
+#include "testtypes.h"
+
+class tst_qmlgraphicswebview : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlgraphicswebview() {}
+
+private slots:
+ void basicProperties();
+ void settings();
+ void historyNav();
+ void multipleWindows();
+ void elementAreaAt();
+ void loadError();
+ void setHtml();
+ void javaScript();
+ void cleanupTestCase();
+ void pixelCache();
+
+private:
+ void checkNoErrors(const QmlComponent& component);
+ QmlEngine engine;
+ QString tmpDir() const
+ {
+ static QString tmpd = QDir::tempPath()+"/tst_qmlgraphicswebview-"
+ + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss"));
+ return tmpd;
+ }
+};
+
+static QString strippedHtml(QString html)
+{
+ html.replace(QRegExp("\\s+"),"");
+ return html;
+}
+
+static QString fileContents(const QString& filename)
+{
+ QFile file(filename);
+ file.open(QIODevice::ReadOnly);
+ return QString::fromUtf8(file.readAll());
+}
+
+
+static void removeRecursive(const QString& dirname)
+{
+ QDir dir(dirname);
+ QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot));
+ for (int i = 0; i < entries.count(); ++i)
+ if (entries[i].isDir())
+ removeRecursive(entries[i].filePath());
+ else
+ dir.remove(entries[i].fileName());
+ QDir().rmdir(dirname);
+}
+
+void tst_qmlgraphicswebview::cleanupTestCase()
+{
+ removeRecursive(tmpDir());
+}
+
+void tst_qmlgraphicswebview::checkNoErrors(const QmlComponent& component)
+{
+ // Wait until the component is ready
+ QTRY_VERIFY(component.isReady());
+
+
+ if (component.isError()) {
+ QList<QmlError> errors = component.errors();
+ for (int ii = 0; ii < errors.count(); ++ii) {
+ const QmlError &error = errors.at(ii);
+ QByteArray errorStr = QByteArray::number(error.line()) + ":" +
+ QByteArray::number(error.column()) + ":" +
+ error.description().toUtf8();
+ qWarning() << errorStr;
+ }
+ }
+ QVERIFY(!component.isError());
+}
+
+void tst_qmlgraphicswebview::basicProperties()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml"));
+ checkNoErrors(component);
+ QWebSettings::enablePersistentStorage(tmpDir());
+
+ QmlGraphicsWebView *wv = qobject_cast<QmlGraphicsWebView*>(component.create());
+ QVERIFY(wv != 0);
+ QTRY_COMPARE(wv->progress(), 1.0);
+ QCOMPARE(wv->title(),QString("Basic"));
+ QTRY_COMPARE(wv->icon().width(), 48);
+ QCOMPARE(wv->icon(),QPixmap(SRCDIR "/data/basic.png"));
+ QCOMPARE(wv->statusText(),QString("status here"));
+ QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->html()));
+ QCOMPARE(wv->width(), 123.0);
+ QCOMPARE(wv->preferredWidth(), 0);
+ QCOMPARE(wv->preferredHeight(), 0);
+ QCOMPARE(wv->zoomFactor(), 1.0);
+ QCOMPARE(wv->url(), QUrl::fromLocalFile(SRCDIR "/data/basic.html"));
+ QCOMPARE(wv->status(), QmlGraphicsWebView::Ready);
+ QVERIFY(wv->reloadAction());
+ QVERIFY(wv->reloadAction()->isEnabled());
+ QVERIFY(wv->backAction());
+ QVERIFY(!wv->backAction()->isEnabled());
+ QVERIFY(wv->forwardAction());
+ QVERIFY(!wv->forwardAction()->isEnabled());
+ QVERIFY(wv->stopAction());
+ QVERIFY(!wv->stopAction()->isEnabled());
+
+ wv->setPixelCacheSize(0); // mainly testing that it doesn't crash or anything!
+ QCOMPARE(wv->pixelCacheSize(),0);
+ wv->reloadAction()->trigger();
+ QTRY_COMPARE(wv->progress(), 1.0);
+}
+
+void tst_qmlgraphicswebview::settings()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml"));
+ checkNoErrors(component);
+ QmlGraphicsWebView *wv = qobject_cast<QmlGraphicsWebView*>(component.create());
+ QVERIFY(wv != 0);
+ QTRY_COMPARE(wv->progress(), 1.0);
+
+ QmlGraphicsWebSettings *s = wv->settingsObject();
+
+ // merely tests that setting gets stored (in QWebSettings)
+ // behavioural tests are in WebKit.
+ for (int b=0; b<=1; ++b) {
+ bool on = !!b;
+
+ s->setAutoLoadImages(on);
+ s->setDeveloperExtrasEnabled(on);
+ s->setJavaEnabled(on);
+ s->setJavascriptCanAccessClipboard(on);
+ s->setJavascriptCanOpenWindows(on);
+ s->setJavascriptEnabled(on);
+ s->setLinksIncludedInFocusChain(on);
+ s->setLocalContentCanAccessRemoteUrls(on);
+ s->setLocalStorageDatabaseEnabled(on);
+ s->setOfflineStorageDatabaseEnabled(on);
+ s->setOfflineWebApplicationCacheEnabled(on);
+ s->setPluginsEnabled(on);
+ s->setPrintElementBackgrounds(on);
+ s->setPrivateBrowsingEnabled(on);
+ s->setZoomTextOnly(on);
+
+ QVERIFY(s->autoLoadImages() == on);
+ QVERIFY(s->developerExtrasEnabled() == on);
+ QVERIFY(s->javaEnabled() == on);
+ QVERIFY(s->javascriptCanAccessClipboard() == on);
+ QVERIFY(s->javascriptCanOpenWindows() == on);
+ QVERIFY(s->javascriptEnabled() == on);
+ QVERIFY(s->linksIncludedInFocusChain() == on);
+ QVERIFY(s->localContentCanAccessRemoteUrls() == on);
+ QVERIFY(s->localStorageDatabaseEnabled() == on);
+ QVERIFY(s->offlineStorageDatabaseEnabled() == on);
+ QVERIFY(s->offlineWebApplicationCacheEnabled() == on);
+ QVERIFY(s->pluginsEnabled() == on);
+ QVERIFY(s->printElementBackgrounds() == on);
+ QVERIFY(s->privateBrowsingEnabled() == on);
+ QVERIFY(s->zoomTextOnly() == on);
+
+ QVERIFY(s->property("autoLoadImages") == on);
+ QVERIFY(s->property("developerExtrasEnabled") == on);
+ QVERIFY(s->property("javaEnabled") == on);
+ QVERIFY(s->property("javascriptCanAccessClipboard") == on);
+ QVERIFY(s->property("javascriptCanOpenWindows") == on);
+ QVERIFY(s->property("javascriptEnabled") == on);
+ QVERIFY(s->property("linksIncludedInFocusChain") == on);
+ QVERIFY(s->property("localContentCanAccessRemoteUrls") == on);
+ QVERIFY(s->property("localStorageDatabaseEnabled") == on);
+ QVERIFY(s->property("offlineStorageDatabaseEnabled") == on);
+ QVERIFY(s->property("offlineWebApplicationCacheEnabled") == on);
+ QVERIFY(s->property("pluginsEnabled") == on);
+ QVERIFY(s->property("printElementBackgrounds") == on);
+ QVERIFY(s->property("privateBrowsingEnabled") == on);
+ QVERIFY(s->property("zoomTextOnly") == on);
+ }
+}
+
+void tst_qmlgraphicswebview::historyNav()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml"));
+ checkNoErrors(component);
+ QWebSettings::enablePersistentStorage(tmpDir());
+
+ QmlGraphicsWebView *wv = qobject_cast<QmlGraphicsWebView*>(component.create());
+ QVERIFY(wv != 0);
+ for (int i=1; i<=2; ++i) {
+ QTRY_COMPARE(wv->progress(), 1.0);
+ QCOMPARE(wv->title(),QString("Basic"));
+ QTRY_COMPARE(wv->icon().width(), 48);
+ QCOMPARE(wv->icon(),QPixmap(SRCDIR "/data/basic.png"));
+ QCOMPARE(wv->statusText(),QString("status here"));
+ QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->html()));
+ QCOMPARE(wv->width(), 123.0);
+ QCOMPARE(wv->preferredWidth(), 0);
+ QCOMPARE(wv->zoomFactor(), 1.0);
+ QCOMPARE(wv->url(), QUrl::fromLocalFile(SRCDIR "/data/basic.html"));
+ QCOMPARE(wv->status(), QmlGraphicsWebView::Ready);
+ QVERIFY(wv->reloadAction());
+ QVERIFY(wv->reloadAction()->isEnabled());
+ QVERIFY(wv->backAction());
+ QVERIFY(!wv->backAction()->isEnabled());
+ QVERIFY(wv->forwardAction());
+ QVERIFY(!wv->forwardAction()->isEnabled());
+ QVERIFY(wv->stopAction());
+ QVERIFY(!wv->stopAction()->isEnabled());
+
+ wv->reloadAction()->trigger();
+ }
+
+ wv->setUrl(QUrl::fromLocalFile(SRCDIR "/data/forward.html"));
+ QTRY_COMPARE(wv->progress(), 1.0);
+ QCOMPARE(wv->title(),QString("Forward"));
+ QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/forward.html")), strippedHtml(wv->html()));
+ QCOMPARE(wv->url(), QUrl::fromLocalFile(SRCDIR "/data/forward.html"));
+ QCOMPARE(wv->status(), QmlGraphicsWebView::Ready);
+ QCOMPARE(wv->statusText(),QString(""));
+ QVERIFY(wv->reloadAction());
+ QVERIFY(wv->reloadAction()->isEnabled());
+ QVERIFY(wv->backAction());
+ QVERIFY(wv->backAction()->isEnabled());
+ QVERIFY(wv->forwardAction());
+ QVERIFY(!wv->forwardAction()->isEnabled());
+ QVERIFY(wv->stopAction());
+ QVERIFY(!wv->stopAction()->isEnabled());
+
+ wv->backAction()->trigger();
+
+ QTRY_COMPARE(wv->progress(), 1.0);
+ QCOMPARE(wv->title(),QString("Basic"));
+ QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->html()));
+ QCOMPARE(wv->url(), QUrl::fromLocalFile(SRCDIR "/data/basic.html"));
+ QCOMPARE(wv->status(), QmlGraphicsWebView::Ready);
+ QVERIFY(wv->reloadAction());
+ QVERIFY(wv->reloadAction()->isEnabled());
+ QVERIFY(wv->backAction());
+ QVERIFY(!wv->backAction()->isEnabled());
+ QVERIFY(wv->forwardAction());
+ QVERIFY(wv->forwardAction()->isEnabled());
+ QVERIFY(wv->stopAction());
+ QVERIFY(!wv->stopAction()->isEnabled());
+}
+
+void tst_qmlgraphicswebview::multipleWindows()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/newwindows.qml"));
+ checkNoErrors(component);
+
+ QmlGraphicsGrid *grid = qobject_cast<QmlGraphicsGrid*>(component.create());
+ QVERIFY(grid != 0);
+ QTRY_COMPARE(grid->children().count(), 2+5); // Component, Loader, 5 WebViews
+}
+
+void tst_qmlgraphicswebview::loadError()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/loadError.qml"));
+ checkNoErrors(component);
+ QWebSettings::enablePersistentStorage(tmpDir());
+
+ QmlGraphicsWebView *wv = qobject_cast<QmlGraphicsWebView*>(component.create());
+ QVERIFY(wv != 0);
+ for (int i=1; i<=2; ++i) {
+ QTRY_COMPARE(wv->progress(), 1.0);
+ QCOMPARE(wv->title(),QString(""));
+ QCOMPARE(wv->statusText(),QString("")); // HTML 'status bar' text, not error message
+ QCOMPARE(wv->url(), QUrl::fromLocalFile(SRCDIR "/data/does-not-exist.html")); // Unlike QWebPage, which loses url
+ QCOMPARE(wv->status(), QmlGraphicsWebView::Error);
+
+ wv->reloadAction()->trigger();
+ }
+}
+
+void tst_qmlgraphicswebview::setHtml()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/sethtml.qml"));
+ checkNoErrors(component);
+ QmlGraphicsWebView *wv = qobject_cast<QmlGraphicsWebView*>(component.create());
+ QVERIFY(wv != 0);
+ QCOMPARE(wv->html(),QString("<html><head></head><body><p>This is a <b>string</b> set on the WebView</p></body></html>"));
+}
+
+void tst_qmlgraphicswebview::elementAreaAt()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/elements.qml"));
+ checkNoErrors(component);
+ QmlGraphicsWebView *wv = qobject_cast<QmlGraphicsWebView*>(component.create());
+ QVERIFY(wv != 0);
+ QTRY_COMPARE(wv->progress(), 1.0);
+
+ QCOMPARE(wv->elementAreaAt(40,30,100,100),QRect(1,1,75,54)); // Area A in data/elements.html
+ QCOMPARE(wv->elementAreaAt(130,30,200,100),QRect(78,3,110,50)); // Area B
+ QCOMPARE(wv->elementAreaAt(40,30,400,400),QRect(0,0,310,100)); // Whole view
+ QCOMPARE(wv->elementAreaAt(130,30,280,280),QRect(76,1,223,54)); // Area BC
+ QCOMPARE(wv->elementAreaAt(130,30,400,400),QRect(0,0,310,100)); // Whole view
+}
+
+void tst_qmlgraphicswebview::javaScript()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/javaScript.qml"));
+ checkNoErrors(component);
+ QmlGraphicsWebView *wv = qobject_cast<QmlGraphicsWebView*>(component.create());
+ QVERIFY(wv != 0);
+ QTRY_COMPARE(wv->progress(), 1.0);
+ QCOMPARE(wv->evaluateJavaScript("123").toInt(), 123);
+ QCOMPARE(wv->evaluateJavaScript("window.status").toString(), QString("status here"));
+ QCOMPARE(wv->evaluateJavaScript("window.myjsname.qmlprop").toString(), QString("qmlvalue"));
+}
+
+void tst_qmlgraphicswebview::pixelCache()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/pixelCache.qml"));
+ checkNoErrors(component);
+ MyWebView *wv = qobject_cast<MyWebView*>(component.create());
+ QVERIFY(wv != 0);
+ QTRY_COMPARE(wv->progress(), 1.0);
+ QPixmap pm(150,150);
+ QPainter p(&pm);
+ wv->paint(&p,0,0);
+ const int expected = 120*(150+128); // 120 = width of HTML page, 150=pixmap height, 128=cache extra area
+ QCOMPARE(wv->pixelsPainted(), expected);
+ wv->paint(&p,0,0);
+ QCOMPARE(wv->pixelsPainted(), expected); // nothing new needed to be painted
+ wv->setPixelCacheSize(0); // clears the cache
+ wv->paint(&p,0,0);
+ QCOMPARE(wv->pixelsPainted(), expected*2); // everything needed to be painted
+ // Note that painted things always go into the cache (even if they don't "fit"),
+ // just that they will be removed if anything else needs to be painted.
+ wv->setPixelCacheSize(expected); // won't clear the cache
+ wv->paint(&p,0,0);
+ QCOMPARE(wv->pixelsPainted(), expected*2); // still there
+ wv->setPixelCacheSize(expected-1); // too small - will clear the cache
+ wv->paint(&p,0,0);
+ QCOMPARE(wv->pixelsPainted(), expected*3); // repainted
+}
+
+QTEST_MAIN(tst_qmlgraphicswebview)
+
+#include "tst_qmlgraphicswebview.moc"
diff --git a/tests/auto/declarative/qmlinfo/data/NestedObject.qml b/tests/auto/declarative/qmlinfo/data/NestedObject.qml
new file mode 100644
index 0000000..cd5b426
--- /dev/null
+++ b/tests/auto/declarative/qmlinfo/data/NestedObject.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property var nested
+
+ nested: QtObject {}
+}
+
diff --git a/tests/auto/declarative/qmlinfo/data/nestedQmlObject.qml b/tests/auto/declarative/qmlinfo/data/nestedQmlObject.qml
new file mode 100644
index 0000000..a2ce78a
--- /dev/null
+++ b/tests/auto/declarative/qmlinfo/data/nestedQmlObject.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property var nested
+ nested: NestedObject { }
+ property var nested2: nested.nested
+}
+
diff --git a/tests/auto/declarative/qmlinfo/data/qmlObject.qml b/tests/auto/declarative/qmlinfo/data/qmlObject.qml
new file mode 100644
index 0000000..ce05f89
--- /dev/null
+++ b/tests/auto/declarative/qmlinfo/data/qmlObject.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property var nested
+
+ nested: QtObject {
+ }
+}
diff --git a/tests/auto/declarative/qmlinfo/qmlinfo.pro b/tests/auto/declarative/qmlinfo/qmlinfo.pro
new file mode 100644
index 0000000..dbebf92
--- /dev/null
+++ b/tests/auto/declarative/qmlinfo/qmlinfo.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlinfo.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlinfo/tst_qmlinfo.cpp b/tests/auto/declarative/qmlinfo/tst_qmlinfo.cpp
new file mode 100644
index 0000000..880f7b8
--- /dev/null
+++ b/tests/auto/declarative/qmlinfo/tst_qmlinfo.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QPushButton>
+#include <QmlContext>
+#include <qmlinfo.h>
+
+class tst_qmlinfo : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlinfo() {}
+
+private slots:
+ void qmlObject();
+ void nestedQmlObject();
+ void nonQmlObject();
+ void nullObject();
+ void nonQmlContextedObject();
+
+private:
+ QmlEngine engine;
+};
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
+}
+
+void tst_qmlinfo::qmlObject()
+{
+ QmlComponent component(&engine, TEST_FILE("qmlObject.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QString message = "QML QObject_QML_0 (" + component.url().toString() + ":3:1) Test Message";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ qmlInfo(object) << "Test Message";
+
+ QObject *nested = qvariant_cast<QObject *>(object->property("nested"));
+ QVERIFY(nested != 0);
+
+ message = "QML QtObject (" + component.url().toString() + ":6:13) Second Test Message";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ qmlInfo(nested) << "Second Test Message";
+}
+
+void tst_qmlinfo::nestedQmlObject()
+{
+ QmlComponent component(&engine, TEST_FILE("nestedQmlObject.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QObject *nested = qvariant_cast<QObject *>(object->property("nested"));
+ QVERIFY(nested != 0);
+ QObject *nested2 = qvariant_cast<QObject *>(object->property("nested2"));
+ QVERIFY(nested2 != 0);
+
+ QString message = "QML NestedObject (" + component.url().toString() + ":5:13) Outer Object";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ qmlInfo(nested) << "Outer Object";
+
+ message = "QML QtObject (" + TEST_FILE("NestedObject.qml").toString() + ":6:14) Inner Object";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ qmlInfo(nested2) << "Inner Object";
+}
+
+void tst_qmlinfo::nonQmlObject()
+{
+ QObject object;
+ QTest::ignoreMessage(QtWarningMsg, "QML QtObject (unknown location) Test Message");
+ qmlInfo(&object) << "Test Message";
+
+ QPushButton pbObject;
+ QTest::ignoreMessage(QtWarningMsg, "QML QPushButton (unknown location) Test Message");
+ qmlInfo(&pbObject) << "Test Message";
+}
+
+void tst_qmlinfo::nullObject()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QML (unknown location) Null Object Test Message");
+ qmlInfo(0) << "Null Object Test Message";
+}
+
+void tst_qmlinfo::nonQmlContextedObject()
+{
+ QObject object;
+ QmlContext context(&engine);
+ QmlEngine::setContextForObject(&object, &context);
+ QTest::ignoreMessage(QtWarningMsg, "QML QtObject (unknown location) Test Message");
+ qmlInfo(&object) << "Test Message";
+}
+
+QTEST_MAIN(tst_qmlinfo)
+
+#include "tst_qmlinfo.moc"
diff --git a/tests/auto/declarative/qmlinstruction/qmlinstruction.pro b/tests/auto/declarative/qmlinstruction/qmlinstruction.pro
new file mode 100644
index 0000000..41be488
--- /dev/null
+++ b/tests/auto/declarative/qmlinstruction/qmlinstruction.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative script
+SOURCES += tst_qmlinstruction.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlinstruction/tst_qmlinstruction.cpp b/tests/auto/declarative/qmlinstruction/tst_qmlinstruction.cpp
new file mode 100644
index 0000000..ea99a9e
--- /dev/null
+++ b/tests/auto/declarative/qmlinstruction/tst_qmlinstruction.cpp
@@ -0,0 +1,603 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <private/qmlcompiler_p.h>
+
+class tst_qmlinstruction : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlinstruction() {}
+
+private slots:
+ void dump();
+};
+
+static QStringList messages;
+static void msgHandler(QtMsgType, const char *msg)
+{
+ messages << QLatin1String(msg);
+}
+
+void tst_qmlinstruction::dump()
+{
+ QmlCompiledData *data = new QmlCompiledData(0);
+ {
+ QmlInstruction i;
+ i.line = 0;
+ i.type = QmlInstruction::Init;
+ i.init.bindingsSize = 0;
+ i.init.parserStatusSize = 3;
+ i.init.contextCache = -1;
+ i.init.compiledBinding = -1;
+ data->bytecode << i;
+ }
+
+ {
+ QmlCompiledData::TypeReference ref;
+ ref.className = "Test";
+ data->types << ref;
+
+ QmlInstruction i;
+ i.line = 1;
+ i.type = QmlInstruction::CreateObject;
+ i.create.type = 0;
+ i.create.data = -1;
+ i.create.bindingBits = -1;
+ i.create.column = 10;
+ data->bytecode << i;
+ }
+
+ {
+ data->primitives << "testId";
+
+ QmlInstruction i;
+ i.line = 2;
+ i.type = QmlInstruction::SetId;
+ i.setId.value = 0;
+ i.setId.index = 0;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 3;
+ i.type = QmlInstruction::SetDefault;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 4;
+ i.type = QmlInstruction::CreateComponent;
+ i.createComponent.count = 3;
+ i.createComponent.column = 4;
+ i.createComponent.endLine = 14;
+ i.createComponent.metaObject = 0;
+
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 5;
+ i.type = QmlInstruction::StoreMetaObject;
+ i.storeMeta.data = 3;
+ i.storeMeta.aliasData = 6;
+ i.storeMeta.propertyCache = 7;
+
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 6;
+ i.type = QmlInstruction::StoreFloat;
+ i.storeFloat.propertyIndex = 3;
+ i.storeFloat.value = 11.3;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 7;
+ i.type = QmlInstruction::StoreDouble;
+ i.storeDouble.propertyIndex = 4;
+ i.storeDouble.value = 14.8;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 8;
+ i.type = QmlInstruction::StoreInteger;
+ i.storeInteger.propertyIndex = 5;
+ i.storeInteger.value = 9;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 9;
+ i.type = QmlInstruction::StoreBool;
+ i.storeBool.propertyIndex = 6;
+ i.storeBool.value = true;
+
+ data->bytecode << i;
+ }
+
+ {
+ data->primitives << "Test String";
+ QmlInstruction i;
+ i.line = 10;
+ i.type = QmlInstruction::StoreString;
+ i.storeString.propertyIndex = 7;
+ i.storeString.value = 1;
+ data->bytecode << i;
+ }
+
+ {
+ data->primitives << "http://www.nokia.com";
+ QmlInstruction i;
+ i.line = 11;
+ i.type = QmlInstruction::StoreUrl;
+ i.storeUrl.propertyIndex = 8;
+ i.storeUrl.value = 2;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 12;
+ i.type = QmlInstruction::StoreColor;
+ i.storeColor.propertyIndex = 9;
+ i.storeColor.value = 0xFF00FF00;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 13;
+ i.type = QmlInstruction::StoreDate;
+ i.storeDate.propertyIndex = 10;
+ i.storeDate.value = 9;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 14;
+ i.type = QmlInstruction::StoreTime;
+ i.storeTime.propertyIndex = 11;
+ i.storeTime.valueIndex = 33;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 15;
+ i.type = QmlInstruction::StoreDateTime;
+ i.storeDateTime.propertyIndex = 12;
+ i.storeDateTime.valueIndex = 44;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 16;
+ i.type = QmlInstruction::StorePoint;
+ i.storeRealPair.propertyIndex = 13;
+ i.storeRealPair.valueIndex = 3;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 17;
+ i.type = QmlInstruction::StorePointF;
+ i.storeRealPair.propertyIndex = 14;
+ i.storeRealPair.valueIndex = 9;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 18;
+ i.type = QmlInstruction::StoreSize;
+ i.storeRealPair.propertyIndex = 15;
+ i.storeRealPair.valueIndex = 8;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 19;
+ i.type = QmlInstruction::StoreSizeF;
+ i.storeRealPair.propertyIndex = 16;
+ i.storeRealPair.valueIndex = 99;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 20;
+ i.type = QmlInstruction::StoreRect;
+ i.storeRect.propertyIndex = 17;
+ i.storeRect.valueIndex = 2;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 21;
+ i.type = QmlInstruction::StoreRectF;
+ i.storeRect.propertyIndex = 18;
+ i.storeRect.valueIndex = 19;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 22;
+ i.type = QmlInstruction::StoreVector3D;
+ i.storeVector3D.propertyIndex = 19;
+ i.storeVector3D.valueIndex = 9;
+ data->bytecode << i;
+ }
+
+ {
+ data->primitives << "color(1, 1, 1, 1)";
+ QmlInstruction i;
+ i.line = 23;
+ i.type = QmlInstruction::StoreVariant;
+ i.storeString.propertyIndex = 20;
+ i.storeString.value = 3;
+
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 24;
+ i.type = QmlInstruction::StoreObject;
+ i.storeObject.propertyIndex = 21;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 25;
+ i.type = QmlInstruction::StoreVariantObject;
+ i.storeObject.propertyIndex = 22;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 26;
+ i.type = QmlInstruction::StoreInterface;
+ i.storeObject.propertyIndex = 23;
+ data->bytecode << i;
+ }
+
+ {
+ data->primitives << "console.log(1921)";
+
+ QmlInstruction i;
+ i.line = 27;
+ i.type = QmlInstruction::StoreSignal;
+ i.storeSignal.signalIndex = 2;
+ i.storeSignal.value = 4;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 28;
+ i.type = QmlInstruction::StoreScript;
+ i.storeScript.value = 2;
+ //i.storeScript.fileName = 18;
+ //i.storeScript.lineNumber = 28;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 29;
+ i.type = QmlInstruction::StoreScriptString;
+ i.storeScriptString.propertyIndex = 24;
+ i.storeScriptString.value = 3;
+ i.storeScriptString.scope = 1;
+ data->bytecode << i;
+ }
+
+ {
+ data->datas << "mySignal";
+
+ QmlInstruction i;
+ i.line = 30;
+ i.type = QmlInstruction::AssignSignalObject;
+ i.assignSignalObject.signal = 0;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 31;
+ i.type = QmlInstruction::AssignCustomType;
+ i.assignCustomType.propertyIndex = 25;
+ i.assignCustomType.valueIndex = 4;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 32;
+ i.type = QmlInstruction::StoreBinding;
+ i.assignBinding.property = 26;
+ i.assignBinding.value = 3;
+ i.assignBinding.context = 2;
+ i.assignBinding.owner = 0;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 33;
+ i.type = QmlInstruction::StoreCompiledBinding;
+ i.assignBinding.property = 27;
+ i.assignBinding.value = 2;
+ i.assignBinding.context = 4;
+ i.assignBinding.owner = 0;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 34;
+ i.type = QmlInstruction::StoreValueSource;
+ i.assignValueSource.property = 29;
+ i.assignValueSource.owner = 1;
+ i.assignValueSource.castValue = 4;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 35;
+ i.type = QmlInstruction::StoreValueInterceptor;
+ i.assignValueInterceptor.property = 30;
+ i.assignValueInterceptor.owner = 2;
+ i.assignValueInterceptor.castValue = -4;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 36;
+ i.type = QmlInstruction::BeginObject;
+ i.begin.castValue = 4;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 37;
+ i.type = QmlInstruction::StoreObjectQmlList;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 38;
+ i.type = QmlInstruction::StoreObjectQList;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 39;
+ i.type = QmlInstruction::AssignObjectList;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 40;
+ i.type = QmlInstruction::FetchAttached;
+ i.fetchAttached.id = 23;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 41;
+ i.type = QmlInstruction::FetchQmlList;
+ i.fetchQmlList.property = 31;
+ i.fetchQmlList.type = 3;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 42;
+ i.type = QmlInstruction::FetchQList;
+ i.fetch.property = 32;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 43;
+ i.type = QmlInstruction::FetchObject;
+ i.fetch.property = 33;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 44;
+ i.type = QmlInstruction::FetchValueType;
+ i.fetchValue.property = 34;
+ i.fetchValue.type = 6;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 45;
+ i.type = QmlInstruction::PopFetchedObject;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 46;
+ i.type = QmlInstruction::PopQList;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 47;
+ i.type = QmlInstruction::PopValueType;
+ i.fetchValue.property = 35;
+ i.fetchValue.type = 8;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 48;
+ i.type = QmlInstruction::Defer;
+ i.defer.deferCount = 7;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = -1;
+ i.type = QmlInstruction::Defer;
+ i.defer.deferCount = 7;
+ data->bytecode << i;
+ }
+
+ {
+ QmlInstruction i;
+ i.line = 50;
+ i.type = (QmlInstruction::Type)(QmlInstruction::Defer + 1); // Non-existant
+ data->bytecode << i;
+ }
+
+ QStringList expect;
+ expect
+ << "Index\tLine\tOperation\t\tData1\tData2\tData3\tComments"
+ << "-------------------------------------------------------------------------------"
+ << "0\t\t0\tINIT\t\t\t0\t3\t-1\t-1"
+ << "1\t\t1\tCREATE\t\t\t0\t\t\t\"Test\""
+ << "2\t\t2\tSETID\t\t\t0\t\t\t\"testId\""
+ << "3\t\t3\tSET_DEFAULT"
+ << "4\t\t4\tCREATE_COMPONENT\t3"
+ << "5\t\t5\tSTORE_META\t\t3"
+ << "6\t\t6\tSTORE_FLOAT\t\t3\t11.3"
+ << "7\t\t7\tSTORE_DOUBLE\t\t4\t14.8"
+ << "8\t\t8\tSTORE_INTEGER\t\t5\t9"
+ << "9\t\t9\tSTORE_BOOL\t\t6\ttrue"
+ << "10\t\t10\tSTORE_STRING\t\t7\t1\t\t\"Test String\""
+ << "11\t\t11\tSTORE_URL\t\t8\t2\t\t\"http://www.nokia.com\""
+ << "12\t\t12\tSTORE_COLOR\t\t9\t\t\t\"ff00ff00\""
+ << "13\t\t13\tSTORE_DATE\t\t10\t9"
+ << "14\t\t14\tSTORE_TIME\t\t11\t33"
+ << "15\t\t15\tSTORE_DATETIME\t\t12\t44"
+ << "16\t\t16\tSTORE_POINT\t\t13\t3"
+ << "17\t\t17\tSTORE_POINTF\t\t14\t9"
+ << "18\t\t18\tSTORE_SIZE\t\t15\t8"
+ << "19\t\t19\tSTORE_SIZEF\t\t16\t99"
+ << "20\t\t20\tSTORE_RECT\t\t17\t2"
+ << "21\t\t21\tSTORE_RECTF\t\t18\t19"
+ << "22\t\t22\tSTORE_VECTOR3D\t\t19\t9"
+ << "23\t\t23\tSTORE_VARIANT\t\t20\t3\t\t\"color(1, 1, 1, 1)\""
+ << "24\t\t24\tSTORE_OBJECT\t\t21"
+ << "25\t\t25\tSTORE_VARIANT_OBJECT\t22"
+ << "26\t\t26\tSTORE_INTERFACE\t\t23"
+ << "27\t\t27\tSTORE_SIGNAL\t\t2\t4\t\t\"console.log(1921)\""
+ << "28\t\t28\tSTORE_SCRIPT\t\t2"
+ << "29\t\t29\tSTORE_SCRIPT_STRING\t24\t3\t1"
+ << "30\t\t30\tASSIGN_SIGNAL_OBJECT\t0\t\t\t\"mySignal\""
+ << "31\t\t31\tASSIGN_CUSTOMTYPE\t25\t4"
+ << "32\t\t32\tSTORE_BINDING\t26\t3\t2"
+ << "33\t\t33\tSTORE_COMPILED_BINDING\t27\t2\t4"
+ << "34\t\t34\tSTORE_VALUE_SOURCE\t29\t4"
+ << "35\t\t35\tSTORE_VALUE_INTERCEPTOR\t30\t-4"
+ << "36\t\t36\tBEGIN\t\t\t4"
+ << "37\t\t37\tSTORE_OBJECT_QMLLIST"
+ << "38\t\t38\tSTORE_OBJECT_QLIST"
+ << "39\t\t39\tASSIGN_OBJECT_LIST"
+ << "40\t\t40\tFETCH_ATTACHED\t\t23"
+ << "41\t\t41\tFETCH_QMLLIST\t\t31\t3"
+ << "42\t\t42\tFETCH_QLIST\t\t32"
+ << "43\t\t43\tFETCH\t\t\t33"
+ << "44\t\t44\tFETCH_VALUE\t\t34\t6"
+ << "45\t\t45\tPOP"
+ << "46\t\t46\tPOP_QLIST"
+ << "47\t\t47\tPOP_VALUE\t\t35\t8"
+ << "48\t\t48\tDEFER\t\t\t7"
+ << "49\t\tNA\tDEFER\t\t\t7"
+ << "50\t\t50\tXXX UNKOWN INSTRUCTION\t49"
+ << "-------------------------------------------------------------------------------";
+
+ messages = QStringList();
+ QtMsgHandler old = qInstallMsgHandler(msgHandler);
+ data->dumpInstructions();
+ qInstallMsgHandler(old);
+
+ QCOMPARE(messages.count(), expect.count());
+ for (int ii = 0; ii < messages.count(); ++ii) {
+ QCOMPARE(messages.at(ii), expect.at(ii));
+ }
+
+ data->release();
+}
+
+QTEST_MAIN(tst_qmlinstruction)
+
+#include "tst_qmlinstruction.moc"
diff --git a/tests/auto/declarative/qmllanguage/data/Alias.qml b/tests/auto/declarative/qmllanguage/data/Alias.qml
new file mode 100644
index 0000000..55aa231
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/Alias.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ id: root
+ property int value: 1892
+ property alias aliasValue: root.value
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/Alias2.qml b/tests/auto/declarative/qmllanguage/data/Alias2.qml
new file mode 100644
index 0000000..6362b2d
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/Alias2.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ property var other
+ other: MyTypeObject { id: obj }
+ property alias enumAlias: obj.enumProperty;
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/Alias3.qml b/tests/auto/declarative/qmllanguage/data/Alias3.qml
new file mode 100644
index 0000000..d1e78f8
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/Alias3.qml
@@ -0,0 +1,12 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ property alias obj : otherObj
+ property var child
+ child: QtObject {
+ id: otherObj
+ property int myValue: 10
+ }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/Alias4.qml b/tests/auto/declarative/qmllanguage/data/Alias4.qml
new file mode 100644
index 0000000..573674c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/Alias4.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+import Qt 4.6
+
+Alias3 {}
+
diff --git a/tests/auto/declarative/qmllanguage/data/ComponentComposite.qml b/tests/auto/declarative/qmllanguage/data/ComponentComposite.qml
new file mode 100644
index 0000000..05fbc3f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/ComponentComposite.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Component {
+ QtObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType.qml b/tests/auto/declarative/qmllanguage/data/CompositeType.qml
new file mode 100644
index 0000000..99d010f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/CompositeType.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+QtObject {
+}
diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType2.qml b/tests/auto/declarative/qmllanguage/data/CompositeType2.qml
new file mode 100644
index 0000000..86210e9
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/CompositeType2.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyQmlObject {
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType3.qml b/tests/auto/declarative/qmllanguage/data/CompositeType3.qml
new file mode 100644
index 0000000..d08f35b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/CompositeType3.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ property int a
+}
diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType4.qml b/tests/auto/declarative/qmllanguage/data/CompositeType4.qml
new file mode 100644
index 0000000..a6a8168
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/CompositeType4.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyQmlObject {
+ property int a
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/DynamicPropertiesNestedType.qml b/tests/auto/declarative/qmllanguage/data/DynamicPropertiesNestedType.qml
new file mode 100644
index 0000000..aefbf9a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/DynamicPropertiesNestedType.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ property int super_a: 10
+ property int super_c: 14
+}
diff --git a/tests/auto/declarative/qmllanguage/data/HelperAlias.qml b/tests/auto/declarative/qmllanguage/data/HelperAlias.qml
new file mode 100644
index 0000000..dc3b382
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/HelperAlias.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ property var child
+ child: QtObject { id: obj }
+ property alias objAlias: obj;
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/I18n.qml b/tests/auto/declarative/qmllanguage/data/I18n.qml
new file mode 100644
index 0000000..558c836
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/I18n.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ property int áâãäå: 10
+ stringProperty: "Test áâãäå: " + áâãäå
+}
diff --git a/tests/auto/declarative/qmllanguage/data/I18nType30.qml b/tests/auto/declarative/qmllanguage/data/I18nType30.qml
new file mode 100644
index 0000000..42dbc69
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/I18nType30.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ stringProperty: "Test áâãäå: 30"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/MyComponent.qml b/tests/auto/declarative/qmllanguage/data/MyComponent.qml
new file mode 100644
index 0000000..1a23277
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/MyComponent.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyQmlObject {
+ property real x;
+ property real y;
+}
diff --git a/tests/auto/declarative/qmllanguage/data/MyCompositeValueSource.qml b/tests/auto/declarative/qmllanguage/data/MyCompositeValueSource.qml
new file mode 100644
index 0000000..e620e26
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/MyCompositeValueSource.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyPropertyValueSource {
+ property int x
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/MyContainerComponent.qml b/tests/auto/declarative/qmllanguage/data/MyContainerComponent.qml
new file mode 100644
index 0000000..61f54c5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/MyContainerComponent.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyContainer {
+ property int x
+}
diff --git a/tests/auto/declarative/qmllanguage/data/NestedAlias.qml b/tests/auto/declarative/qmllanguage/data/NestedAlias.qml
new file mode 100644
index 0000000..5155612
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/NestedAlias.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+QtObject {
+ property QtObject o1
+ property QtObject o2
+
+ property alias a: object2.a
+
+ o1: QtObject { id: object1 }
+ o2: QtObject {
+ id: object2
+ property int a: 1923
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/NestedErrorsType.qml b/tests/auto/declarative/qmllanguage/data/NestedErrorsType.qml
new file mode 100644
index 0000000..5cc8d20
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/NestedErrorsType.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Item {
+ x: "You can't assign a string to a real!"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/OnCompletedType.qml b/tests/auto/declarative/qmllanguage/data/OnCompletedType.qml
new file mode 100644
index 0000000..2889caf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/OnCompletedType.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+import Qt 4.6
+
+MyQmlObject {
+ property int a: Math.max(10, 9)
+ property int b: 11
+ Component.onCompleted: console.log("Completed " + a + " " + b);
+}
diff --git a/tests/auto/declarative/qmllanguage/data/alias.1.qml b/tests/auto/declarative/qmllanguage/data/alias.1.qml
new file mode 100644
index 0000000..500b0f6
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.1.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ id: root
+ property int value: 10
+ property alias valueAlias: root.value
+}
diff --git a/tests/auto/declarative/qmllanguage/data/alias.2.qml b/tests/auto/declarative/qmllanguage/data/alias.2.qml
new file mode 100644
index 0000000..5c92270
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.2.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyQmlObject {
+ id: root
+ property alias aliasObject: root.qmlobjectProperty
+
+ qmlobjectProperty: MyQmlObject { value : 10 }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/alias.3.qml b/tests/auto/declarative/qmllanguage/data/alias.3.qml
new file mode 100644
index 0000000..e059937
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.3.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+QtObject {
+ property var other
+ other: Alias { id: myAliasObject }
+
+ property alias value: myAliasObject.aliasValue
+ property alias value2: myAliasObject.value
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/alias.4.qml b/tests/auto/declarative/qmllanguage/data/alias.4.qml
new file mode 100644
index 0000000..bd6a769
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.4.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+Alias2 {
+ enumAlias: MyTypeObject.EnumVal2
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/alias.5.qml b/tests/auto/declarative/qmllanguage/data/alias.5.qml
new file mode 100644
index 0000000..4316d0d
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.5.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+import Test 1.0
+
+QtObject {
+ property alias otherAlias: otherObject
+
+ property var other
+ other: MyQmlObject {
+ id: otherObject
+ value: 10
+ }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/alias.6.qml b/tests/auto/declarative/qmllanguage/data/alias.6.qml
new file mode 100644
index 0000000..e3af230
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.6.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property QtObject o;
+ property alias a: object.a
+ o: NestedAlias { id: object }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/alias.7.qml b/tests/auto/declarative/qmllanguage/data/alias.7.qml
new file mode 100644
index 0000000..a9a57eb
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.7.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+QtObject {
+ property QtObject object
+ property alias aliasedObject: target.object
+
+ object: QtObject {
+ id: target
+
+ property QtObject object
+ object: QtObject {}
+ }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/alias.8.qml b/tests/auto/declarative/qmllanguage/data/alias.8.qml
new file mode 100644
index 0000000..2b9ad85
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.8.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ property var other
+ other: Alias3 { id: myAliasObject }
+
+ property int value: myAliasObject.obj.myValue
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/alias.9.qml b/tests/auto/declarative/qmllanguage/data/alias.9.qml
new file mode 100644
index 0000000..a2a41a1
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.9.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ property var other
+ other: Alias4 { id: myAliasObject }
+
+ property int value: myAliasObject.obj.myValue
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/assignBasicTypes.qml b/tests/auto/declarative/qmllanguage/data/assignBasicTypes.qml
new file mode 100644
index 0000000..c86c96b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignBasicTypes.qml
@@ -0,0 +1,29 @@
+import Test 1.0
+MyTypeObject {
+ flagProperty: "FlagVal1 | FlagVal3"
+ enumProperty: "EnumVal2"
+ stringProperty: "Hello World!"
+ uintProperty: 10
+ intProperty: -19
+ realProperty: 23.2
+ doubleProperty: -19.7
+ floatProperty: 8.5
+ colorProperty: "red"
+ dateProperty: "1982-11-25"
+ timeProperty: "11:11:31"
+ timeProperty: "11:11:32"
+ timeProperty: "11:11:32"
+ dateTimeProperty: "2009-05-12T13:22:01"
+ pointProperty: "99,13"
+ pointFProperty: "-10.1,12.3"
+ sizeProperty: "99x13"
+ sizeFProperty: "0.1x0.2"
+ rectProperty: "9,7,100x200"
+ rectFProperty: "1000.1,-10.9,400x90.99"
+ boolProperty: true
+ variantProperty: "Hello World!"
+ vectorProperty: "10,1,2.2"
+ urlProperty: "main.qml"
+
+ objectProperty: MyTypeObject { intProperty: 8 }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml b/tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml
new file mode 100644
index 0000000..f6422bd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+import Test 1.0
+
+QtObject {
+ property QtObject myProperty
+ property QtObject myProperty2
+ property QtObject myProperty3
+ property QtObject myProperty4
+ property MyQmlObject myProperty5
+ property MyQmlObject myProperty6
+
+ myProperty: CompositeType {}
+ myProperty2: CompositeType2 {}
+ myProperty3: CompositeType3 {}
+ myProperty4: CompositeType4 {}
+ myProperty5: CompositeType2 {}
+ myProperty6: CompositeType4 {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/assignLiteralSignalProperty.qml b/tests/auto/declarative/qmllanguage/data/assignLiteralSignalProperty.qml
new file mode 100644
index 0000000..399fcea
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignLiteralSignalProperty.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ onLiteralSignal: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/assignObjectToSignal.qml b/tests/auto/declarative/qmllanguage/data/assignObjectToSignal.qml
new file mode 100644
index 0000000..789cc66
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignObjectToSignal.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ onBasicSignal: MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/assignObjectToVariant.qml b/tests/auto/declarative/qmllanguage/data/assignObjectToVariant.qml
new file mode 100644
index 0000000..0ff9370
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignObjectToVariant.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ property var a;
+ a: MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/assignQmlComponent.qml b/tests/auto/declarative/qmllanguage/data/assignQmlComponent.qml
new file mode 100644
index 0000000..20bdc55
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignQmlComponent.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyContainer {
+ MyComponent { x: 10; y: 11; }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/assignSignal.qml b/tests/auto/declarative/qmllanguage/data/assignSignal.qml
new file mode 100644
index 0000000..2a48df8
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignSignal.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyQmlObject {
+ onBasicSignal: basicSlot()
+ onBasicParameterizedSignal: basicSlotWithArgs(parameter)
+}
diff --git a/tests/auto/declarative/qmllanguage/data/assignTypeExtremes.qml b/tests/auto/declarative/qmllanguage/data/assignTypeExtremes.qml
new file mode 100644
index 0000000..60ede52
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/assignTypeExtremes.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ uintProperty: 4000000000
+ intProperty: -2000000000
+}
diff --git a/tests/auto/declarative/qmllanguage/data/attachedProperties.qml b/tests/auto/declarative/qmllanguage/data/attachedProperties.qml
new file mode 100644
index 0000000..b46ec34
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/attachedProperties.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+import Test 1.0 as Namespace
+import Qt 4.6
+
+QtObject {
+ MyQmlObject.value: 10
+ Namespace.MyQmlObject.value2: 13
+}
diff --git a/tests/auto/declarative/qmllanguage/data/autoComponentCreation.qml b/tests/auto/declarative/qmllanguage/data/autoComponentCreation.qml
new file mode 100644
index 0000000..5d00144
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/autoComponentCreation.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyTypeObject {
+ componentProperty : MyTypeObject { realProperty: 9 }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/component.1.errors.txt b/tests/auto/declarative/qmllanguage/data/component.1.errors.txt
new file mode 100644
index 0000000..091aad6
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.1.errors.txt
@@ -0,0 +1 @@
+3:1:Cannot create empty component specification
diff --git a/tests/auto/declarative/qmllanguage/data/component.1.qml b/tests/auto/declarative/qmllanguage/data/component.1.qml
new file mode 100644
index 0000000..07e463a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.1.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+Component {
+}
diff --git a/tests/auto/declarative/qmllanguage/data/component.2.errors.txt b/tests/auto/declarative/qmllanguage/data/component.2.errors.txt
new file mode 100644
index 0000000..76e7656
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.2.errors.txt
@@ -0,0 +1 @@
+6:9:id is not unique
diff --git a/tests/auto/declarative/qmllanguage/data/component.2.qml b/tests/auto/declarative/qmllanguage/data/component.2.qml
new file mode 100644
index 0000000..88e0f73
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.2.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+Item {
+ id: myId
+ Component {
+ id: myId
+ QtObject {}
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/component.3.errors.txt b/tests/auto/declarative/qmllanguage/data/component.3.errors.txt
new file mode 100644
index 0000000..9a13142
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.3.errors.txt
@@ -0,0 +1 @@
+6:9:Invalid component id specification
diff --git a/tests/auto/declarative/qmllanguage/data/component.3.qml b/tests/auto/declarative/qmllanguage/data/component.3.qml
new file mode 100644
index 0000000..287a959
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.3.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+Item {
+ Component {
+ id: myId
+ id: myId2
+ QtObject {}
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/component.4.errors.txt b/tests/auto/declarative/qmllanguage/data/component.4.errors.txt
new file mode 100644
index 0000000..2ab18685
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.4.errors.txt
@@ -0,0 +1 @@
+3:1:Invalid component body specification
diff --git a/tests/auto/declarative/qmllanguage/data/component.4.qml b/tests/auto/declarative/qmllanguage/data/component.4.qml
new file mode 100644
index 0000000..ab1e29b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.4.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Component {
+ QtObject {}
+ QtObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/component.5.errors.txt b/tests/auto/declarative/qmllanguage/data/component.5.errors.txt
new file mode 100644
index 0000000..5e88900
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.5.errors.txt
@@ -0,0 +1 @@
+4:5:Invalid component specification
diff --git a/tests/auto/declarative/qmllanguage/data/component.5.qml b/tests/auto/declarative/qmllanguage/data/component.5.qml
new file mode 100644
index 0000000..629e998
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.5.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Component {
+ x: 10
+ QtObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/component.6.errors.txt b/tests/auto/declarative/qmllanguage/data/component.6.errors.txt
new file mode 100644
index 0000000..2b1c6ca
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.6.errors.txt
@@ -0,0 +1 @@
+4:5:Invalid component id specification
diff --git a/tests/auto/declarative/qmllanguage/data/component.6.qml b/tests/auto/declarative/qmllanguage/data/component.6.qml
new file mode 100644
index 0000000..2303ebf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/component.6.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Component {
+ id: QtObject {}
+ QtObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/componentCompositeType.qml b/tests/auto/declarative/qmllanguage/data/componentCompositeType.qml
new file mode 100644
index 0000000..0a7249a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/componentCompositeType.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property var test
+
+ test: ComponentComposite {}
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/cppnamespace.2.qml b/tests/auto/declarative/qmllanguage/data/cppnamespace.2.qml
new file mode 100644
index 0000000..e3b32ca
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/cppnamespace.2.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MySecondNamespacedType {
+ list: [ MyNamespacedType {} ]
+}
diff --git a/tests/auto/declarative/qmllanguage/data/cppnamespace.qml b/tests/auto/declarative/qmllanguage/data/cppnamespace.qml
new file mode 100644
index 0000000..e1daf3b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/cppnamespace.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+
+MyNamespacedType {
+}
diff --git a/tests/auto/declarative/qmllanguage/data/crash2.qml b/tests/auto/declarative/qmllanguage/data/crash2.qml
new file mode 100644
index 0000000..a22c776
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/crash2.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ objectName: "Hello" + "World"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.errors.txt b/tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.errors.txt
new file mode 100644
index 0000000..43a8bb2
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.errors.txt
@@ -0,0 +1 @@
+4:19:ListElement: cannot use reserved "id" property
diff --git a/tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.qml b/tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.qml
new file mode 100644
index 0000000..00cc0c4
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/customParserIdNotAllowed.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+ListModel {
+ ListElement { a: 10 }
+ ListElement { id: foo; a: 12 }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/customParserTypes.qml b/tests/auto/declarative/qmllanguage/data/customParserTypes.qml
new file mode 100644
index 0000000..cf2f272
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/customParserTypes.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+ListModel {
+ ListElement { a: 10 }
+ ListElement { a: 12 }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/customVariantTypes.qml b/tests/auto/declarative/qmllanguage/data/customVariantTypes.qml
new file mode 100644
index 0000000..0263ed2
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/customVariantTypes.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ customType: "10"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/declaredPropertyValues.qml b/tests/auto/declarative/qmllanguage/data/declaredPropertyValues.qml
new file mode 100644
index 0000000..3987a3c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/declaredPropertyValues.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property int a: 10
+ property int b: 10 + a
+ property QtObject c: QtObject {}
+ property list<QtObject> d: [ QtObject {}, QtObject {} ]
+}
diff --git a/tests/auto/declarative/qmllanguage/data/defaultGrouped.errors.txt b/tests/auto/declarative/qmllanguage/data/defaultGrouped.errors.txt
new file mode 100644
index 0000000..945d51b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/defaultGrouped.errors.txt
@@ -0,0 +1 @@
+7:9:Invalid value in grouped property
diff --git a/tests/auto/declarative/qmllanguage/data/defaultGrouped.qml b/tests/auto/declarative/qmllanguage/data/defaultGrouped.qml
new file mode 100644
index 0000000..0fd1404
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/defaultGrouped.qml
@@ -0,0 +1,10 @@
+import Test 1.0
+import Qt 4.6
+
+MyTypeObject {
+ grouped {
+ script: console.log(1921)
+ QtObject {}
+ }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/defaultPropertyListOrder.qml b/tests/auto/declarative/qmllanguage/data/defaultPropertyListOrder.qml
new file mode 100644
index 0000000..3651511
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/defaultPropertyListOrder.qml
@@ -0,0 +1,29 @@
+import Test 1.0
+import Qt 4.6
+
+MyContainer {
+ QtObject {
+ property int index: 0
+ }
+
+ QtObject {
+ property int index: 1
+ }
+
+ children: [
+ QtObject {
+ property int index: 2
+ },
+ QtObject {
+ property int index: 3
+ }
+ ]
+
+ QtObject {
+ property int index: 4
+ }
+
+ QtObject {
+ property int index: 5
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/doubleSignal.errors.txt b/tests/auto/declarative/qmllanguage/data/doubleSignal.errors.txt
new file mode 100644
index 0000000..2aea251
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/doubleSignal.errors.txt
@@ -0,0 +1 @@
+5:5:Incorrectly specified signal
diff --git a/tests/auto/declarative/qmllanguage/data/doubleSignal.qml b/tests/auto/declarative/qmllanguage/data/doubleSignal.qml
new file mode 100644
index 0000000..fb07b9f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/doubleSignal.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+
+MyQmlObject {
+ onBasicSignal: console.log(1921)
+ onBasicSignal: console.log(1921)
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/duplicateIDs.errors.txt b/tests/auto/declarative/qmllanguage/data/duplicateIDs.errors.txt
new file mode 100644
index 0000000..66241cf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/duplicateIDs.errors.txt
@@ -0,0 +1 @@
+4:19:id is not unique
diff --git a/tests/auto/declarative/qmllanguage/data/duplicateIDs.qml b/tests/auto/declarative/qmllanguage/data/duplicateIDs.qml
new file mode 100644
index 0000000..a993abd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/duplicateIDs.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+MyContainer {
+ MyQmlObject { id: myID }
+ MyQmlObject { id: myID }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/dynamicObject.1.qml b/tests/auto/declarative/qmllanguage/data/dynamicObject.1.qml
new file mode 100644
index 0000000..85d1052
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/dynamicObject.1.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+import Qt 4.6
+PropertyChanges {
+ propa: a + 10
+ propb: Math.min(a, 10)
+ propc: MyPropertyValueSource {}
+ onPropA: a
+}
diff --git a/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml b/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml
new file mode 100644
index 0000000..c80a7c0
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml
@@ -0,0 +1,13 @@
+import Test 1.0
+import Qt 4.6
+import Qt 4.6 as Qt
+
+QtObject {
+ property QtObject objectProperty
+ property QtObject objectProperty2
+ objectProperty2: QtObject {}
+
+ property MyComponent myComponentProperty
+ property MyComponent myComponentProperty2
+ myComponentProperty2: MyComponent {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/dynamicProperties.qml b/tests/auto/declarative/qmllanguage/data/dynamicProperties.qml
new file mode 100644
index 0000000..aef3269
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/dynamicProperties.qml
@@ -0,0 +1,14 @@
+import Test 1.0
+import Qt 4.6
+QtObject {
+ default property int intProperty : 10
+ property bool boolProperty: false
+ property double doubleProperty: -10.1
+ property real realProperty: -19.9
+ property string stringProperty: "Hello World!"
+ property color colorProperty: "red"
+ property url urlProperty: "main.qml"
+ property date dateProperty: "1945-09-02"
+ property var varProperty: "Hello World!"
+ property variant variantProperty: 12
+}
diff --git a/tests/auto/declarative/qmllanguage/data/dynamicPropertiesNested.qml b/tests/auto/declarative/qmllanguage/data/dynamicPropertiesNested.qml
new file mode 100644
index 0000000..7bfab67
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/dynamicPropertiesNested.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+DynamicPropertiesNestedType {
+ property int a: 13
+ property int b: 12
+
+ super_a: 11
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/dynamicSignalsAndSlots.qml b/tests/auto/declarative/qmllanguage/data/dynamicSignalsAndSlots.qml
new file mode 100644
index 0000000..2a834e8
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/dynamicSignalsAndSlots.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+QtObject {
+ signal signal1
+ function slot1() {}
+ signal signal2
+ function slot2() {}
+
+ property int test: 0
+ function slot3(a) { console.log(1921); test = a; }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/empty.errors.txt b/tests/auto/declarative/qmllanguage/data/empty.errors.txt
new file mode 100644
index 0000000..d416e76
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/empty.errors.txt
@@ -0,0 +1,2 @@
+0:0:Expected token `numeric literal'
+0:0:Expected a qualified name id
diff --git a/tests/auto/declarative/qmllanguage/data/empty.qml b/tests/auto/declarative/qmllanguage/data/empty.qml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/empty.qml
diff --git a/tests/auto/declarative/qmllanguage/data/emptySignal.errors.txt b/tests/auto/declarative/qmllanguage/data/emptySignal.errors.txt
new file mode 100644
index 0000000..353bbf5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/emptySignal.errors.txt
@@ -0,0 +1 @@
+4:5:Empty signal assignment
diff --git a/tests/auto/declarative/qmllanguage/data/emptySignal.qml b/tests/auto/declarative/qmllanguage/data/emptySignal.qml
new file mode 100644
index 0000000..4c5a122
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/emptySignal.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyQmlObject {
+ onBasicSignal: " "
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/failingComponent.errors.txt b/tests/auto/declarative/qmllanguage/data/failingComponent.errors.txt
new file mode 100644
index 0000000..0cf0ef3
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/failingComponent.errors.txt
@@ -0,0 +1 @@
+3:5:Type FailingComponent unavailable
diff --git a/tests/auto/declarative/qmllanguage/data/failingComponentTest.qml b/tests/auto/declarative/qmllanguage/data/failingComponentTest.qml
new file mode 100644
index 0000000..74a6acf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/failingComponentTest.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyContainer {
+ FailingComponent {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/fakeDotProperty.errors.txt b/tests/auto/declarative/qmllanguage/data/fakeDotProperty.errors.txt
new file mode 100644
index 0000000..3074823
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/fakeDotProperty.errors.txt
@@ -0,0 +1 @@
+3:5:Invalid grouped property access
diff --git a/tests/auto/declarative/qmllanguage/data/fakeDotProperty.qml b/tests/auto/declarative/qmllanguage/data/fakeDotProperty.qml
new file mode 100644
index 0000000..d971eee
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/fakeDotProperty.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ value.something: "hello"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/finalOverride.errors.txt b/tests/auto/declarative/qmllanguage/data/finalOverride.errors.txt
new file mode 100644
index 0000000..49e06cb
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/finalOverride.errors.txt
@@ -0,0 +1 @@
+3:5:Cannot override FINAL property
diff --git a/tests/auto/declarative/qmllanguage/data/finalOverride.qml b/tests/auto/declarative/qmllanguage/data/finalOverride.qml
new file mode 100644
index 0000000..a84393a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/finalOverride.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ property int value: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml
new file mode 100644
index 0000000..558c836
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ property int áâãäå: 10
+ stringProperty: "Test áâãäå: " + áâãäå
+}
diff --git a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml
new file mode 100644
index 0000000..74918e2
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml
@@ -0,0 +1,3 @@
+I18n {
+ áâãäå: 15
+}
diff --git a/tests/auto/declarative/qmllanguage/data/i18nNameSpace.qml b/tests/auto/declarative/qmllanguage/data/i18nNameSpace.qml
new file mode 100644
index 0000000..c0b2f94
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/i18nNameSpace.qml
@@ -0,0 +1,5 @@
+import Test 1.0 as Áâãäå
+
+Áâãäå.MyTypeObject {
+ stringProperty: "Test áâãäå: 40"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/i18nScript.qml b/tests/auto/declarative/qmllanguage/data/i18nScript.qml
new file mode 100644
index 0000000..942ed90
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/i18nScript.qml
@@ -0,0 +1,12 @@
+import Test 1.0
+
+MyTypeObject {
+ Script {
+ function val() {
+ var áâãäå = 20
+ return "Test áâãäå: " + áâãäå
+ }
+
+ }
+ stringProperty: val()
+}
diff --git a/tests/auto/declarative/qmllanguage/data/i18nStrings.qml b/tests/auto/declarative/qmllanguage/data/i18nStrings.qml
new file mode 100644
index 0000000..764c926
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/i18nStrings.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ stringProperty: "Test áâãäå (5 accented 'a' letters)"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/i18nType.qml b/tests/auto/declarative/qmllanguage/data/i18nType.qml
new file mode 100644
index 0000000..d7954ef
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/i18nType.qml
@@ -0,0 +1 @@
+I18nTypeÁâãäå { }
diff --git a/tests/auto/declarative/qmllanguage/data/idProperty.qml b/tests/auto/declarative/qmllanguage/data/idProperty.qml
new file mode 100644
index 0000000..90c1483
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/idProperty.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+MyContainer {
+ property var object : myObjectId
+
+ MyTypeObject {
+ id: "myObjectId"
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/importNamespaceConflict.errors.txt b/tests/auto/declarative/qmllanguage/data/importNamespaceConflict.errors.txt
new file mode 100644
index 0000000..231998d
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/importNamespaceConflict.errors.txt
@@ -0,0 +1 @@
+4:1:Namespace Rectangle cannot be used as a type
diff --git a/tests/auto/declarative/qmllanguage/data/importNamespaceConflict.qml b/tests/auto/declarative/qmllanguage/data/importNamespaceConflict.qml
new file mode 100644
index 0000000..cd112af
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/importNamespaceConflict.qml
@@ -0,0 +1,4 @@
+import Test 1.0 as Rectangle
+import Qt 4.6
+
+Rectangle { }
diff --git a/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt b/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt
new file mode 100644
index 0000000..c7d880e
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt
@@ -0,0 +1 @@
+1:16:Library import requires a version
diff --git a/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.qml b/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.qml
new file mode 100644
index 0000000..23ed566
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.qml
@@ -0,0 +1,7 @@
+import Test as S
+
+S.MyQmlObject {
+ property real x;
+ property real y;
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt b/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt
new file mode 100644
index 0000000..89e58ee
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt
@@ -0,0 +1 @@
+1:35:Library import requires a version
diff --git a/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.qml b/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.qml
new file mode 100644
index 0000000..97ec222
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.qml
@@ -0,0 +1,3 @@
+import com.nokia.installedtest as T
+
+T.InstalledTest {}
diff --git a/tests/auto/declarative/qmllanguage/data/inlineQmlComponents.qml b/tests/auto/declarative/qmllanguage/data/inlineQmlComponents.qml
new file mode 100644
index 0000000..478f06a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/inlineQmlComponents.qml
@@ -0,0 +1,10 @@
+import Test 1.0
+import Qt 4.6
+MyContainer {
+ Component {
+ id: myComponent
+ MyQmlObject {
+ value: 11
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/interfaceProperty.qml b/tests/auto/declarative/qmllanguage/data/interfaceProperty.qml
new file mode 100644
index 0000000..70879ff
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/interfaceProperty.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+import Qt 4.6
+MyQmlObject {
+ interfaceProperty: MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/interfaceQList.qml b/tests/auto/declarative/qmllanguage/data/interfaceQList.qml
new file mode 100644
index 0000000..c87dfae
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/interfaceQList.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+MyContainer {
+ qlistInterfaces: [
+ MyQmlObject {},
+ MyQmlObject {}
+ ]
+}
diff --git a/tests/auto/declarative/qmllanguage/data/interfaceQmlList.qml b/tests/auto/declarative/qmllanguage/data/interfaceQmlList.qml
new file mode 100644
index 0000000..8392bea
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/interfaceQmlList.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+MyContainer {
+ qmllistInterfaces: [
+ MyQmlObject {},
+ MyQmlObject {}
+ ]
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.errors.txt
new file mode 100644
index 0000000..68fe671
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.errors.txt
@@ -0,0 +1 @@
+5:17:Cannot assign to non-existant property "foo"
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.qml
new file mode 100644
index 0000000..324f79c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.1.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ MyQmlObject.foo: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.errors.txt
new file mode 100644
index 0000000..7f630f4
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.errors.txt
@@ -0,0 +1 @@
+5:15:Non-existant attached object
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.qml
new file mode 100644
index 0000000..b768e9f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.10.qml
@@ -0,0 +1,6 @@
+import Test 1.0 as Namespace
+import Qt 4.6
+
+QtObject {
+ Namespace.MadeUpClass.foo: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.errors.txt
new file mode 100644
index 0000000..fee5050
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.errors.txt
@@ -0,0 +1 @@
+5:15:Not an attached property name
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.qml
new file mode 100644
index 0000000..7b782be
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.11.qml
@@ -0,0 +1,7 @@
+import Test 1.0 as Namespace
+import Qt 4.6
+
+QtObject {
+ Namespace.madeUpClass.foo: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.errors.txt
new file mode 100644
index 0000000..9f06e07
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.errors.txt
@@ -0,0 +1 @@
+5:27:Cannot assign to non-existant property "foo"
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.qml
new file mode 100644
index 0000000..1f47c61
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.2.qml
@@ -0,0 +1,6 @@
+import Test 1.0 as Namespace
+import Qt 4.6
+
+QtObject {
+ Namespace.MyQmlObject.foo: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.errors.txt
new file mode 100644
index 0000000..05161c4
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.errors.txt
@@ -0,0 +1 @@
+5:5:Invalid attached object assignment
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.qml
new file mode 100644
index 0000000..79c2981
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.3.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ MyQmlObject: 10
+}
+
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.errors.txt
new file mode 100644
index 0000000..a208bcf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.errors.txt
@@ -0,0 +1 @@
+5:15:Invalid attached object assignment
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.qml
new file mode 100644
index 0000000..af0be80
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.4.qml
@@ -0,0 +1,7 @@
+import Test 1.0 as Namespace
+import Qt 4.6
+
+QtObject {
+ Namespace.MyQmlObject: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.errors.txt
new file mode 100644
index 0000000..05161c4
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.errors.txt
@@ -0,0 +1 @@
+5:5:Invalid attached object assignment
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.qml
new file mode 100644
index 0000000..0546322
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.5.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ MyQmlObject: QtObject {}
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.errors.txt
new file mode 100644
index 0000000..e232b23
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.errors.txt
@@ -0,0 +1 @@
+5:5:Non-existant attached object
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.qml
new file mode 100644
index 0000000..108109a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.6.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ Test.MyQmlObject: QtObject {}
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.errors.txt
new file mode 100644
index 0000000..e232b23
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.errors.txt
@@ -0,0 +1 @@
+5:5:Non-existant attached object
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.qml
new file mode 100644
index 0000000..ccf0353
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.7.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ MyTypeObject.foo: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.errors.txt
new file mode 100644
index 0000000..7f630f4
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.errors.txt
@@ -0,0 +1 @@
+5:15:Non-existant attached object
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.qml
new file mode 100644
index 0000000..e736379
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.8.qml
@@ -0,0 +1,6 @@
+import Test 1.0 as Namespace
+import Qt 4.6
+
+QtObject {
+ Namespace.MyTypeObject.foo: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.errors.txt
new file mode 100644
index 0000000..e232b23
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.errors.txt
@@ -0,0 +1 @@
+5:5:Non-existant attached object
diff --git a/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.qml b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.qml
new file mode 100644
index 0000000..a095229
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidAttachedProperty.9.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ MadeUpClass.foo: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt
new file mode 100644
index 0000000..810fd31
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt
@@ -0,0 +1 @@
+5:5:Invalid grouped property access
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml
new file mode 100644
index 0000000..1167e39
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ property var o;
+ o.blah: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt
new file mode 100644
index 0000000..810fd31
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt
@@ -0,0 +1 @@
+5:5:Invalid grouped property access
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml
new file mode 100644
index 0000000..a0c8306
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+QtObject {
+ property int o;
+ o.blah: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.errors.txt
new file mode 100644
index 0000000..f6d6f29
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.errors.txt
@@ -0,0 +1 @@
+4:5:Invalid grouped property access
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.qml
new file mode 100644
index 0000000..0bbfc4f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.3.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyQmlObject {
+ customType.x: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.errors.txt
new file mode 100644
index 0000000..19934fa
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.errors.txt
@@ -0,0 +1 @@
+4:5:Cannot assign to non-existant property "foo"
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.qml
new file mode 100644
index 0000000..134fef9
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.4.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyQmlObject {
+ foo.x: 10
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.errors.txt
new file mode 100644
index 0000000..2c8a970
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.errors.txt
@@ -0,0 +1 @@
+4:18:Property assignment expected
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.qml
new file mode 100644
index 0000000..55cefe6
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.5.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ rectProperty.x.foo: 100
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.errors.txt
new file mode 100644
index 0000000..8331725
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.errors.txt
@@ -0,0 +1 @@
+5:18:Single property assignment expected
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.qml
new file mode 100644
index 0000000..9ec33ab
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.6.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ rectProperty.x: 100
+ rectProperty.x: 101
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.errors.txt
new file mode 100644
index 0000000..4a7e383
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.errors.txt
@@ -0,0 +1 @@
+4:-1:Cannot set properties on nullGrouped as it is null
diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.qml
new file mode 100644
index 0000000..977539a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.7.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ nullGrouped.script: console.log(1921)
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.2.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidID.2.errors.txt
new file mode 100644
index 0000000..56e3eeb
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.2.errors.txt
@@ -0,0 +1,2 @@
+3:5:"" is not a valid object id
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.2.qml b/tests/auto/declarative/qmllanguage/data/invalidID.2.qml
new file mode 100644
index 0000000..4fb3b29
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.2.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyQmlObject {
+ id: ""
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.3.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidID.3.errors.txt
new file mode 100644
index 0000000..bb811cf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.3.errors.txt
@@ -0,0 +1 @@
+3:5:Invalid use of id property
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.3.qml b/tests/auto/declarative/qmllanguage/data/invalidID.3.qml
new file mode 100644
index 0000000..6684172
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.3.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyQmlObject {
+ id.other: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.4.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidID.4.errors.txt
new file mode 100644
index 0000000..cfe8756
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.4.errors.txt
@@ -0,0 +1 @@
+4:5:Invalid use of id property
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.4.qml b/tests/auto/declarative/qmllanguage/data/invalidID.4.qml
new file mode 100644
index 0000000..86010bf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.4.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+MyQmlObject {
+ id: hello
+ id: world
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.5.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidID.5.errors.txt
new file mode 100644
index 0000000..c167de3
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.5.errors.txt
@@ -0,0 +1 @@
+2:20:Invalid import qualifier ID
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.5.qml b/tests/auto/declarative/qmllanguage/data/invalidID.5.qml
new file mode 100644
index 0000000..5b92a1a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.5.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+import Test 1.0 as hello
+MyQmlObject {
+ id: hello
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.6.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidID.6.errors.txt
new file mode 100644
index 0000000..160e8b5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.6.errors.txt
@@ -0,0 +1 @@
+3:5:"StartsWithUpperCase" is not a valid object id
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.6.qml b/tests/auto/declarative/qmllanguage/data/invalidID.6.qml
new file mode 100644
index 0000000..62187d9
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.6.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyQmlObject {
+ id: StartsWithUpperCase
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidID.errors.txt
new file mode 100644
index 0000000..1ca678c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.errors.txt
@@ -0,0 +1 @@
+3:5:"1" is not a valid object id
diff --git a/tests/auto/declarative/qmllanguage/data/invalidID.qml b/tests/auto/declarative/qmllanguage/data/invalidID.qml
new file mode 100644
index 0000000..04db3eb
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidID.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ id: 1
+}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidImportID.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidImportID.errors.txt
new file mode 100644
index 0000000..a65f5fd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidImportID.errors.txt
@@ -0,0 +1 @@
+2:18:Invalid import qualifier ID
diff --git a/tests/auto/declarative/qmllanguage/data/invalidImportID.qml b/tests/auto/declarative/qmllanguage/data/invalidImportID.qml
new file mode 100644
index 0000000..30d88d5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidImportID.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+import Qt 4.6 as qt
+
+QtObject {}
diff --git a/tests/auto/declarative/qmllanguage/data/invalidRoot.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidRoot.errors.txt
new file mode 100644
index 0000000..4bcc948
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidRoot.errors.txt
@@ -0,0 +1 @@
+1:1:Expected type name
diff --git a/tests/auto/declarative/qmllanguage/data/invalidRoot.qml b/tests/auto/declarative/qmllanguage/data/invalidRoot.qml
new file mode 100644
index 0000000..427827c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/invalidRoot.qml
@@ -0,0 +1,2 @@
+foo {
+}
diff --git a/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest.qml b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest.qml
new file mode 100644
index 0000000..d8a22a8
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+Rectangle {}
diff --git a/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest2.qml b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest2.qml
new file mode 100644
index 0000000..a0706ad
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/InstalledTest2.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+Text {}
diff --git a/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/PrivateType.qml b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/PrivateType.qml
new file mode 100644
index 0000000..93c7630
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/PrivateType.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+Image {}
diff --git a/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/qmldir b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/qmldir
new file mode 100644
index 0000000..eeb9a05
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/lib/com/nokia/installedtest/qmldir
@@ -0,0 +1,4 @@
+Rectangle 1.5 InstalledTest2.qml
+InstalledTest 1.4 InstalledTest2.qml
+InstalledTest 1.0 InstalledTest.qml
+InstalledTestTP 0.0 InstalledTest.qml
diff --git a/tests/auto/declarative/qmllanguage/data/listAssignment.1.errors.txt b/tests/auto/declarative/qmllanguage/data/listAssignment.1.errors.txt
new file mode 100644
index 0000000..d68d487
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listAssignment.1.errors.txt
@@ -0,0 +1 @@
+3:24:Cannot assign primitives to lists
diff --git a/tests/auto/declarative/qmllanguage/data/listAssignment.1.qml b/tests/auto/declarative/qmllanguage/data/listAssignment.1.qml
new file mode 100644
index 0000000..4240425
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listAssignment.1.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyContainer {
+ qmllistInterfaces: 1
+}
diff --git a/tests/auto/declarative/qmllanguage/data/listAssignment.2.errors.txt b/tests/auto/declarative/qmllanguage/data/listAssignment.2.errors.txt
new file mode 100644
index 0000000..8b40aa3
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listAssignment.2.errors.txt
@@ -0,0 +1,2 @@
+3:15:Cannot assign primitives to lists
+
diff --git a/tests/auto/declarative/qmllanguage/data/listAssignment.2.qml b/tests/auto/declarative/qmllanguage/data/listAssignment.2.qml
new file mode 100644
index 0000000..e3baadb
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listAssignment.2.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyContainer {
+ children: 2
+}
diff --git a/tests/auto/declarative/qmllanguage/data/listAssignment.3.errors.txt b/tests/auto/declarative/qmllanguage/data/listAssignment.3.errors.txt
new file mode 100644
index 0000000..8c7b7e9
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listAssignment.3.errors.txt
@@ -0,0 +1 @@
+4:15:Can only assign one binding to lists
diff --git a/tests/auto/declarative/qmllanguage/data/listAssignment.3.qml b/tests/auto/declarative/qmllanguage/data/listAssignment.3.qml
new file mode 100644
index 0000000..00c4c6b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listAssignment.3.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+MyContainer {
+ children: childBinding.expression
+ children: childBinding2.expression
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/listItemDeleteSelf.qml b/tests/auto/declarative/qmllanguage/data/listItemDeleteSelf.qml
new file mode 100644
index 0000000..779c6d4
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listItemDeleteSelf.qml
@@ -0,0 +1,38 @@
+import Qt 4.6
+
+Item {
+ ListModel {
+ id: fruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ }
+ }
+
+ Component {
+ id: fruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: fruitModel.remove(index)
+ }
+ }
+ }
+
+ ListView {
+ model: fruitModel
+ delegate: fruitDelegate
+ anchors.fill: parent
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/listProperties.qml b/tests/auto/declarative/qmllanguage/data/listProperties.qml
new file mode 100644
index 0000000..ba9e37c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/listProperties.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ property list<QtObject> listProperty
+ property int test: listProperty.length
+
+ listProperty: [ QtObject{}, QtObject {} ]
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/missingObject.errors.txt b/tests/auto/declarative/qmllanguage/data/missingObject.errors.txt
new file mode 100644
index 0000000..b31b562
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/missingObject.errors.txt
@@ -0,0 +1 @@
+1:10:Expected token `{'
diff --git a/tests/auto/declarative/qmllanguage/data/missingObject.qml b/tests/auto/declarative/qmllanguage/data/missingObject.qml
new file mode 100644
index 0000000..2f17045
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/missingObject.qml
@@ -0,0 +1 @@
+something: 24
diff --git a/tests/auto/declarative/qmllanguage/data/missingSignal.errors.txt b/tests/auto/declarative/qmllanguage/data/missingSignal.errors.txt
new file mode 100644
index 0000000..e243ae5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/missingSignal.errors.txt
@@ -0,0 +1 @@
+4:5:Cannot assign to non-existant property "onClicked"
diff --git a/tests/auto/declarative/qmllanguage/data/missingSignal.qml b/tests/auto/declarative/qmllanguage/data/missingSignal.qml
new file mode 100644
index 0000000..3bf75f6
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/missingSignal.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+import Qt 4.6
+QtObject {
+ onClicked: console.log("Hello world!")
+}
diff --git a/tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.errors.txt b/tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.errors.txt
new file mode 100644
index 0000000..dfaa218
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.errors.txt
@@ -0,0 +1 @@
+4:18:Cannot assign to non-existant property "foo"
diff --git a/tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.qml b/tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.qml
new file mode 100644
index 0000000..9a0fa6a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/missingValueTypeProperty.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ rectProperty.foo: 9
+}
diff --git a/tests/auto/declarative/qmllanguage/data/nestedErrors.errors.txt b/tests/auto/declarative/qmllanguage/data/nestedErrors.errors.txt
new file mode 100644
index 0000000..886da55
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nestedErrors.errors.txt
@@ -0,0 +1,2 @@
+4:5:Unable to create type NestedErrorsType
+4:8:Invalid property assignment: double expected
diff --git a/tests/auto/declarative/qmllanguage/data/nestedErrors.qml b/tests/auto/declarative/qmllanguage/data/nestedErrors.qml
new file mode 100644
index 0000000..c0d755a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nestedErrors.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+Item {
+ NestedErrorsType {}
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.errors.txt b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.errors.txt
new file mode 100644
index 0000000..cfc6fc8
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.errors.txt
@@ -0,0 +1 @@
+2:15:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.qml b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.qml
new file mode 100644
index 0000000..df7406c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.1.qml
@@ -0,0 +1,2 @@
+import Test 1.0
+MyQmlObject { something: 24 }
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.errors.txt b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.errors.txt
new file mode 100644
index 0000000..8b13585
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.errors.txt
@@ -0,0 +1 @@
+3:5:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.qml b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.qml
new file mode 100644
index 0000000..06ccd37
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.2.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ something: 24
+}
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.errors.txt b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.errors.txt
new file mode 100644
index 0000000..8b13585
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.errors.txt
@@ -0,0 +1 @@
+3:5:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.qml b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.qml
new file mode 100644
index 0000000..5b08608
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.3.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ something: 1 + 1
+}
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.errors.txt b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.errors.txt
new file mode 100644
index 0000000..8b13585
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.errors.txt
@@ -0,0 +1 @@
+3:5:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.qml b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.qml
new file mode 100644
index 0000000..6579191
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.4.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ something: ;
+}
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.errors.txt b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.errors.txt
new file mode 100644
index 0000000..c07f2b9
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.errors.txt
@@ -0,0 +1 @@
+3:5:Expected a qualified name id
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.qml b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.qml
new file mode 100644
index 0000000..37af057
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.5.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ 24
+}
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.errors.txt b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.errors.txt
new file mode 100644
index 0000000..c02d7bd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.errors.txt
@@ -0,0 +1 @@
+3:5:Cannot assign to non-existant default property
diff --git a/tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.qml b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.qml
new file mode 100644
index 0000000..5cd55d0
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nonexistantProperty.6.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/nullDotProperty.errors.txt b/tests/auto/declarative/qmllanguage/data/nullDotProperty.errors.txt
new file mode 100644
index 0000000..07a4094
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nullDotProperty.errors.txt
@@ -0,0 +1 @@
+3:-1:Cannot set properties on obj as it is null
diff --git a/tests/auto/declarative/qmllanguage/data/nullDotProperty.qml b/tests/auto/declarative/qmllanguage/data/nullDotProperty.qml
new file mode 100644
index 0000000..4e36779
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/nullDotProperty.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyDotPropertyObject {
+ obj.value: 1
+}
diff --git a/tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.errors.txt b/tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.errors.txt
new file mode 100644
index 0000000..db7d9c0
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.errors.txt
@@ -0,0 +1 @@
+4:18:Unexpected object assignment
diff --git a/tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.qml b/tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.qml
new file mode 100644
index 0000000..9924773
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/objectValueTypeProperty.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ rectProperty.x: MyTypeObject {}
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/onCompleted.qml b/tests/auto/declarative/qmllanguage/data/onCompleted.qml
new file mode 100644
index 0000000..5725f85
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/onCompleted.qml
@@ -0,0 +1,17 @@
+import Test 1.0
+import Qt 4.6
+
+MyTypeObject {
+ // We set a and b to ensure that onCompleted is executed after bindings and
+ // constants have been assigned
+ property int a: Math.min(6, 7)
+ Component.onCompleted: console.log("Completed " + a + " " + nestedObject.b)
+
+ objectProperty: OnCompletedType {
+ qmlobjectProperty: MyQmlObject {
+ id: nestedObject
+ property int b: 10
+ Component.onCompleted: console.log("Completed " + a + " " + nestedObject.b)
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/property.1.errors.txt b/tests/auto/declarative/qmllanguage/data/property.1.errors.txt
new file mode 100644
index 0000000..3ae6c46
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.1.errors.txt
@@ -0,0 +1 @@
+4:14:Expected property type
diff --git a/tests/auto/declarative/qmllanguage/data/property.1.qml b/tests/auto/declarative/qmllanguage/data/property.1.qml
new file mode 100644
index 0000000..cadc39a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.1.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ property blah a;
+}
diff --git a/tests/auto/declarative/qmllanguage/data/property.2.errors.txt b/tests/auto/declarative/qmllanguage/data/property.2.errors.txt
new file mode 100644
index 0000000..a18e21a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.2.errors.txt
@@ -0,0 +1 @@
+4:14:Unexpected property type modifier
diff --git a/tests/auto/declarative/qmllanguage/data/property.2.qml b/tests/auto/declarative/qmllanguage/data/property.2.qml
new file mode 100644
index 0000000..e810c6c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.2.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ property invalidmodifier<int> a;
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/property.3.errors.txt b/tests/auto/declarative/qmllanguage/data/property.3.errors.txt
new file mode 100644
index 0000000..5e09a25
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.3.errors.txt
@@ -0,0 +1 @@
+4:14:Invalid property type modifier
diff --git a/tests/auto/declarative/qmllanguage/data/property.3.qml b/tests/auto/declarative/qmllanguage/data/property.3.qml
new file mode 100644
index 0000000..04147c2
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.3.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+QtObject {
+ property invalidmodifier<QtObject> a;
+}
+
+
diff --git a/tests/auto/declarative/qmllanguage/data/property.4.errors.txt b/tests/auto/declarative/qmllanguage/data/property.4.errors.txt
new file mode 100644
index 0000000..b447186
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.4.errors.txt
@@ -0,0 +1 @@
+5:1:Syntax error
diff --git a/tests/auto/declarative/qmllanguage/data/property.4.qml b/tests/auto/declarative/qmllanguage/data/property.4.qml
new file mode 100644
index 0000000..b2ec482
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.4.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ readonly property int a
+}
diff --git a/tests/auto/declarative/qmllanguage/data/property.5.errors.txt b/tests/auto/declarative/qmllanguage/data/property.5.errors.txt
new file mode 100644
index 0000000..32a8dc1
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.5.errors.txt
@@ -0,0 +1 @@
+4:5:Readonly not yet supported
diff --git a/tests/auto/declarative/qmllanguage/data/property.5.qml b/tests/auto/declarative/qmllanguage/data/property.5.qml
new file mode 100644
index 0000000..65fafbb
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/property.5.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ readonly property int a: value
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/propertyValueSource.2.qml b/tests/auto/declarative/qmllanguage/data/propertyValueSource.2.qml
new file mode 100644
index 0000000..57a6070
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/propertyValueSource.2.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ intProperty : MyCompositeValueSource {}
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/propertyValueSource.qml b/tests/auto/declarative/qmllanguage/data/propertyValueSource.qml
new file mode 100644
index 0000000..ad71fcf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/propertyValueSource.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyTypeObject {
+ intProperty : MyPropertyValueSource {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml
new file mode 100644
index 0000000..429c327
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+import Qt 4.6
+QtObject {
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml
new file mode 100644
index 0000000..0f57b61
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+import Qt 4.6
+QtObject {
+ MyQmlObject.value: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/readOnly.1.errors.txt b/tests/auto/declarative/qmllanguage/data/readOnly.1.errors.txt
new file mode 100644
index 0000000..b8c3404
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/readOnly.1.errors.txt
@@ -0,0 +1 @@
+3:21:Invalid property assignment: "readOnlyString" is a read-only property
diff --git a/tests/auto/declarative/qmllanguage/data/readOnly.1.qml b/tests/auto/declarative/qmllanguage/data/readOnly.1.qml
new file mode 100644
index 0000000..60757bd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/readOnly.1.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ readOnlyString: "Hello World"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/readOnly.2.errors.txt b/tests/auto/declarative/qmllanguage/data/readOnly.2.errors.txt
new file mode 100644
index 0000000..d857a04
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/readOnly.2.errors.txt
@@ -0,0 +1 @@
+3:5:Invalid property assignment: "readOnlyString" is a read-only property
diff --git a/tests/auto/declarative/qmllanguage/data/readOnly.2.qml b/tests/auto/declarative/qmllanguage/data/readOnly.2.qml
new file mode 100644
index 0000000..8f1633c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/readOnly.2.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ readOnlyString: "Hello" + "World"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/readOnly.3.errors.txt b/tests/auto/declarative/qmllanguage/data/readOnly.3.errors.txt
new file mode 100644
index 0000000..c7e9e1b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/readOnly.3.errors.txt
@@ -0,0 +1 @@
+6:36:Invalid property assignment: "objAlias" is a read-only property
diff --git a/tests/auto/declarative/qmllanguage/data/readOnly.3.qml b/tests/auto/declarative/qmllanguage/data/readOnly.3.qml
new file mode 100644
index 0000000..cd86a48
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/readOnly.3.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+import Qt 4.6
+
+QtObject {
+ property var child
+ child: HelperAlias { objAlias: QtObject {} }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/rootAsQmlComponent.qml b/tests/auto/declarative/qmllanguage/data/rootAsQmlComponent.qml
new file mode 100644
index 0000000..8d72cd3
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/rootAsQmlComponent.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+MyContainerComponent {
+ x: 11
+ MyQmlObject {}
+ MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/script.1.errors.txt b/tests/auto/declarative/qmllanguage/data/script.1.errors.txt
new file mode 100644
index 0000000..50518cc
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.1.errors.txt
@@ -0,0 +1 @@
+3:1:Invalid use of Script block
diff --git a/tests/auto/declarative/qmllanguage/data/script.1.qml b/tests/auto/declarative/qmllanguage/data/script.1.qml
new file mode 100644
index 0000000..8dac8b7
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.1.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+Script {
+}
diff --git a/tests/auto/declarative/qmllanguage/data/script.10.errors.txt b/tests/auto/declarative/qmllanguage/data/script.10.errors.txt
new file mode 100644
index 0000000..8299d23
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.10.errors.txt
@@ -0,0 +1 @@
+6:9:Invalid component specification
diff --git a/tests/auto/declarative/qmllanguage/data/script.10.qml b/tests/auto/declarative/qmllanguage/data/script.10.qml
new file mode 100644
index 0000000..516e878
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.10.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+Item {
+ Component {
+ Item {}
+ Script {}
+ }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/script.11.errors.txt b/tests/auto/declarative/qmllanguage/data/script.11.errors.txt
new file mode 100644
index 0000000..a664203
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.11.errors.txt
@@ -0,0 +1 @@
+5:9:Invalid Script block
diff --git a/tests/auto/declarative/qmllanguage/data/script.11.qml b/tests/auto/declarative/qmllanguage/data/script.11.qml
new file mode 100644
index 0000000..6d2d598
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.11.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ QtObject {}
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/script.12.errors.txt b/tests/auto/declarative/qmllanguage/data/script.12.errors.txt
new file mode 100644
index 0000000..85c8396
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.12.errors.txt
@@ -0,0 +1 @@
+4:5:QmlJS declaration outside Script element
diff --git a/tests/auto/declarative/qmllanguage/data/script.12.qml b/tests/auto/declarative/qmllanguage/data/script.12.qml
new file mode 100644
index 0000000..9ecb5d9
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.12.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ var a
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/script.2.errors.txt b/tests/auto/declarative/qmllanguage/data/script.2.errors.txt
new file mode 100644
index 0000000..8fb3bbd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.2.errors.txt
@@ -0,0 +1 @@
+5:9:Properties cannot be set on Script block
diff --git a/tests/auto/declarative/qmllanguage/data/script.2.qml b/tests/auto/declarative/qmllanguage/data/script.2.qml
new file mode 100644
index 0000000..dce1a41
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.2.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ id: myScript
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/script.3.errors.txt b/tests/auto/declarative/qmllanguage/data/script.3.errors.txt
new file mode 100644
index 0000000..8fb3bbd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.3.errors.txt
@@ -0,0 +1 @@
+5:9:Properties cannot be set on Script block
diff --git a/tests/auto/declarative/qmllanguage/data/script.3.qml b/tests/auto/declarative/qmllanguage/data/script.3.qml
new file mode 100644
index 0000000..8621a9a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.3.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ hello: world
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/script.4.errors.txt b/tests/auto/declarative/qmllanguage/data/script.4.errors.txt
new file mode 100644
index 0000000..49a507f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.4.errors.txt
@@ -0,0 +1 @@
+5:9:Invalid Script source value
diff --git a/tests/auto/declarative/qmllanguage/data/script.4.qml b/tests/auto/declarative/qmllanguage/data/script.4.qml
new file mode 100644
index 0000000..d89817c
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.4.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ source: 10
+ }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/script.5.errors.txt b/tests/auto/declarative/qmllanguage/data/script.5.errors.txt
new file mode 100644
index 0000000..49a507f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.5.errors.txt
@@ -0,0 +1 @@
+5:9:Invalid Script source value
diff --git a/tests/auto/declarative/qmllanguage/data/script.5.qml b/tests/auto/declarative/qmllanguage/data/script.5.qml
new file mode 100644
index 0000000..8986b3b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.5.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ source: "hello" + ".js"
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmllanguage/data/script.6.errors.txt b/tests/auto/declarative/qmllanguage/data/script.6.errors.txt
new file mode 100644
index 0000000..4e53b6b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.6.errors.txt
@@ -0,0 +1 @@
+5:9:Invalid Script block. Specify either the source property or inline script
diff --git a/tests/auto/declarative/qmllanguage/data/script.6.qml b/tests/auto/declarative/qmllanguage/data/script.6.qml
new file mode 100644
index 0000000..07e9d78
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.6.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ source: "test.js"
+ function helloWorld() {}
+ }
+}
+
+
+
diff --git a/tests/auto/declarative/qmllanguage/data/script.7.errors.txt b/tests/auto/declarative/qmllanguage/data/script.7.errors.txt
new file mode 100644
index 0000000..dc15ddf
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.7.errors.txt
@@ -0,0 +1 @@
+5:9:Variable declarations not allow in inline Script blocks
diff --git a/tests/auto/declarative/qmllanguage/data/script.7.qml b/tests/auto/declarative/qmllanguage/data/script.7.qml
new file mode 100644
index 0000000..fa905e6
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.7.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ var a = 10;
+ }
+}
+
+
+
+
diff --git a/tests/auto/declarative/qmllanguage/data/script.8.errors.txt b/tests/auto/declarative/qmllanguage/data/script.8.errors.txt
new file mode 100644
index 0000000..b5bf1a8
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.8.errors.txt
@@ -0,0 +1 @@
+6:9:Invalid Script source value
diff --git a/tests/auto/declarative/qmllanguage/data/script.8.qml b/tests/auto/declarative/qmllanguage/data/script.8.qml
new file mode 100644
index 0000000..f600c88
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.8.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ Script {
+ source: "test.js"
+ source: "test2.js"
+ }
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/script.9.errors.txt b/tests/auto/declarative/qmllanguage/data/script.9.errors.txt
new file mode 100644
index 0000000..dc1eb53
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.9.errors.txt
@@ -0,0 +1 @@
+5:9:Invalid component specification
diff --git a/tests/auto/declarative/qmllanguage/data/script.9.qml b/tests/auto/declarative/qmllanguage/data/script.9.qml
new file mode 100644
index 0000000..79aa504
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/script.9.qml
@@ -0,0 +1,7 @@
+import Qt 4.6
+
+Item {
+ Component {
+ Script {}
+ }
+}
diff --git a/tests/auto/declarative/qmllanguage/data/scriptString.qml b/tests/auto/declarative/qmllanguage/data/scriptString.qml
new file mode 100644
index 0000000..40a3bbe
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/scriptString.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ scriptProperty: foo + bar
+ grouped.script: console.log(1921)
+}
diff --git a/tests/auto/declarative/qmllanguage/data/signal.1.errors.txt b/tests/auto/declarative/qmllanguage/data/signal.1.errors.txt
new file mode 100644
index 0000000..78d9960
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/signal.1.errors.txt
@@ -0,0 +1 @@
+4:12:Expected parameter type
diff --git a/tests/auto/declarative/qmllanguage/data/signal.1.qml b/tests/auto/declarative/qmllanguage/data/signal.1.qml
new file mode 100644
index 0000000..fbaf017
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/signal.1.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ signal mySignal(nontype a)
+}
diff --git a/tests/auto/declarative/qmllanguage/data/signal.2.errors.txt b/tests/auto/declarative/qmllanguage/data/signal.2.errors.txt
new file mode 100644
index 0000000..fce8928
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/signal.2.errors.txt
@@ -0,0 +1 @@
+4:21:Unexpected token `;'
diff --git a/tests/auto/declarative/qmllanguage/data/signal.2.qml b/tests/auto/declarative/qmllanguage/data/signal.2.qml
new file mode 100644
index 0000000..5049192
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/signal.2.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ signal mySignal(,)
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/signal.3.errors.txt b/tests/auto/declarative/qmllanguage/data/signal.3.errors.txt
new file mode 100644
index 0000000..bf043ac
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/signal.3.errors.txt
@@ -0,0 +1 @@
+4:22:Expected token `identifier'
diff --git a/tests/auto/declarative/qmllanguage/data/signal.3.qml b/tests/auto/declarative/qmllanguage/data/signal.3.qml
new file mode 100644
index 0000000..9dd4cc7
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/signal.3.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ signal mySignal(a)
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/simpleBindings.qml b/tests/auto/declarative/qmllanguage/data/simpleBindings.qml
new file mode 100644
index 0000000..2fcd1a5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/simpleBindings.qml
@@ -0,0 +1,18 @@
+import Test 1.0
+MyTypeObject {
+ id: me
+ property int v1: 10
+ property int v2: 11
+
+ property int value1
+ property int value2
+ property int value3
+ property int value4
+
+ value1: v1
+ value2: me.v1
+ value3: v1 + v2
+ value4: Math.min(v1, v2)
+
+ objectProperty: me
+}
diff --git a/tests/auto/declarative/qmllanguage/data/simpleContainer.qml b/tests/auto/declarative/qmllanguage/data/simpleContainer.qml
new file mode 100644
index 0000000..c3a795f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/simpleContainer.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyContainer {
+ MyQmlObject {}
+ MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qmllanguage/data/simpleObject.qml b/tests/auto/declarative/qmllanguage/data/simpleObject.qml
new file mode 100644
index 0000000..30c7823
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/simpleObject.qml
@@ -0,0 +1,2 @@
+import Test 1.0
+MyQmlObject {}
diff --git a/tests/auto/declarative/qmllanguage/data/subdir/Test.qml b/tests/auto/declarative/qmllanguage/data/subdir/Test.qml
new file mode 100644
index 0000000..c4d5905
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/subdir/Test.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+Rectangle { }
diff --git a/tests/auto/declarative/qmllanguage/data/subdir/subsubdir/SubTest.qml b/tests/auto/declarative/qmllanguage/data/subdir/subsubdir/SubTest.qml
new file mode 100644
index 0000000..c4d5905
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/subdir/subsubdir/SubTest.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+Rectangle { }
diff --git a/tests/auto/declarative/qmllanguage/data/test.js b/tests/auto/declarative/qmllanguage/data/test.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/test.js
diff --git a/tests/auto/declarative/qmllanguage/data/test2.js b/tests/auto/declarative/qmllanguage/data/test2.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/test2.js
diff --git a/tests/auto/declarative/qmllanguage/data/unregisteredObject.errors.txt b/tests/auto/declarative/qmllanguage/data/unregisteredObject.errors.txt
new file mode 100644
index 0000000..347db05
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/unregisteredObject.errors.txt
@@ -0,0 +1 @@
+2:1:Type UnregisteredObjectType unavailable
diff --git a/tests/auto/declarative/qmllanguage/data/unregisteredObject.qml b/tests/auto/declarative/qmllanguage/data/unregisteredObject.qml
new file mode 100644
index 0000000..4969f62
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/unregisteredObject.qml
@@ -0,0 +1,2 @@
+import Test 1.0
+UnregisteredObjectType {}
diff --git a/tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt b/tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt
new file mode 100644
index 0000000..3cd626d
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt
@@ -0,0 +1 @@
+3:13:Invalid property assignment: unsupported type "QMatrix"
diff --git a/tests/auto/declarative/qmllanguage/data/unsupportedProperty.qml b/tests/auto/declarative/qmllanguage/data/unsupportedProperty.qml
new file mode 100644
index 0000000..9f19680
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/unsupportedProperty.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ matrix: "1,0,0,0,1,0,0,0,1"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/valueTypes.qml b/tests/auto/declarative/qmllanguage/data/valueTypes.qml
new file mode 100644
index 0000000..bf325a7
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/valueTypes.qml
@@ -0,0 +1,13 @@
+import Test 1.0
+MyTypeObject {
+ rectProperty.x: 10
+ rectProperty.y: 11
+ rectProperty.width: rectProperty.x + 2
+ rectProperty.height: 13
+
+ intProperty: rectProperty.x
+
+ onAction: { var a = rectProperty; a.x = 12; }
+
+ rectProperty2: rectProperty
+}
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.1.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.1.errors.txt
new file mode 100644
index 0000000..ba7a076
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.1.errors.txt
@@ -0,0 +1 @@
+3:12:Invalid property assignment: int expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.1.qml b/tests/auto/declarative/qmllanguage/data/wrongType.1.qml
new file mode 100644
index 0000000..289d37f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.1.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ value: "hello"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.10.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.10.errors.txt
new file mode 100644
index 0000000..ae75b52
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.10.errors.txt
@@ -0,0 +1 @@
+3:23:Invalid property assignment: datetime expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.10.qml b/tests/auto/declarative/qmllanguage/data/wrongType.10.qml
new file mode 100644
index 0000000..2cf0e50
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.10.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ dateTimeProperty: 12
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.11.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.11.errors.txt
new file mode 100644
index 0000000..23a4cda
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.11.errors.txt
@@ -0,0 +1 @@
+3:20:Invalid property assignment: point expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.11.qml b/tests/auto/declarative/qmllanguage/data/wrongType.11.qml
new file mode 100644
index 0000000..ae77ba1
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.11.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ pointProperty: "apples"
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.12.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.12.errors.txt
new file mode 100644
index 0000000..3092100
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.12.errors.txt
@@ -0,0 +1 @@
+3:19:Invalid property assignment: size expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.12.qml b/tests/auto/declarative/qmllanguage/data/wrongType.12.qml
new file mode 100644
index 0000000..b7a366f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.12.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ sizeProperty: "red"
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.13.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.13.errors.txt
new file mode 100644
index 0000000..ba7a076
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.13.errors.txt
@@ -0,0 +1 @@
+3:12:Invalid property assignment: int expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.13.qml b/tests/auto/declarative/qmllanguage/data/wrongType.13.qml
new file mode 100644
index 0000000..477aff1
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.13.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ value: "12"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.14.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.14.errors.txt
new file mode 100644
index 0000000..d621fdd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.14.errors.txt
@@ -0,0 +1 @@
+3:21:Invalid property assignment: string expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.14.qml b/tests/auto/declarative/qmllanguage/data/wrongType.14.qml
new file mode 100644
index 0000000..672d693
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.14.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ stringProperty: 10
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.15.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.15.errors.txt
new file mode 100644
index 0000000..44768e3
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.15.errors.txt
@@ -0,0 +1 @@
+3:18:Invalid property assignment: url expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.15.qml b/tests/auto/declarative/qmllanguage/data/wrongType.15.qml
new file mode 100644
index 0000000..633a5ba
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.15.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyTypeObject {
+ urlProperty: 12
+}
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.2.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.2.errors.txt
new file mode 100644
index 0000000..9ff9f25
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.2.errors.txt
@@ -0,0 +1 @@
+3:14:Invalid property assignment: boolean expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.2.qml b/tests/auto/declarative/qmllanguage/data/wrongType.2.qml
new file mode 100644
index 0000000..34b74f7
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.2.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ enabled: 5
+}
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.3.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.3.errors.txt
new file mode 100644
index 0000000..6d971c6
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.3.errors.txt
@@ -0,0 +1 @@
+3:11:Invalid property assignment: rect expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.3.qml b/tests/auto/declarative/qmllanguage/data/wrongType.3.qml
new file mode 100644
index 0000000..384181a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.3.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyQmlObject {
+ rect: "5,5x10"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.4.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.4.errors.txt
new file mode 100644
index 0000000..ef34d0e
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.4.errors.txt
@@ -0,0 +1 @@
+3:19:Invalid property assignment: unknown enumeration
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.4.qml b/tests/auto/declarative/qmllanguage/data/wrongType.4.qml
new file mode 100644
index 0000000..0787bf5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.4.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+MyTypeObject {
+ enumProperty: "InvalidEnumName"
+}
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.5.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.5.errors.txt
new file mode 100644
index 0000000..cab10bd
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.5.errors.txt
@@ -0,0 +1 @@
+3:19:Invalid property assignment: unsigned int expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.5.qml b/tests/auto/declarative/qmllanguage/data/wrongType.5.qml
new file mode 100644
index 0000000..c50ae9a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.5.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ uintProperty: -13
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.6.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.6.errors.txt
new file mode 100644
index 0000000..d0a0b00
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.6.errors.txt
@@ -0,0 +1 @@
+3:19:Invalid property assignment: double expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.6.qml b/tests/auto/declarative/qmllanguage/data/wrongType.6.qml
new file mode 100644
index 0000000..da10b78
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.6.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ realProperty: "Hello"
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.7.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.7.errors.txt
new file mode 100644
index 0000000..614346b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.7.errors.txt
@@ -0,0 +1 @@
+3:20:Invalid property assignment: color expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.7.qml b/tests/auto/declarative/qmllanguage/data/wrongType.7.qml
new file mode 100644
index 0000000..ddc3835
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.7.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ colorProperty: 12
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.8.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.8.errors.txt
new file mode 100644
index 0000000..1773c00
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.8.errors.txt
@@ -0,0 +1 @@
+3:19:Invalid property assignment: date expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.8.qml b/tests/auto/declarative/qmllanguage/data/wrongType.8.qml
new file mode 100644
index 0000000..a5f6756
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.8.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ dateProperty: 12
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.9.errors.txt b/tests/auto/declarative/qmllanguage/data/wrongType.9.errors.txt
new file mode 100644
index 0000000..8630975
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.9.errors.txt
@@ -0,0 +1 @@
+3:19:Invalid property assignment: time expected
diff --git a/tests/auto/declarative/qmllanguage/data/wrongType.9.qml b/tests/auto/declarative/qmllanguage/data/wrongType.9.qml
new file mode 100644
index 0000000..a3db732
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/wrongType.9.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+MyTypeObject {
+ timeProperty: 12
+}
+
diff --git a/tests/auto/declarative/qmllanguage/qmllanguage.pro b/tests/auto/declarative/qmllanguage/qmllanguage.pro
new file mode 100644
index 0000000..d1876ef
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qmllanguage.pro
@@ -0,0 +1,14 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+QT += script network
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmllanguage.cpp \
+ testtypes.cpp
+HEADERS += testtypes.h
+
+INCLUDEPATH += ../shared/
+HEADERS += ../shared/testhttpserver.h
+SOURCES += ../shared/testhttpserver.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/LocalInternal.qml b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/LocalInternal.qml
new file mode 100644
index 0000000..836c20a
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/LocalInternal.qml
@@ -0,0 +1,3 @@
+import Qt 4.6
+
+Image { source: "pics/blue.png" }
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/Test.qml b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/Test.qml
new file mode 100644
index 0000000..c4d5905
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/Test.qml
@@ -0,0 +1,2 @@
+import Qt 4.6
+Rectangle { }
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestLocal.qml b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestLocal.qml
new file mode 100644
index 0000000..11443ca
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestLocal.qml
@@ -0,0 +1 @@
+LocalInternal {}
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestSubDir.qml b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestSubDir.qml
new file mode 100644
index 0000000..0dfede4
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/TestSubDir.qml
@@ -0,0 +1,2 @@
+import "subdir"
+SubTest { }
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/pics/blue.png b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/pics/blue.png
new file mode 100644
index 0000000..46f815f
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/pics/blue.png
Binary files differ
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/qmldir b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/qmldir
new file mode 100644
index 0000000..b32f82b
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/qmldir
@@ -0,0 +1,3 @@
+Test 0.0 Test.qml
+TestSubDir 0.0 TestSubDir.qml
+TestLocal 0.0 TestLocal.qml
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/SubTest.qml b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/SubTest.qml
new file mode 100644
index 0000000..0ea9ec6
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/SubTest.qml
@@ -0,0 +1,3 @@
+import Qt 4.6
+
+Text {}
diff --git a/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/qmldir b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/qmldir
new file mode 100644
index 0000000..f7016c7
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/qtest/declarative/qmllanguage/subdir/qmldir
@@ -0,0 +1 @@
+SubTest 0.0 SubTest.qml
diff --git a/tests/auto/declarative/qmllanguage/testtypes.cpp b/tests/auto/declarative/qmllanguage/testtypes.cpp
new file mode 100644
index 0000000..f30f47e
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/testtypes.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "testtypes.h"
+
+QML_DEFINE_INTERFACE(MyInterface);
+QML_DEFINE_TYPE(Test,1,0,MyQmlObject,MyQmlObject);
+QML_DEFINE_TYPE(Test,1,0,MyTypeObject,MyTypeObject);
+QML_DEFINE_TYPE(Test,1,0,MyContainer,MyContainer);
+QML_DEFINE_TYPE(Test,1,0,MyPropertyValueSource,MyPropertyValueSource);
+QML_DEFINE_TYPE(Test,1,0,MyDotPropertyObject,MyDotPropertyObject);
+QML_DEFINE_TYPE(Test,1,0,MyNamespacedType,MyNamespace::MyNamespacedType);
+QML_DEFINE_TYPE(Test,1,0,MySecondNamespacedType,MyNamespace::MySecondNamespacedType);
+QML_DEFINE_NOCREATE_TYPE(MyGroupedObject);
+
+QVariant myCustomVariantTypeConverter(const QString &data)
+{
+ MyCustomVariantType rv;
+ rv.a = data.toInt();
+ return QVariant::fromValue(rv);
+}
+
diff --git a/tests/auto/declarative/qmllanguage/testtypes.h b/tests/auto/declarative/qmllanguage/testtypes.h
new file mode 100644
index 0000000..d6ca898
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/testtypes.h
@@ -0,0 +1,548 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TESTTYPES_H
+#define TESTTYPES_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qdatetime.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qvector3d.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlparserstatus.h>
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlscriptstring.h>
+
+QVariant myCustomVariantTypeConverter(const QString &data);
+
+class MyInterface
+{
+public:
+ MyInterface() : id(913) {}
+ int id;
+};
+Q_DECLARE_INTERFACE(MyInterface, "com.trolltech.Qt.Test.MyInterface");
+QML_DECLARE_INTERFACE(MyInterface);
+
+struct MyCustomVariantType
+{
+ MyCustomVariantType() : a(0) {}
+ int a;
+};
+Q_DECLARE_METATYPE(MyCustomVariantType);
+
+class MyAttachedObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+ Q_PROPERTY(int value2 READ value2 WRITE setValue2)
+public:
+ MyAttachedObject(QObject *parent) : QObject(parent), m_value(0), m_value2(0) {}
+
+ int value() const { return m_value; }
+ void setValue(int v) { m_value = v; }
+
+ int value2() const { return m_value2; }
+ void setValue2(int v) { m_value2 = v; }
+
+private:
+ int m_value;
+ int m_value2;
+};
+
+class MyQmlObject : public QObject, public MyInterface, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue FINAL)
+ Q_PROPERTY(QString readOnlyString READ readOnlyString)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
+ Q_PROPERTY(QRect rect READ rect WRITE setRect)
+ Q_PROPERTY(QMatrix matrix READ matrix WRITE setMatrix) //assumed to be unsupported by QML
+ Q_PROPERTY(MyInterface *interfaceProperty READ interface WRITE setInterface)
+ Q_PROPERTY(int onLiteralSignal READ onLiteralSignal WRITE setOnLiteralSignal);
+ Q_PROPERTY(MyCustomVariantType customType READ customType WRITE setCustomType);
+ Q_PROPERTY(MyQmlObject *qmlobjectProperty READ qmlobject WRITE setQmlobject)
+
+ Q_INTERFACES(MyInterface QmlParserStatus)
+public:
+ MyQmlObject() : m_value(-1), m_interface(0), m_qmlobject(0) { qRegisterMetaType<MyCustomVariantType>("MyCustomVariantType"); }
+
+ int value() const { return m_value; }
+ void setValue(int v) { m_value = v; }
+
+ QString readOnlyString() const { return QLatin1String(""); }
+
+ bool enabled() const { return false; }
+ void setEnabled(bool) {}
+
+ QRect rect() const { return QRect(); }
+ void setRect(const QRect&) {}
+
+ QMatrix matrix() const { return QMatrix(); }
+ void setMatrix(const QMatrix&) {}
+
+ MyInterface *interface() const { return m_interface; }
+ void setInterface(MyInterface *iface) { m_interface = iface; }
+
+ static MyAttachedObject *qmlAttachedProperties(QObject *other) {
+ return new MyAttachedObject(other);
+ }
+ Q_CLASSINFO("DefaultMethod", "basicSlot()");
+
+ int onLiteralSignal() const { return m_value; }
+ void setOnLiteralSignal(int v) { m_value = v; }
+
+ MyQmlObject *qmlobject() const { return m_qmlobject; }
+ void setQmlobject(MyQmlObject *o) { m_qmlobject = o; }
+
+ MyCustomVariantType customType() const { return m_custom; }
+ void setCustomType(const MyCustomVariantType &v) { m_custom = v; }
+public slots:
+ void basicSlot() { qWarning("MyQmlObject::basicSlot"); }
+ void basicSlotWithArgs(int v) { qWarning("MyQmlObject::basicSlotWithArgs(%d)", v); }
+
+signals:
+ void basicSignal();
+ void basicParameterizedSignal(int parameter);
+
+private:
+ friend class tst_qmllanguage;
+ int m_value;
+ MyInterface *m_interface;
+ MyQmlObject *m_qmlobject;
+ MyCustomVariantType m_custom;
+};
+QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(MyQmlObject);
+
+class MyGroupedObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QmlScriptString script READ script WRITE setScript);
+public:
+ QmlScriptString script() const { return m_script; }
+ void setScript(const QmlScriptString &s) { m_script = s; }
+
+private:
+ QmlScriptString m_script;
+};
+
+QML_DECLARE_TYPE(MyGroupedObject);
+
+
+class MyTypeObject : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(MyEnum)
+ Q_FLAGS(MyFlags)
+
+ Q_PROPERTY(QString id READ id WRITE setId);
+ Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty);
+ Q_PROPERTY(QmlComponent *componentProperty READ componentProperty WRITE setComponentProperty);
+ Q_PROPERTY(MyFlags flagProperty READ flagProperty WRITE setFlagProperty);
+ Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty);
+ Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty);
+ Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty);
+ Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty);
+ Q_PROPERTY(qreal realProperty READ realProperty WRITE setRealProperty);
+ Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty);
+ Q_PROPERTY(float floatProperty READ floatProperty WRITE setFloatProperty);
+ Q_PROPERTY(QColor colorProperty READ colorProperty WRITE setColorProperty);
+ Q_PROPERTY(QDate dateProperty READ dateProperty WRITE setDateProperty);
+ Q_PROPERTY(QTime timeProperty READ timeProperty WRITE setTimeProperty);
+ Q_PROPERTY(QDateTime dateTimeProperty READ dateTimeProperty WRITE setDateTimeProperty);
+ Q_PROPERTY(QPoint pointProperty READ pointProperty WRITE setPointProperty);
+ Q_PROPERTY(QPointF pointFProperty READ pointFProperty WRITE setPointFProperty);
+ Q_PROPERTY(QSize sizeProperty READ sizeProperty WRITE setSizeProperty);
+ Q_PROPERTY(QSizeF sizeFProperty READ sizeFProperty WRITE setSizeFProperty);
+ Q_PROPERTY(QRect rectProperty READ rectProperty WRITE setRectProperty NOTIFY rectPropertyChanged);
+ Q_PROPERTY(QRect rectProperty2 READ rectProperty2 WRITE setRectProperty2);
+ Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty);
+ Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty);
+ Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty);
+ Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty);
+ Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty);
+
+ Q_PROPERTY(QmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty);
+ Q_PROPERTY(MyGroupedObject *grouped READ grouped CONSTANT);
+ Q_PROPERTY(MyGroupedObject *nullGrouped READ nullGrouped CONSTANT);
+
+public:
+ MyTypeObject()
+ : objectPropertyValue(0), componentPropertyValue(0) {}
+
+ QString idValue;
+ QString id() const {
+ return idValue;
+ }
+ void setId(const QString &v) {
+ idValue = v;
+ }
+
+ QObject *objectPropertyValue;
+ QObject *objectProperty() const {
+ return objectPropertyValue;
+ }
+ void setObjectProperty(QObject *v) {
+ objectPropertyValue = v;
+ }
+
+ QmlComponent *componentPropertyValue;
+ QmlComponent *componentProperty() const {
+ return componentPropertyValue;
+ }
+ void setComponentProperty(QmlComponent *v) {
+ componentPropertyValue = v;
+ }
+
+ enum MyFlag { FlagVal1 = 0x01, FlagVal2 = 0x02, FlagVal3 = 0x04 };
+ Q_DECLARE_FLAGS(MyFlags, MyFlag)
+ MyFlags flagPropertyValue;
+ MyFlags flagProperty() const {
+ return flagPropertyValue;
+ }
+ void setFlagProperty(MyFlags v) {
+ flagPropertyValue = v;
+ }
+
+ enum MyEnum { EnumVal1, EnumVal2 };
+ MyEnum enumPropertyValue;
+ MyEnum enumProperty() const {
+ return enumPropertyValue;
+ }
+ void setEnumProperty(MyEnum v) {
+ enumPropertyValue = v;
+ }
+
+ QString stringPropertyValue;
+ QString stringProperty() const {
+ return stringPropertyValue;
+ }
+ void setStringProperty(const QString &v) {
+ stringPropertyValue = v;
+ }
+
+ uint uintPropertyValue;
+ uint uintProperty() const {
+ return uintPropertyValue;
+ }
+ void setUintProperty(const uint &v) {
+ uintPropertyValue = v;
+ }
+
+ int intPropertyValue;
+ int intProperty() const {
+ return intPropertyValue;
+ }
+ void setIntProperty(const int &v) {
+ intPropertyValue = v;
+ }
+
+ qreal realPropertyValue;
+ qreal realProperty() const {
+ return realPropertyValue;
+ }
+ void setRealProperty(const qreal &v) {
+ realPropertyValue = v;
+ }
+
+ double doublePropertyValue;
+ double doubleProperty() const {
+ return doublePropertyValue;
+ }
+ void setDoubleProperty(const double &v) {
+ doublePropertyValue = v;
+ }
+
+ float floatPropertyValue;
+ float floatProperty() const {
+ return floatPropertyValue;
+ }
+ void setFloatProperty(const float &v) {
+ floatPropertyValue = v;
+ }
+
+ QColor colorPropertyValue;
+ QColor colorProperty() const {
+ return colorPropertyValue;
+ }
+ void setColorProperty(const QColor &v) {
+ colorPropertyValue = v;
+ }
+
+ QDate datePropertyValue;
+ QDate dateProperty() const {
+ return datePropertyValue;
+ }
+ void setDateProperty(const QDate &v) {
+ datePropertyValue = v;
+ }
+
+ QTime timePropertyValue;
+ QTime timeProperty() const {
+ return timePropertyValue;
+ }
+ void setTimeProperty(const QTime &v) {
+ timePropertyValue = v;
+ }
+
+ QDateTime dateTimePropertyValue;
+ QDateTime dateTimeProperty() const {
+ return dateTimePropertyValue;
+ }
+ void setDateTimeProperty(const QDateTime &v) {
+ dateTimePropertyValue = v;
+ }
+
+ QPoint pointPropertyValue;
+ QPoint pointProperty() const {
+ return pointPropertyValue;
+ }
+ void setPointProperty(const QPoint &v) {
+ pointPropertyValue = v;
+ }
+
+ QPointF pointFPropertyValue;
+ QPointF pointFProperty() const {
+ return pointFPropertyValue;
+ }
+ void setPointFProperty(const QPointF &v) {
+ pointFPropertyValue = v;
+ }
+
+ QSize sizePropertyValue;
+ QSize sizeProperty() const {
+ return sizePropertyValue;
+ }
+ void setSizeProperty(const QSize &v) {
+ sizePropertyValue = v;
+ }
+
+ QSizeF sizeFPropertyValue;
+ QSizeF sizeFProperty() const {
+ return sizeFPropertyValue;
+ }
+ void setSizeFProperty(const QSizeF &v) {
+ sizeFPropertyValue = v;
+ }
+
+ QRect rectPropertyValue;
+ QRect rectProperty() const {
+ return rectPropertyValue;
+ }
+ void setRectProperty(const QRect &v) {
+ rectPropertyValue = v;
+ emit rectPropertyChanged();
+ }
+
+ QRect rectPropertyValue2;
+ QRect rectProperty2() const {
+ return rectPropertyValue2;
+ }
+ void setRectProperty2(const QRect &v) {
+ rectPropertyValue2 = v;
+ }
+
+ QRectF rectFPropertyValue;
+ QRectF rectFProperty() const {
+ return rectFPropertyValue;
+ }
+ void setRectFProperty(const QRectF &v) {
+ rectFPropertyValue = v;
+ }
+
+ bool boolPropertyValue;
+ bool boolProperty() const {
+ return boolPropertyValue;
+ }
+ void setBoolProperty(const bool &v) {
+ boolPropertyValue = v;
+ }
+
+ QVariant variantPropertyValue;
+ QVariant variantProperty() const {
+ return variantPropertyValue;
+ }
+ void setVariantProperty(const QVariant &v) {
+ variantPropertyValue = v;
+ }
+
+ QVector3D vectorPropertyValue;
+ QVector3D vectorProperty() const {
+ return vectorPropertyValue;
+ }
+ void setVectorProperty(const QVector3D &v) {
+ vectorPropertyValue = v;
+ }
+
+ QUrl urlPropertyValue;
+ QUrl urlProperty() const {
+ return urlPropertyValue;
+ }
+ void setUrlProperty(const QUrl &v) {
+ urlPropertyValue = v;
+ }
+
+ QmlScriptString scriptPropertyValue;
+ QmlScriptString scriptProperty() const {
+ return scriptPropertyValue;
+ }
+ void setScriptProperty(const QmlScriptString &v) {
+ scriptPropertyValue = v;
+ }
+
+ MyGroupedObject groupedValue;
+ MyGroupedObject *grouped() { return &groupedValue; }
+
+ MyGroupedObject *nullGrouped() { return 0; }
+
+ void doAction() { emit action(); }
+signals:
+ void action();
+ void rectPropertyChanged();
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
+QML_DECLARE_TYPE(MyTypeObject);
+
+class MyContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<QObject*>* children READ children)
+ Q_PROPERTY(QList<MyInterface*>* qlistInterfaces READ qlistInterfaces)
+ Q_PROPERTY(QmlList<MyInterface*>* qmllistInterfaces READ qmllistInterfaces)
+ Q_CLASSINFO("DefaultProperty", "children");
+public:
+ MyContainer() {}
+
+ QList<QObject*> *children() { return &m_children; }
+ QList<MyInterface *> *qlistInterfaces() { return &m_interfaces; }
+ QmlList<MyInterface *> *qmllistInterfaces() { return &m_qmlinterfaces; }
+ const QmlConcreteList<MyInterface *> &qmllistAccessor() const { return m_qmlinterfaces; }
+
+private:
+ QList<QObject*> m_children;
+ QList<MyInterface *> m_interfaces;
+ QmlConcreteList<MyInterface *> m_qmlinterfaces;
+};
+
+QML_DECLARE_TYPE(MyContainer);
+
+
+class MyPropertyValueSource : public QObject, public QmlPropertyValueSource
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlPropertyValueSource)
+public:
+ MyPropertyValueSource()
+ : QmlPropertyValueSource() {}
+
+ QmlMetaProperty prop;
+ virtual void setTarget(const QmlMetaProperty &p)
+ {
+ prop = p;
+ }
+};
+QML_DECLARE_TYPE(MyPropertyValueSource);
+
+class MyDotPropertyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(MyQmlObject *obj READ obj)
+ Q_PROPERTY(MyQmlObject *readWriteObj READ readWriteObj WRITE setReadWriteObj)
+public:
+ MyDotPropertyObject() : m_rwobj(0), m_ownRWObj(false) {}
+ ~MyDotPropertyObject()
+ {
+ if (m_ownRWObj)
+ delete m_rwobj;
+ }
+
+ MyQmlObject *obj() { return 0; }
+
+ MyQmlObject *readWriteObj()
+ {
+ if (!m_rwobj) {
+ m_rwobj = new MyQmlObject;
+ m_ownRWObj = true;
+ }
+ return m_rwobj;
+ }
+
+ void setReadWriteObj(MyQmlObject *obj)
+ {
+ if (m_ownRWObj) {
+ delete m_rwobj;
+ m_ownRWObj = false;
+ }
+
+ m_rwobj = obj;
+ }
+
+private:
+ MyQmlObject *m_rwobj;
+ bool m_ownRWObj;
+};
+
+QML_DECLARE_TYPE(MyDotPropertyObject);
+
+namespace MyNamespace {
+ class MyNamespacedType : public QObject
+ {
+ Q_OBJECT
+ };
+
+ class MySecondNamespacedType : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY(QmlList<MyNamespace::MyNamespacedType *> *list READ list);
+ public:
+ QmlList<MyNamespacedType *> *list() { return &m_list; }
+
+ private:
+ QmlConcreteList<MyNamespacedType *> m_list;
+ };
+}
+QML_DECLARE_TYPE(MyNamespace::MyNamespacedType);
+QML_DECLARE_TYPE(MyNamespace::MySecondNamespacedType);
+
+#endif // TESTTYPES_H
diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
new file mode 100644
index 0000000..3029501
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
@@ -0,0 +1,1396 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdir.h>
+#include <private/qmlmetaproperty_p.h>
+#include "testtypes.h"
+
+#include "../../../shared/util.h"
+
+/*
+This test case covers QML language issues. This covers everything that does not
+involve evaluating ECMAScript expressions and bindings.
+
+Evaluation of expressions and bindings is covered in qmlecmascript
+*/
+class tst_qmllanguage : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmllanguage() {
+ QmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
+ QFileInfo fileInfo(__FILE__);
+ engine.addImportPath(fileInfo.absoluteDir().filePath(QLatin1String("data/lib")));
+ }
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void errors_data();
+ void errors();
+
+ void simpleObject();
+ void simpleContainer();
+ void interfaceProperty();
+ void interfaceQmlList();
+ void interfaceQList();
+ void assignObjectToSignal();
+ void assignObjectToVariant();
+ void assignLiteralSignalProperty();
+ void assignQmlComponent();
+ void assignBasicTypes();
+ void assignTypeExtremes();
+ void assignCompositeToType();
+ void customParserTypes();
+ void rootAsQmlComponent();
+ void inlineQmlComponents();
+ void idProperty();
+ void assignSignal();
+ void dynamicProperties();
+ void dynamicPropertiesNested();
+ void listProperties();
+ void dynamicObjectProperties();
+ void dynamicSignalsAndSlots();
+ void simpleBindings();
+ void autoComponentCreation();
+ void propertyValueSource();
+ void attachedProperties();
+ void dynamicObjects();
+ void customVariantTypes();
+ void valueTypes();
+ void cppnamespace();
+ void aliasProperties();
+ void componentCompositeType();
+ void i18n();
+ void i18n_data();
+ void onCompleted();
+ void scriptString();
+ void defaultPropertyListOrder();
+ void declaredPropertyValues();
+
+ void importsBuiltin_data();
+ void importsBuiltin();
+ void importsLocal_data();
+ void importsLocal();
+ void importsRemote_data();
+ void importsRemote();
+ void importsInstalled_data();
+ void importsInstalled();
+ void importsOrder_data();
+ void importsOrder();
+
+ void qmlAttachedPropertiesObjectMethod();
+
+ // regression tests for crashes
+ void crash1();
+ void crash2();
+
+private:
+ QmlEngine engine;
+ void testType(const QString& qml, const QString& type);
+};
+
+#define VERIFY_ERRORS(errorfile) \
+ if (!errorfile) { \
+ if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
+ qWarning() << "Unexpected Errors:" << component.errors(); \
+ QVERIFY(!component.isError()); \
+ QVERIFY(component.errors().isEmpty()); \
+ } else { \
+ QFile file(QLatin1String(SRCDIR) + QLatin1String("/data/") + QLatin1String(errorfile)); \
+ QVERIFY(file.open(QIODevice::ReadOnly)); \
+ QByteArray data = file.readAll(); \
+ file.close(); \
+ QList<QByteArray> expected = data.split('\n'); \
+ expected.removeAll(QByteArray("")); \
+ QList<QmlError> errors = component.errors(); \
+ QList<QByteArray> actual; \
+ for (int ii = 0; ii < errors.count(); ++ii) { \
+ const QmlError &error = errors.at(ii); \
+ QByteArray errorStr = QByteArray::number(error.line()) + ":" + \
+ QByteArray::number(error.column()) + ":" + \
+ error.description().toUtf8(); \
+ actual << errorStr; \
+ } \
+ if (qgetenv("DEBUG") != "" && expected != actual) \
+ qWarning() << "Expected:" << expected << "Actual:" << actual; \
+ if (qgetenv("QMLLANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
+ QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
+ QVERIFY(file.open(QIODevice::WriteOnly)); \
+ for (int ii = 0; ii < actual.count(); ++ii) { \
+ file.write(actual.at(ii)); file.write("\n"); \
+ } \
+ file.close(); \
+ } else { \
+ QCOMPARE(expected, actual); \
+ } \
+ }
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ QFileInfo fileInfo(__FILE__);
+ return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(QLatin1String("data/") + filename));
+}
+
+inline QUrl TEST_FILE(const char *filename)
+{
+ return TEST_FILE(QLatin1String(filename));
+}
+
+void tst_qmllanguage::initTestCase()
+{
+ // Create locale-specific file
+ // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit
+ // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters
+ // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded
+ QFile in(TEST_FILE(QLatin1String("I18nType30.qml")).toLocalFile());
+ QVERIFY(in.open(QIODevice::ReadOnly));
+ QFile out(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile());
+ QVERIFY(out.open(QIODevice::WriteOnly));
+ out.write(in.readAll());
+}
+
+void tst_qmllanguage::cleanupTestCase()
+{
+ QVERIFY(QFile::remove(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()));
+}
+
+void tst_qmllanguage::errors_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("errorFile");
+ QTest::addColumn<bool>("create");
+
+ QTest::newRow("nonexistantProperty.1") << "nonexistantProperty.1.qml" << "nonexistantProperty.1.errors.txt" << false;
+ QTest::newRow("nonexistantProperty.2") << "nonexistantProperty.2.qml" << "nonexistantProperty.2.errors.txt" << false;
+ QTest::newRow("nonexistantProperty.3") << "nonexistantProperty.3.qml" << "nonexistantProperty.3.errors.txt" << false;
+ QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false;
+ QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false;
+ QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false;
+
+ QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false;
+ QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false;
+ QTest::newRow("wrongType (bad rect)") << "wrongType.3.qml" << "wrongType.3.errors.txt" << false;
+
+ QTest::newRow("wrongType (invalid enum)") << "wrongType.4.qml" << "wrongType.4.errors.txt" << false;
+ QTest::newRow("wrongType (int for uint)") << "wrongType.5.qml" << "wrongType.5.errors.txt" << false;
+ QTest::newRow("wrongType (string for real)") << "wrongType.6.qml" << "wrongType.6.errors.txt" << false;
+ QTest::newRow("wrongType (int for color)") << "wrongType.7.qml" << "wrongType.7.errors.txt" << false;
+ QTest::newRow("wrongType (int for date)") << "wrongType.8.qml" << "wrongType.8.errors.txt" << false;
+ QTest::newRow("wrongType (int for time)") << "wrongType.9.qml" << "wrongType.9.errors.txt" << false;
+ QTest::newRow("wrongType (int for datetime)") << "wrongType.10.qml" << "wrongType.10.errors.txt" << false;
+ QTest::newRow("wrongType (string for point)") << "wrongType.11.qml" << "wrongType.11.errors.txt" << false;
+ QTest::newRow("wrongType (color for size)") << "wrongType.12.qml" << "wrongType.12.errors.txt" << false;
+ QTest::newRow("wrongType (number string for int)") << "wrongType.13.qml" << "wrongType.13.errors.txt" << false;
+ QTest::newRow("wrongType (int for string)") << "wrongType.14.qml" << "wrongType.14.errors.txt" << false;
+ QTest::newRow("wrongType (int for url)") << "wrongType.15.qml" << "wrongType.15.errors.txt" << false;
+
+ QTest::newRow("readOnly.1") << "readOnly.1.qml" << "readOnly.1.errors.txt" << false;
+ QTest::newRow("readOnly.2") << "readOnly.2.qml" << "readOnly.2.errors.txt" << false;
+ QTest::newRow("readOnly.3") << "readOnly.3.qml" << "readOnly.3.errors.txt" << false;
+
+ QTest::newRow("listAssignment.1") << "listAssignment.1.qml" << "listAssignment.1.errors.txt" << false;
+ QTest::newRow("listAssignment.2") << "listAssignment.2.qml" << "listAssignment.2.errors.txt" << false;
+ QTest::newRow("listAssignment.3") << "listAssignment.3.qml" << "listAssignment.3.errors.txt" << false;
+
+ QTest::newRow("invalidID.1") << "invalidID.qml" << "invalidID.errors.txt" << false;
+ QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false;
+ QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false;
+ QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false;
+ QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false;
+ QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false;
+
+ QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false;
+ QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true;
+ QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false;
+ QTest::newRow("duplicateIDs") << "duplicateIDs.qml" << "duplicateIDs.errors.txt" << false;
+ QTest::newRow("unregisteredObject") << "unregisteredObject.qml" << "unregisteredObject.errors.txt" << false;
+ QTest::newRow("empty") << "empty.qml" << "empty.errors.txt" << false;
+ QTest::newRow("missingObject") << "missingObject.qml" << "missingObject.errors.txt" << false;
+ QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false;
+ QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false;
+ QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false;
+ QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false;
+
+ QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false;
+ QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false;
+ QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false;
+ QTest::newRow("invalidGroupedProperty.4") << "invalidGroupedProperty.4.qml" << "invalidGroupedProperty.4.errors.txt" << false;
+ QTest::newRow("invalidGroupedProperty.5") << "invalidGroupedProperty.5.qml" << "invalidGroupedProperty.5.errors.txt" << false;
+ QTest::newRow("invalidGroupedProperty.6") << "invalidGroupedProperty.6.qml" << "invalidGroupedProperty.6.errors.txt" << false;
+ QTest::newRow("invalidGroupedProperty.7") << "invalidGroupedProperty.7.qml" << "invalidGroupedProperty.7.errors.txt" << true;
+
+ QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false;
+ QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false;
+ QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false;
+ QTest::newRow("invalidImportID") << "invalidImportID.qml" << "invalidImportID.errors.txt" << false;
+
+ QTest::newRow("signal.1") << "signal.1.qml" << "signal.1.errors.txt" << false;
+ QTest::newRow("signal.2") << "signal.2.qml" << "signal.2.errors.txt" << false;
+ QTest::newRow("signal.3") << "signal.3.qml" << "signal.3.errors.txt" << false;
+
+ QTest::newRow("property.1") << "property.1.qml" << "property.1.errors.txt" << false;
+ QTest::newRow("property.2") << "property.2.qml" << "property.2.errors.txt" << false;
+ QTest::newRow("property.3") << "property.3.qml" << "property.3.errors.txt" << false;
+ QTest::newRow("property.4") << "property.4.qml" << "property.4.errors.txt" << false;
+ QTest::newRow("property.5") << "property.5.qml" << "property.5.errors.txt" << false;
+
+ QTest::newRow("Script.1") << "script.1.qml" << "script.1.errors.txt" << false;
+ QTest::newRow("Script.2") << "script.2.qml" << "script.2.errors.txt" << false;
+ QTest::newRow("Script.3") << "script.3.qml" << "script.3.errors.txt" << false;
+ QTest::newRow("Script.4") << "script.4.qml" << "script.4.errors.txt" << false;
+ QTest::newRow("Script.5") << "script.5.qml" << "script.5.errors.txt" << false;
+ QTest::newRow("Script.6") << "script.6.qml" << "script.6.errors.txt" << false;
+ QTest::newRow("Script.7") << "script.7.qml" << "script.7.errors.txt" << false;
+ QTest::newRow("Script.8") << "script.8.qml" << "script.8.errors.txt" << false;
+ QTest::newRow("Script.9") << "script.9.qml" << "script.9.errors.txt" << false;
+ QTest::newRow("Script.10") << "script.10.qml" << "script.10.errors.txt" << false;
+ QTest::newRow("Script.11") << "script.11.qml" << "script.11.errors.txt" << false;
+ QTest::newRow("Script.12") << "script.12.qml" << "script.12.errors.txt" << false;
+
+ QTest::newRow("Component.1") << "component.1.qml" << "component.1.errors.txt" << false;
+ QTest::newRow("Component.2") << "component.2.qml" << "component.2.errors.txt" << false;
+ QTest::newRow("Component.3") << "component.3.qml" << "component.3.errors.txt" << false;
+ QTest::newRow("Component.4") << "component.4.qml" << "component.4.errors.txt" << false;
+ QTest::newRow("Component.5") << "component.5.qml" << "component.5.errors.txt" << false;
+ QTest::newRow("Component.6") << "component.6.qml" << "component.6.errors.txt" << false;
+
+ QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.3") << "invalidAttachedProperty.3.qml" << "invalidAttachedProperty.3.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.4") << "invalidAttachedProperty.4.qml" << "invalidAttachedProperty.4.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.5") << "invalidAttachedProperty.5.qml" << "invalidAttachedProperty.5.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.6") << "invalidAttachedProperty.6.qml" << "invalidAttachedProperty.6.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.7") << "invalidAttachedProperty.7.qml" << "invalidAttachedProperty.7.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.8") << "invalidAttachedProperty.8.qml" << "invalidAttachedProperty.8.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.9") << "invalidAttachedProperty.9.qml" << "invalidAttachedProperty.9.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.10") << "invalidAttachedProperty.10.qml" << "invalidAttachedProperty.10.errors.txt" << false;
+ QTest::newRow("invalidAttachedProperty.11") << "invalidAttachedProperty.11.qml" << "invalidAttachedProperty.11.errors.txt" << false;
+
+ QTest::newRow("nestedErrors") << "nestedErrors.qml" << "nestedErrors.errors.txt" << false;
+ QTest::newRow("defaultGrouped") << "defaultGrouped.qml" << "defaultGrouped.errors.txt" << false;
+ QTest::newRow("emptySignal") << "emptySignal.qml" << "emptySignal.errors.txt" << false;
+ QTest::newRow("doubleSignal") << "doubleSignal.qml" << "doubleSignal.errors.txt" << false;
+ QTest::newRow("invalidRoot") << "invalidRoot.qml" << "invalidRoot.errors.txt" << false;
+ QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false;
+ QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false;
+}
+
+
+void tst_qmllanguage::errors()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, errorFile);
+ QFETCH(bool, create);
+
+ if (file == "invalidID.6.qml")
+ QSKIP("Test disabled until we strictly disallow ids from beginning with uppercase letters", SkipSingle);
+
+ QmlComponent component(&engine, TEST_FILE(file));
+
+ if(create) {
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ VERIFY_ERRORS(errorFile.toLatin1().constData());
+}
+
+void tst_qmllanguage::simpleObject()
+{
+ QmlComponent component(&engine, TEST_FILE("simpleObject.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+void tst_qmllanguage::simpleContainer()
+{
+ QmlComponent component(&engine, TEST_FILE("simpleContainer.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QCOMPARE(container->children()->count(),2);
+}
+
+void tst_qmllanguage::interfaceProperty()
+{
+ QmlComponent component(&engine, TEST_FILE("interfaceProperty.qml"));
+ VERIFY_ERRORS(0);
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->interface());
+ QVERIFY(object->interface()->id == 913);
+}
+
+void tst_qmllanguage::interfaceQmlList()
+{
+ QmlComponent component(&engine, TEST_FILE("interfaceQmlList.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qmllistAccessor().count() == 2);
+ for(int ii = 0; ii < 2; ++ii)
+ QVERIFY(container->qmllistAccessor().at(ii)->id == 913);
+}
+
+void tst_qmllanguage::interfaceQList()
+{
+ QmlComponent component(&engine, TEST_FILE("interfaceQList.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qlistInterfaces()->count() == 2);
+ for(int ii = 0; ii < 2; ++ii)
+ QVERIFY(container->qlistInterfaces()->at(ii)->id == 913);
+}
+
+void tst_qmllanguage::assignObjectToSignal()
+{
+ QmlComponent component(&engine, TEST_FILE("assignObjectToSignal.qml"));
+ VERIFY_ERRORS(0);
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
+ emit object->basicSignal();
+}
+
+void tst_qmllanguage::assignObjectToVariant()
+{
+ QmlComponent component(&engine, TEST_FILE("assignObjectToVariant.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVariant v = object->property("a");
+ QVERIFY(v.userType() == qMetaTypeId<QObject *>());
+}
+
+void tst_qmllanguage::assignLiteralSignalProperty()
+{
+ QmlComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.qml"));
+ VERIFY_ERRORS(0);
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->onLiteralSignal(), 10);
+}
+
+// Test is an external component can be loaded and assigned (to a qlist)
+void tst_qmllanguage::assignQmlComponent()
+{
+ QmlComponent component(&engine, TEST_FILE("assignQmlComponent.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->children()->count() == 1);
+ QObject *child = object->children()->at(0);
+ QCOMPARE(child->property("x"), QVariant(10));
+ QCOMPARE(child->property("y"), QVariant(11));
+}
+
+// Test literal assignment to all the basic types
+void tst_qmllanguage::assignBasicTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
+ VERIFY_ERRORS(0);
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
+ QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
+ QCOMPARE(object->stringProperty(), QString("Hello World!"));
+ QCOMPARE(object->uintProperty(), uint(10));
+ QCOMPARE(object->intProperty(), -19);
+ QCOMPARE((float)object->realProperty(), float(23.2));
+ QCOMPARE((float)object->doubleProperty(), float(-19.7));
+ QCOMPARE((float)object->floatProperty(), float(8.5));
+ QCOMPARE(object->colorProperty(), QColor("red"));
+ QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
+ QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
+ QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
+ QCOMPARE(object->pointProperty(), QPoint(99,13));
+ QCOMPARE(object->pointFProperty(), QPointF((float)-10.1, (float)12.3));
+ QCOMPARE(object->sizeProperty(), QSize(99, 13));
+ QCOMPARE(object->sizeFProperty(), QSizeF((float)0.1, (float)0.2));
+ QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
+ QCOMPARE(object->rectFProperty(), QRectF((float)1000.1, (float)-10.9, (float)400, (float)90.99));
+ QCOMPARE(object->boolProperty(), true);
+ QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
+ QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
+ QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
+ QVERIFY(object->objectProperty() != 0);
+ MyTypeObject *child = qobject_cast<MyTypeObject *>(object->objectProperty());
+ QVERIFY(child != 0);
+ QCOMPARE(child->intProperty(), 8);
+}
+
+// Test edge case type assignments
+void tst_qmllanguage::assignTypeExtremes()
+{
+ QmlComponent component(&engine, TEST_FILE("assignTypeExtremes.qml"));
+ VERIFY_ERRORS(0);
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->uintProperty(), 0xEE6B2800);
+ QCOMPARE(object->intProperty(), -0x77359400);
+}
+
+// Test that a composite type can assign to a property of its base type
+void tst_qmllanguage::assignCompositeToType()
+{
+ QmlComponent component(&engine, TEST_FILE("assignCompositeToType.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+// Tests that custom parser types can be instantiated
+void tst_qmllanguage::customParserTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("customParserTypes.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("count") == QVariant(2));
+}
+
+// Tests that the root item can be a custom component
+void tst_qmllanguage::rootAsQmlComponent()
+{
+ QmlComponent component(&engine, TEST_FILE("rootAsQmlComponent.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("x"), QVariant(11));
+ QCOMPARE(object->children()->count(), 2);
+}
+
+// Tests that components can be specified inline
+void tst_qmllanguage::inlineQmlComponents()
+{
+ QmlComponent component(&engine, TEST_FILE("inlineQmlComponents.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->children()->count(), 1);
+ QmlComponent *comp = qobject_cast<QmlComponent *>(object->children()->at(0));
+ QVERIFY(comp != 0);
+ MyQmlObject *compObject = qobject_cast<MyQmlObject *>(comp->create());
+ QVERIFY(compObject != 0);
+ QCOMPARE(compObject->value(), 11);
+}
+
+// Tests that types that have an id property have it set
+void tst_qmllanguage::idProperty()
+{
+ QmlComponent component(&engine, TEST_FILE("idProperty.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->children()->count(), 1);
+ MyTypeObject *child =
+ qobject_cast<MyTypeObject *>(object->children()->at(0));
+ QVERIFY(child != 0);
+ QCOMPARE(child->id(), QString("myObjectId"));
+ QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
+}
+
+// Tests that signals can be assigned to
+void tst_qmllanguage::assignSignal()
+{
+ QmlComponent component(&engine, TEST_FILE("assignSignal.qml"));
+ VERIFY_ERRORS(0);
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
+ emit object->basicSignal();
+ QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
+ emit object->basicParameterizedSignal(9);
+}
+
+// Tests the creation and assignment of dynamic properties
+void tst_qmllanguage::dynamicProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicProperties.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("intProperty"), QVariant(10));
+ QCOMPARE(object->property("boolProperty"), QVariant(false));
+ QCOMPARE(object->property("doubleProperty"), QVariant(-10.1));
+ QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9));
+ QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
+ QCOMPARE(object->property("urlProperty"), QVariant(TEST_FILE("main.qml")));
+ QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
+ QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
+ QCOMPARE(object->property("varProperty"), QVariant("Hello World!"));
+ QCOMPARE(object->property("variantProperty"), QVariant(12));
+}
+
+// Test that nested types can use dynamic properties
+void tst_qmllanguage::dynamicPropertiesNested()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicPropertiesNested.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("super_a").toInt(), 11); // Overridden
+ QCOMPARE(object->property("super_c").toInt(), 14); // Inherited
+ QCOMPARE(object->property("a").toInt(), 13); // New
+ QCOMPARE(object->property("b").toInt(), 12); // New
+
+ delete object;
+}
+
+// Tests the creation and assignment to dynamic list properties
+void tst_qmllanguage::listProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("listProperties.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toInt(), 2);
+}
+
+// Tests the creation and assignment of dynamic object properties
+// ### Not complete
+void tst_qmllanguage::dynamicObjectProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
+ QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
+}
+
+// Tests the declaration of dynamic signals and slots
+void tst_qmllanguage::dynamicSignalsAndSlots()
+{
+ QTest::ignoreMessage(QtDebugMsg, "1921");
+
+ QmlComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1);
+ QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1);
+ QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1);
+ QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1);
+
+ QCOMPARE(object->property("test").toInt(), 0);
+ QMetaObject::invokeMethod(object, "slot3", Qt::DirectConnection, Q_ARG(QVariant, QVariant(10)));
+ QCOMPARE(object->property("test").toInt(), 10);
+}
+
+void tst_qmllanguage::simpleBindings()
+{
+ QmlComponent component(&engine, TEST_FILE("simpleBindings.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("value1"), QVariant(10));
+ QCOMPARE(object->property("value2"), QVariant(10));
+ QCOMPARE(object->property("value3"), QVariant(21));
+ QCOMPARE(object->property("value4"), QVariant(10));
+ QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object));
+}
+
+void tst_qmllanguage::autoComponentCreation()
+{
+ QmlComponent component(&engine, TEST_FILE("autoComponentCreation.qml"));
+ VERIFY_ERRORS(0);
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->componentProperty() != 0);
+ MyTypeObject *child = qobject_cast<MyTypeObject *>(object->componentProperty()->create());
+ QVERIFY(child != 0);
+ QCOMPARE(child->realProperty(), qreal(9));
+}
+
+void tst_qmllanguage::propertyValueSource()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("propertyValueSource.qml"));
+ VERIFY_ERRORS(0);
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QList<QObject *> valueSources;
+ QObjectList allChildren = object->findChildren<QObject*>();
+ foreach (QObject *child, allChildren) {
+ if (qobject_cast<QmlPropertyValueSource *>(child))
+ valueSources.append(child);
+ }
+
+ QCOMPARE(valueSources.count(), 1);
+ MyPropertyValueSource *valueSource =
+ qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
+ QVERIFY(valueSource != 0);
+ QCOMPARE(valueSource->prop.object(), object);
+ QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("propertyValueSource.2.qml"));
+ VERIFY_ERRORS(0);
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QList<QObject *> valueSources;
+ QObjectList allChildren = object->findChildren<QObject*>();
+ foreach (QObject *child, allChildren) {
+ if (qobject_cast<QmlPropertyValueSource *>(child))
+ valueSources.append(child);
+ }
+
+ QCOMPARE(valueSources.count(), 1);
+ MyPropertyValueSource *valueSource =
+ qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
+ QVERIFY(valueSource != 0);
+ QCOMPARE(valueSource->prop.object(), object);
+ QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
+ }
+}
+
+void tst_qmllanguage::attachedProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("attachedProperties.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QObject *attached = qmlAttachedPropertiesObject<MyQmlObject>(object);
+ QVERIFY(attached != 0);
+ QCOMPARE(attached->property("value"), QVariant(10));
+ QCOMPARE(attached->property("value2"), QVariant(13));
+}
+
+// Tests non-static object properties
+void tst_qmllanguage::dynamicObjects()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicObject.1.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+// Tests the registration of custom variant string converters
+void tst_qmllanguage::customVariantTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("customVariantTypes.qml"));
+ VERIFY_ERRORS(0);
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->customType().a, 10);
+}
+
+void tst_qmllanguage::valueTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("valueTypes.qml"));
+ VERIFY_ERRORS(0);
+
+ QString message = QLatin1String("QML MyTypeObject (") + component.url().toString() +
+ QLatin1String(":2:1) Binding loop detected for property \"rectProperty.width\"");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+
+ MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
+ QVERIFY(object != 0);
+
+
+ QCOMPARE(object->rectProperty(), QRect(10, 11, 12, 13));
+ QCOMPARE(object->rectProperty2(), QRect(10, 11, 12, 13));
+ QCOMPARE(object->intProperty(), 10);
+ object->doAction();
+ QCOMPARE(object->rectProperty(), QRect(12, 11, 14, 13));
+ QCOMPARE(object->rectProperty2(), QRect(12, 11, 14, 13));
+ QCOMPARE(object->intProperty(), 12);
+
+ // ###
+#if 0
+ QmlMetaProperty p = QmlMetaProperty::createProperty(object, "rectProperty.x");
+ QCOMPARE(p.read(), QVariant(12));
+ p.write(13);
+ QCOMPARE(p.read(), QVariant(13));
+
+ quint32 r = QmlMetaPropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex());
+ QmlMetaProperty p2;
+ QmlMetaPropertyPrivate::restore(p2, r, object);
+ QCOMPARE(p2.read(), QVariant(13));
+#endif
+}
+
+void tst_qmllanguage::cppnamespace()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("cppnamespace.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("cppnamespace.2.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ delete object;
+ }
+}
+
+void tst_qmllanguage::aliasProperties()
+{
+ // Simple "int" alias
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.1.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ // Read through alias
+ QCOMPARE(object->property("valueAlias").toInt(), 10);
+ object->setProperty("value", QVariant(13));
+ QCOMPARE(object->property("valueAlias").toInt(), 13);
+
+ // Write throught alias
+ object->setProperty("valueAlias", QVariant(19));
+ QCOMPARE(object->property("valueAlias").toInt(), 19);
+ QCOMPARE(object->property("value").toInt(), 19);
+
+ delete object;
+ }
+
+ // Complex object alias
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.2.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ // Read through alias
+ MyQmlObject *v =
+ qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
+ QVERIFY(v != 0);
+ QCOMPARE(v->value(), 10);
+
+ // Write through alias
+ MyQmlObject *v2 = new MyQmlObject();
+ v2->setParent(object);
+ object->setProperty("aliasObject", qVariantFromValue(v2));
+ MyQmlObject *v3 =
+ qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
+ QVERIFY(v3 != 0);
+ QCOMPARE(v3, v2);
+
+ delete object;
+ }
+
+ // Nested aliases
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.3.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("value").toInt(), 1892);
+ QCOMPARE(object->property("value2").toInt(), 1892);
+
+ object->setProperty("value", QVariant(1313));
+ QCOMPARE(object->property("value").toInt(), 1313);
+ QCOMPARE(object->property("value2").toInt(), 1313);
+
+ object->setProperty("value2", QVariant(8080));
+ QCOMPARE(object->property("value").toInt(), 8080);
+ QCOMPARE(object->property("value2").toInt(), 8080);
+
+ delete object;
+ }
+
+ // Enum aliases
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.4.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("enumAlias").toInt(), 1);
+
+ delete object;
+ }
+
+ // Id aliases
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.5.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVariant v = object->property("otherAlias");
+ QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
+ MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
+ QCOMPARE(o->value(), 10);
+
+ delete o;
+
+ v = object->property("otherAlias");
+ QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
+ o = qvariant_cast<MyQmlObject*>(v);
+ QVERIFY(o == 0);
+
+ delete object;
+ }
+
+ // Nested aliases - this used to cause a crash
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.6.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("a").toInt(), 1923);
+ }
+
+ // Ptr Alias Cleanup - check that aliases to ptr types return 0
+ // if the object aliased to is removed
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.7.qml"));
+ VERIFY_ERRORS(0);
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QObject *object1 = qvariant_cast<QObject *>(object->property("object"));
+ QVERIFY(object1 != 0);
+ QObject *object2 = qvariant_cast<QObject *>(object1->property("object"));
+ QVERIFY(object2 != 0);
+
+ QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
+ QVERIFY(alias == object2);
+
+ delete object1;
+
+ QObject *alias2 = object; // "Random" start value
+ int status = -1;
+ void *a[] = { &alias2, 0, &status };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty,
+ object->metaObject()->indexOfProperty("aliasedObject"), a);
+ QVERIFY(alias2 == 0);
+ }
+
+ // Simple composite type
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.8.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("value").toInt(), 10);
+
+ delete object;
+ }
+
+ // Complex composite type
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.9.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("value").toInt(), 10);
+
+ delete object;
+ }
+}
+
+// Test that the root element in a composite type can be a Component
+void tst_qmllanguage::componentCompositeType()
+{
+ QmlComponent component(&engine, TEST_FILE("componentCompositeType.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+class TestType : public QObject {
+ Q_OBJECT
+public:
+ TestType(QObject *p=0) : QObject(p) {}
+};
+
+class TestType2 : public QObject {
+ Q_OBJECT
+public:
+ TestType2(QObject *p=0) : QObject(p) {}
+};
+
+void tst_qmllanguage::i18n_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("stringProperty");
+ QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245 (5 accented 'a' letters)");
+ QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 10");
+ QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 15");
+ QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 20");
+ QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 30");
+ QTest::newRow("i18nNameSpace") << "i18nNameSpace.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 40");
+}
+
+void tst_qmllanguage::i18n()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, stringProperty);
+ QmlComponent component(&engine, TEST_FILE(file));
+ VERIFY_ERRORS(0);
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->stringProperty(), stringProperty);
+
+ delete object;
+}
+
+// Check that the Component::onCompleted attached property works
+void tst_qmllanguage::onCompleted()
+{
+ QmlComponent component(&engine, TEST_FILE("onCompleted.qml"));
+ VERIFY_ERRORS(0);
+ QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
+ QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
+ QTest::ignoreMessage(QtDebugMsg, "Completed 10 11");
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+// Check that assignments to QmlScriptString properties work
+void tst_qmllanguage::scriptString()
+{
+ QmlComponent component(&engine, TEST_FILE("scriptString.qml"));
+ VERIFY_ERRORS(0);
+
+ MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->scriptProperty().script(), QString("foo + bar"));
+ QCOMPARE(object->scriptProperty().scopeObject(), object);
+ QCOMPARE(object->scriptProperty().context(), qmlContext(object));
+
+ QVERIFY(object->grouped() != 0);
+ QCOMPARE(object->grouped()->script().script(), QString("console.log(1921)"));
+ QCOMPARE(object->grouped()->script().scopeObject(), object);
+ QCOMPARE(object->grouped()->script().context(), qmlContext(object));
+}
+
+// Check that default property assignments are correctly spliced into explicit
+// property assignments
+void tst_qmllanguage::defaultPropertyListOrder()
+{
+ QmlComponent component(&engine, TEST_FILE("defaultPropertyListOrder.qml"));
+ VERIFY_ERRORS(0);
+
+ MyContainer *container = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->children()->count(), 6);
+ QCOMPARE(container->children()->at(0)->property("index"), QVariant(0));
+ QCOMPARE(container->children()->at(1)->property("index"), QVariant(1));
+ QCOMPARE(container->children()->at(2)->property("index"), QVariant(2));
+ QCOMPARE(container->children()->at(3)->property("index"), QVariant(3));
+ QCOMPARE(container->children()->at(4)->property("index"), QVariant(4));
+ QCOMPARE(container->children()->at(5)->property("index"), QVariant(5));
+}
+
+void tst_qmllanguage::declaredPropertyValues()
+{
+ QmlComponent component(&engine, TEST_FILE("declaredPropertyValues.qml"));
+ QEXPECT_FAIL("", "QTBUG-7860", Abort);
+ VERIFY_ERRORS(0);
+}
+
+// Check that first child of qml is of given type. Empty type insists on error.
+void tst_qmllanguage::testType(const QString& qml, const QString& type)
+{
+ QmlComponent component(&engine);
+ component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports
+
+ QTRY_VERIFY(!component.isLoading());
+
+ if (type.isEmpty()) {
+ QVERIFY(component.isError());
+ } else {
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(QString(object->metaObject()->className()), type);
+ }
+}
+
+QML_DECLARE_TYPE(TestType)
+QML_DECLARE_TYPE(TestType2)
+
+QML_DEFINE_TYPE(com.nokia.Test, 0, 0, TestTP, TestType)
+QML_DEFINE_TYPE(com.nokia.Test, 1, 0, Test, TestType)
+QML_DEFINE_TYPE(com.nokia.Test, 1, 5, Test, TestType)
+QML_DEFINE_TYPE(com.nokia.Test, 1, 8, Test, TestType2)
+QML_DEFINE_TYPE(com.nokia.Test, 1, 9, OldTest, TestType)
+QML_DEFINE_TYPE(com.nokia.Test, 1, 12, Test, TestType2)
+
+// Import tests (QT-558)
+
+void tst_qmllanguage::importsBuiltin_data()
+{
+ // QT-610
+
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("type");
+
+ // import built-ins
+ QTest::newRow("missing import")
+ << "Test {}"
+ << "";
+ QTest::newRow("not in version 0.0")
+ << "import com.nokia.Test 0.0\n"
+ "Test {}"
+ << "";
+ QTest::newRow("in version 0.0")
+ << "import com.nokia.Test 0.0\n"
+ "TestTP {}"
+ << "TestType";
+ QTest::newRow("qualified in version 0.0")
+ << "import com.nokia.Test 0.0 as T\n"
+ "T.TestTP {}"
+ << "TestType";
+ QTest::newRow("in version 1.0")
+ << "import com.nokia.Test 1.0\n"
+ "Test {}"
+ << "TestType";
+ QTest::newRow("qualified wrong")
+ << "import com.nokia.Test 1.0 as T\n" // QT-610
+ "Test {}"
+ << "";
+ QTest::newRow("qualified right")
+ << "import com.nokia.Test 1.0 as T\n"
+ "T.Test {}"
+ << "TestType";
+ QTest::newRow("qualified right but not in version 0.0")
+ << "import com.nokia.Test 0.0 as T\n"
+ "T.Test {}"
+ << "";
+ QTest::newRow("in version 1.1")
+ << "import com.nokia.Test 1.1\n"
+ "Test {}"
+ << "TestType";
+ QTest::newRow("in version 1.3")
+ << "import com.nokia.Test 1.3\n"
+ "Test {}"
+ << "TestType";
+ QTest::newRow("in version 1.5")
+ << "import com.nokia.Test 1.5\n"
+ "Test {}"
+ << "TestType";
+ QTest::newRow("changed in version 1.8")
+ << "import com.nokia.Test 1.8\n"
+ "Test {}"
+ << "TestType2";
+ QTest::newRow("in version 1.12")
+ << "import com.nokia.Test 1.12\n"
+ "Test {}"
+ << "TestType2";
+ QTest::newRow("old in version 1.9")
+ << "import com.nokia.Test 1.9\n"
+ "OldTest {}"
+ << "TestType";
+ QTest::newRow("old in version 1.11")
+ << "import com.nokia.Test 1.11\n"
+ "OldTest {}"
+ << "TestType";
+ QTest::newRow("multiversion 1")
+ << "import com.nokia.Test 1.11\n"
+ "import com.nokia.Test 1.12\n"
+ "Test {}"
+ << "TestType2";
+ QTest::newRow("multiversion 2")
+ << "import com.nokia.Test 1.11\n"
+ "import com.nokia.Test 1.12\n"
+ "OldTest {}"
+ << "TestType";
+ QTest::newRow("qualified multiversion 3")
+ << "import com.nokia.Test 1.0 as T0\n"
+ "import com.nokia.Test 1.8 as T8\n"
+ "T0.Test {}"
+ << "TestType";
+ QTest::newRow("qualified multiversion 4")
+ << "import com.nokia.Test 1.0 as T0\n"
+ "import com.nokia.Test 1.8 as T8\n"
+ "T8.Test {}"
+ << "TestType2";
+}
+
+void tst_qmllanguage::importsBuiltin()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, type);
+ testType(qml,type);
+}
+
+void tst_qmllanguage::importsLocal_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("type");
+
+ // import locals
+ QTest::newRow("local import")
+ << "import \"subdir\"\n" // QT-613
+ "Test {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("local import second")
+ << "import Qt 4.6\nimport \"subdir\"\n"
+ "Test {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("local import subsubdir")
+ << "import Qt 4.6\nimport \"subdir/subsubdir\"\n"
+ "SubTest {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("local import QTBUG-7721 A")
+ << "subdir.Test {}" // no longer allowed (QTBUG-7721)
+ << "";
+ QTest::newRow("local import QTBUG-7721 B")
+ << "import \"subdir\" as X\n"
+ "X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721)
+ << "";
+ QTest::newRow("local import as")
+ << "import \"subdir\" as T\n"
+ "T.Test {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("wrong local import as")
+ << "import \"subdir\" as T\n"
+ "Test {}"
+ << "";
+ QTest::newRow("library precedence over local import")
+ << "import \"subdir\"\n"
+ "import com.nokia.Test 1.0\n"
+ "Test {}"
+ << "TestType";
+}
+
+void tst_qmllanguage::importsLocal()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, type);
+ testType(qml,type);
+}
+
+void tst_qmllanguage::importsRemote_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("type");
+
+ QString serverdir = "http://127.0.0.1:14445/qtest/declarative/qmllanguage";
+
+ QTest::newRow("remote import") << "import \""+serverdir+"\"\nTest {}" << "QmlGraphicsRectangle";
+ QTest::newRow("remote import with subdir") << "import \""+serverdir+"\"\nTestSubDir {}" << "QmlGraphicsText";
+ QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QmlGraphicsImage";
+}
+
+#include "testhttpserver.h"
+
+void tst_qmllanguage::importsRemote()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, type);
+
+ TestHTTPServer server(14445);
+ server.serveDirectory(SRCDIR);
+
+ testType(qml,type);
+}
+
+void tst_qmllanguage::importsInstalled_data()
+{
+ // QT-610
+
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("type");
+
+ // import installed
+ QTest::newRow("installed import 0")
+ << "import com.nokia.installedtest 0.0\n"
+ "InstalledTestTP {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("installed import 0 as TP")
+ << "import com.nokia.installedtest 0.0 as TP\n"
+ "TP.InstalledTestTP {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("installed import 1")
+ << "import com.nokia.installedtest 1.0\n"
+ "InstalledTest {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("installed import 2")
+ << "import com.nokia.installedtest 1.3\n"
+ "InstalledTest {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("installed import 3")
+ << "import com.nokia.installedtest 1.4\n"
+ "InstalledTest {}"
+ << "QmlGraphicsText";
+ QTest::newRow("installed import 4")
+ << "import com.nokia.installedtest 1.10\n"
+ "InstalledTest {}"
+ << "QmlGraphicsText";
+ QTest::newRow("installed import visibility") // QT-614
+ << "import com.nokia.installedtest 1.4\n"
+ "PrivateType {}"
+ << "";
+}
+
+void tst_qmllanguage::importsInstalled()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, type);
+ testType(qml,type);
+}
+
+
+void tst_qmllanguage::importsOrder_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("type");
+
+ QTest::newRow("installed import overrides 1") <<
+ "import com.nokia.installedtest 1.0\n"
+ "import com.nokia.installedtest 1.4\n"
+ "InstalledTest {}"
+ << "QmlGraphicsText";
+ QTest::newRow("installed import overrides 2") <<
+ "import com.nokia.installedtest 1.4\n"
+ "import com.nokia.installedtest 1.0\n"
+ "InstalledTest {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("installed import re-overrides 1") <<
+ "import com.nokia.installedtest 1.4\n"
+ "import com.nokia.installedtest 1.0\n"
+ "import com.nokia.installedtest 1.4\n"
+ "InstalledTest {}"
+ << "QmlGraphicsText";
+ QTest::newRow("installed import re-overrides 2") <<
+ "import com.nokia.installedtest 1.4\n"
+ "import com.nokia.installedtest 1.0\n"
+ "import com.nokia.installedtest 1.4\n"
+ "import com.nokia.installedtest 1.0\n"
+ "InstalledTest {}"
+ << "QmlGraphicsRectangle";
+
+ QTest::newRow("installed import versus builtin 1") <<
+ "import com.nokia.installedtest 1.5\n"
+ "import Qt 4.6\n"
+ "Rectangle {}"
+ << "QmlGraphicsRectangle";
+ QTest::newRow("installed import versus builtin 2") <<
+ "import Qt 4.6\n"
+ "import com.nokia.installedtest 1.5\n"
+ "Rectangle {}"
+ << "QmlGraphicsText";
+ QTest::newRow("namespaces cannot be overridden by types 1") <<
+ "import Qt 4.6 as Rectangle\n"
+ "import com.nokia.installedtest 1.5\n"
+ "Rectangle {}"
+ << "";
+ QTest::newRow("namespaces cannot be overridden by types 2") <<
+ "import Qt 4.6 as Rectangle\n"
+ "import com.nokia.installedtest 1.5\n"
+ "Rectangle.Image {}"
+ << "QmlGraphicsImage";
+}
+
+void tst_qmllanguage::importsOrder()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, type);
+ testType(qml,type);
+}
+
+void tst_qmllanguage::qmlAttachedPropertiesObjectMethod()
+{
+ QObject object;
+
+ QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, false), (QObject *)0);
+ QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, true), (QObject *)0);
+
+ {
+ QmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(object, false), (QObject *)0);
+ QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, false) != 0);
+ QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
+ }
+}
+
+void tst_qmllanguage::crash1()
+{
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6\nComponent {}", QUrl());
+}
+
+void tst_qmllanguage::crash2()
+{
+ QmlComponent component(&engine, TEST_FILE("crash2.qml"));
+}
+
+QTEST_MAIN(tst_qmllanguage)
+
+#include "tst_qmllanguage.moc"
diff --git a/tests/auto/declarative/qmllist/qmllist.pro b/tests/auto/declarative/qmllist/qmllist.pro
new file mode 100644
index 0000000..b2145ed
--- /dev/null
+++ b/tests/auto/declarative/qmllist/qmllist.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmllist.cpp
diff --git a/tests/auto/declarative/qmllist/tst_qmllist.cpp b/tests/auto/declarative/qmllist/tst_qmllist.cpp
new file mode 100644
index 0000000..c59ff1d
--- /dev/null
+++ b/tests/auto/declarative/qmllist/tst_qmllist.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlprivate.h>
+
+class tst_QmlList : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlList() {}
+
+private slots:
+ void interface();
+};
+
+void tst_QmlList::interface()
+{
+ QmlConcreteList<QObject*> list;
+ QObject *obj = new QObject;
+ obj->setObjectName("foo");
+ list.append(obj);
+ QVERIFY(list.count() == 1);
+ QCOMPARE(list.at(0), obj);
+
+ QmlPrivate::ListInterface *li = (QmlPrivate::ListInterface*)&list;
+
+ void *ptr[1];
+ li->at(0, ptr);
+ QVERIFY(li->count() == 1);
+ QCOMPARE(ptr[0], obj);
+
+ li->removeAt(0);
+ QVERIFY(li->count() == 0);
+ QVERIFY(list.count() == 0);
+}
+
+QTEST_MAIN(tst_QmlList)
+
+#include "tst_qmllist.moc"
diff --git a/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro b/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro
new file mode 100644
index 0000000..ce2915e
--- /dev/null
+++ b/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmllistaccessor.cpp
diff --git a/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp b/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp
new file mode 100644
index 0000000..ddf9a07
--- /dev/null
+++ b/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp
@@ -0,0 +1,452 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qml.h>
+#include <private/qmllistaccessor_p.h>
+#include <QDebug>
+
+class tst_QmlListAccessor : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlListAccessor() {}
+
+private slots:
+ void invalid();
+ void qmllist();
+ void qlist();
+ void qstringlist();
+ void qvariantlist();
+ void qobject();
+ void instance();
+ void integer();
+};
+
+void tst_QmlListAccessor::invalid()
+{
+ QmlListAccessor accessor;
+
+ QCOMPARE(accessor.list(), QVariant());
+ QVERIFY(!accessor.isValid());
+ QCOMPARE(accessor.type(), QmlListAccessor::Invalid);
+
+ QCOMPARE(accessor.count(), 0);
+ QVERIFY(!accessor.append(QVariant(10)));
+ QVERIFY(!accessor.insert(0, QVariant(10)));
+ QVERIFY(!accessor.removeAt(0));
+ QVERIFY(!accessor.clear());
+
+ accessor.setList(QVariant());
+
+ QCOMPARE(accessor.list(), QVariant());
+ QVERIFY(!accessor.isValid());
+ QCOMPARE(accessor.type(), QmlListAccessor::Invalid);
+
+ QCOMPARE(accessor.count(), 0);
+ QVERIFY(!accessor.append(QVariant(10)));
+ QVERIFY(!accessor.insert(0, QVariant(10)));
+ QVERIFY(!accessor.removeAt(0));
+ QVERIFY(!accessor.clear());
+}
+
+void tst_QmlListAccessor::qmllist()
+{
+ QmlConcreteList<QObject*> list;
+ QObject *obj = new QObject(this);
+ QObject *obj2 = new QObject(this);
+ QObject *obj3 = new QObject(this);
+
+ list.append(obj);
+ QVERIFY(list.count() == 1);
+ QCOMPARE(list.at(0), obj);
+
+ QmlListAccessor accessor;
+ accessor.setList(qVariantFromValue((QmlList<QObject*>*)&list));
+ QCOMPARE(accessor.list(), qVariantFromValue((QmlList<QObject*>*)&list));
+
+ // type
+ QCOMPARE(accessor.type(), QmlListAccessor::QmlList);
+
+ // isValid
+ QVERIFY(accessor.isValid());
+
+ // count
+ QCOMPARE(accessor.count(), 1);
+
+ // at
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(0)), obj);
+
+ // append
+ accessor.append(qVariantFromValue(obj2));
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 2);
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(1)), obj2);
+ QCOMPARE(list.count(), 2);
+ QCOMPARE(list.at(0), obj);
+ QCOMPARE(list.at(1), obj2);
+
+ // insert
+ accessor.insert(1, qVariantFromValue(obj3));
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 3);
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(1)), obj3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(list.at(0), obj);
+ QCOMPARE(list.at(1), obj3);
+ QCOMPARE(list.at(2), obj2);
+
+ // removeAt
+ accessor.removeAt(1);
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 2);
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(1)), obj2);
+ QCOMPARE(list.count(), 2);
+ QCOMPARE(list.at(0), obj);
+ QCOMPARE(list.at(1), obj2);
+
+ // clear
+ accessor.clear();
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 0);
+ QCOMPARE(list.count(), 0);
+}
+
+void tst_QmlListAccessor::qlist()
+{
+ QList<QObject*> list;
+ QObject *obj = new QObject(this);
+ QObject *obj2 = new QObject(this);
+ QObject *obj3 = new QObject(this);
+
+ list.append(obj);
+ QVERIFY(list.count() == 1);
+ QCOMPARE(list.at(0), obj);
+
+ QmlListAccessor accessor;
+ accessor.setList(qVariantFromValue((QList<QObject*>*)&list));
+ QCOMPARE(accessor.list(), qVariantFromValue((QList<QObject*>*)&list));
+
+ // type
+ QCOMPARE(accessor.type(), QmlListAccessor::QListPtr);
+
+ // isValid
+ QVERIFY(accessor.isValid());
+
+ // count
+ QCOMPARE(accessor.count(), 1);
+
+ // at
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(0)), obj);
+
+ // append
+ accessor.append(qVariantFromValue(obj2));
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 2);
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(1)), obj2);
+ QCOMPARE(list.count(), 2);
+ QCOMPARE(list.at(0), obj);
+ QCOMPARE(list.at(1), obj2);
+
+ // insert
+ accessor.insert(1, qVariantFromValue(obj3));
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 3);
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(1)), obj3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(list.at(0), obj);
+ QCOMPARE(list.at(1), obj3);
+ QCOMPARE(list.at(2), obj2);
+
+ // removeAt
+ accessor.removeAt(1);
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 2);
+ QCOMPARE(qvariant_cast<QObject*>(accessor.at(1)), obj2);
+ QCOMPARE(list.count(), 2);
+ QCOMPARE(list.at(0), obj);
+ QCOMPARE(list.at(1), obj2);
+
+ // clear
+ accessor.clear();
+ QVERIFY(accessor.isValid());
+ QCOMPARE(accessor.count(), 0);
+ QCOMPARE(list.count(), 0);
+}
+
+void tst_QmlListAccessor::qstringlist()
+{
+ QStringList list;
+ list.append(QLatin1String("Item1"));
+ list.append(QLatin1String("Item2"));
+ QVERIFY(list.count() == 2);
+
+ QmlListAccessor accessor;
+ accessor.setList(list);
+
+ // type
+ QCOMPARE(accessor.type(), QmlListAccessor::StringList);
+
+ // isValid
+ QVERIFY(accessor.isValid());
+
+ // count
+ QVERIFY(accessor.count() == 2);
+
+ // at
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // append
+ QVERIFY(!accessor.append(QVariant("Item3")));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // insert
+ QVERIFY(!accessor.insert(1, QVariant("MiddleItem")));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // removeAt
+ QVERIFY(!accessor.removeAt(1));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // clear
+ QVERIFY(!accessor.clear());
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+}
+
+void tst_QmlListAccessor::qvariantlist()
+{
+ QVariantList list;
+ list.append(QLatin1String("Item1"));
+ list.append(QLatin1String("Item2"));
+ QVERIFY(list.count() == 2);
+
+ QmlListAccessor accessor;
+ accessor.setList(list);
+
+ // type
+ QCOMPARE(accessor.type(), QmlListAccessor::VariantList);
+
+ // isValid
+ QVERIFY(accessor.isValid());
+
+ // count
+ QVERIFY(accessor.count() == 2);
+
+ // at
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // append
+ QVERIFY(!accessor.append(QVariant("Item3")));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // insert
+ QVERIFY(!accessor.insert(1, QVariant("MiddleItem")));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // removeAt
+ QVERIFY(!accessor.removeAt(1));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+
+ // clear
+ QVERIFY(!accessor.clear());
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 2);
+ QCOMPARE(qvariant_cast<QString>(accessor.at(0)), QLatin1String("Item1"));
+ QCOMPARE(qvariant_cast<QString>(accessor.at(1)), QLatin1String("Item2"));
+}
+
+void tst_QmlListAccessor::qobject()
+{
+ QObject *obj = new QObject(this);
+
+ QmlListAccessor accessor;
+ accessor.setList(qVariantFromValue(obj));
+
+ // type
+ QCOMPARE(accessor.type(), QmlListAccessor::Instance);
+
+ // isValid
+ QVERIFY(accessor.isValid());
+
+ // count
+ QVERIFY(accessor.count() == 1);
+
+ // at
+ QCOMPARE(accessor.at(0), qVariantFromValue(obj));
+
+ // append
+ QVERIFY(!accessor.append(qVariantFromValue((QObject *)0)));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(obj));
+
+ // insert
+ QVERIFY(!accessor.insert(0, qVariantFromValue((QObject *)0)));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(obj));
+
+ // removeAt
+ QVERIFY(!accessor.removeAt(0));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(obj));
+
+ // clear
+ QVERIFY(!accessor.clear());
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(obj));
+}
+
+void tst_QmlListAccessor::instance()
+{
+ QRect r;
+
+ QmlListAccessor accessor;
+ accessor.setList(r);
+
+ // type
+ QCOMPARE(accessor.type(), QmlListAccessor::Instance);
+
+ // isValid
+ QVERIFY(accessor.isValid());
+
+ // count
+ QVERIFY(accessor.count() == 1);
+
+ // at
+ QCOMPARE(accessor.at(0), qVariantFromValue(r));
+
+ // append
+ QVERIFY(!accessor.append(qVariantFromValue(r)));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(r));
+
+ // insert
+ QVERIFY(!accessor.insert(0, qVariantFromValue(r)));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(r));
+
+ // removeAt
+ QVERIFY(!accessor.removeAt(0));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(r));
+
+ // clear
+ QVERIFY(!accessor.clear());
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+ QCOMPARE(accessor.at(0), qVariantFromValue(r));
+}
+
+void tst_QmlListAccessor::integer()
+{
+ int r = 13;
+
+ QmlListAccessor accessor;
+ accessor.setList(r);
+
+ // type
+ QCOMPARE(accessor.type(), QmlListAccessor::Integer);
+
+ // isValid
+ QVERIFY(accessor.isValid());
+
+ // count
+ QVERIFY(accessor.count() == 13);
+
+ // at
+ QCOMPARE(accessor.at(4), qVariantFromValue(4));
+
+ // append
+ QVERIFY(!accessor.append(qVariantFromValue(r)));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 13);
+ QCOMPARE(accessor.at(4), qVariantFromValue(4));
+
+ // insert
+ QVERIFY(!accessor.insert(0, qVariantFromValue(r)));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 13);
+ QCOMPARE(accessor.at(4), qVariantFromValue(4));
+
+ // removeAt
+ QVERIFY(!accessor.removeAt(0));
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 13);
+ QCOMPARE(accessor.at(4), qVariantFromValue(4));
+
+ // clear
+ QVERIFY(!accessor.clear());
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 13);
+ QCOMPARE(accessor.at(4), qVariantFromValue(4));
+}
+
+QTEST_MAIN(tst_QmlListAccessor)
+
+#include "tst_qmllistaccessor.moc"
diff --git a/tests/auto/declarative/qmllistmodel/qmllistmodel.pro b/tests/auto/declarative/qmllistmodel/qmllistmodel.pro
new file mode 100644
index 0000000..60b0c4b
--- /dev/null
+++ b/tests/auto/declarative/qmllistmodel/qmllistmodel.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+QT += script
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmllistmodel.cpp
diff --git a/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp b/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp
new file mode 100644
index 0000000..9d072dd
--- /dev/null
+++ b/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/private/qmllistmodel_p.h>
+#include <QtDeclarative/private/qmlexpression_p.h>
+#include <QmlComponent>
+#include <QDebug>
+
+class tst_QmlListModel : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlListModel() {}
+
+private slots:
+ void static_i18n();
+ void static_nestedElements();
+ void static_nestedElements_data();
+ void dynamic_data();
+ void dynamic();
+ void error_data();
+ void error();
+};
+
+void tst_QmlListModel::static_i18n()
+{
+ QString expect = QString::fromUtf8("na\303\257ve");
+ QString componentStr = "import Qt 4.6\nListModel { ListElement { prop1: \""+expect+"\" } }";
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(componentStr.toUtf8(), QUrl::fromLocalFile(""));
+ QmlListModel *obj = qobject_cast<QmlListModel*>(component.create());
+ QVERIFY(obj != 0);
+ QString prop = obj->get(0).property(QLatin1String("prop1")).toString();
+ QCOMPARE(prop,expect);
+ delete obj;
+}
+
+void tst_QmlListModel::static_nestedElements()
+{
+ QFETCH(int, elementCount);
+
+ QStringList elements;
+ for (int i=0; i<elementCount; i++)
+ elements.append("ListElement { a: 1; b: 2 }");
+ QString elementsStr = elements.join(",\n") + "\n";
+
+ QString componentStr =
+ "import Qt 4.6\n"
+ "ListModel {\n"
+ " ListElement {\n"
+ " attributes: [\n";
+ componentStr += elementsStr.toUtf8().constData();
+ componentStr +=
+ " ]\n"
+ " }\n"
+ "}";
+
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(componentStr.toUtf8(), QUrl::fromLocalFile(""));
+
+ QmlListModel *obj = qobject_cast<QmlListModel*>(component.create());
+ QVERIFY(obj != 0);
+
+ QScriptValue prop = obj->get(0).property(QLatin1String("attributes")).property(QLatin1String("count"));
+ QVERIFY(prop.isNumber());
+ QCOMPARE(prop.toInt32(), qint32(elementCount));
+
+ delete obj;
+}
+
+void tst_QmlListModel::static_nestedElements_data()
+{
+ QTest::addColumn<int>("elementCount");
+
+ QTest::newRow("0 items") << 0;
+ QTest::newRow("1 item") << 1;
+ QTest::newRow("2 items") << 2;
+ QTest::newRow("many items") << 5;
+}
+
+void tst_QmlListModel::dynamic_data()
+{
+ QTest::addColumn<QString>("script");
+ QTest::addColumn<int>("result");
+ QTest::addColumn<QString>("warning");
+
+ // Simple flat model
+
+ QTest::newRow("count") << "count" << 0 << "";
+
+ QTest::newRow("get1") << "{get(0)}" << 0 << "QML ListModel (unknown location) get: index 0 out of range";
+ QTest::newRow("get2") << "{get(-1)}" << 0 << "QML ListModel (unknown location) get: index -1 out of range";
+
+ QTest::newRow("append1") << "{append({'foo':123});count}" << 1 << "";
+ QTest::newRow("append2") << "{append({'foo':123,'bar':456});count}" << 1 << "";
+ QTest::newRow("append3a") << "{append({'foo':123});append({'foo':456});get(0).foo}" << 123 << "";
+ QTest::newRow("append3b") << "{append({'foo':123});append({'foo':456});get(1).foo}" << 456 << "";
+ QTest::newRow("append4a") << "{append(123)}" << 0 << "QML ListModel (unknown location) append: value is not an object";
+ QTest::newRow("append4b") << "{append([1,2,3])}" << 0 << "QML ListModel (unknown location) append: value is not an object";
+
+ QTest::newRow("clear1") << "{append({'foo':456});clear();count}" << 0 << "";
+ QTest::newRow("clear2") << "{append({'foo':123});append({'foo':456});clear();count}" << 0 << "";
+ QTest::newRow("clear2") << "{append({'foo':123});clear();get(0).foo}" << 0 << "QML ListModel (unknown location) get: index 0 out of range";
+
+ QTest::newRow("remove1") << "{append({'foo':123});remove(0);count}" << 0 << "";
+ QTest::newRow("remove2a") << "{append({'foo':123});append({'foo':456});remove(0);count}" << 1 << "";
+ QTest::newRow("remove2b") << "{append({'foo':123});append({'foo':456});remove(0);get(0).foo}" << 456 << "";
+ QTest::newRow("remove2c") << "{append({'foo':123});append({'foo':456});remove(1);get(0).foo}" << 123 << "";
+ QTest::newRow("remove3") << "{append({'foo':123});remove(0);get(0).foo}" << 0 << "QML ListModel (unknown location) get: index 0 out of range";
+ QTest::newRow("remove3a") << "{append({'foo':123});remove(-1)}" << 0 << "QML ListModel (unknown location) remove: index -1 out of range";
+ QTest::newRow("remove4a") << "{remove(0)}" << 0 << "QML ListModel (unknown location) remove: index 0 out of range";
+ QTest::newRow("remove4b") << "{append({'foo':123});remove(0);remove(0)}" << 0 << "QML ListModel (unknown location) remove: index 0 out of range";
+ QTest::newRow("remove4c") << "{append({'foo':123});remove(1)}" << 0 << "QML ListModel (unknown location) remove: index 1 out of range";
+
+ QTest::newRow("insert1") << "{insert(0,{'foo':123});count}" << 1 << "";
+ QTest::newRow("insert2") << "{insert(1,{'foo':123});count}" << 0 << "QML ListModel (unknown location) insert: index 1 out of range";
+ QTest::newRow("insert3a") << "{append({'foo':123});insert(1,{'foo':456});count}" << 2 << "";
+ QTest::newRow("insert3b") << "{append({'foo':123});insert(1,{'foo':456});get(0).foo}" << 123 << "";
+ QTest::newRow("insert3c") << "{append({'foo':123});insert(1,{'foo':456});get(1).foo}" << 456 << "";
+ QTest::newRow("insert3d") << "{append({'foo':123});insert(0,{'foo':456});get(0).foo}" << 456 << "";
+ QTest::newRow("insert3e") << "{append({'foo':123});insert(0,{'foo':456});get(1).foo}" << 123 << "";
+ QTest::newRow("insert4") << "{append({'foo':123});insert(-1,{'foo':456})}" << 0 << "QML ListModel (unknown location) insert: index -1 out of range";
+ QTest::newRow("insert5a") << "{insert(0,123)}" << 0 << "QML ListModel (unknown location) insert: value is not an object";
+ QTest::newRow("insert5b") << "{insert(0,[1,2,3])}" << 0 << "QML ListModel (unknown location) insert: value is not an object";
+
+ QTest::newRow("set1") << "{append({'foo':123});set(0,{'foo':456});count}" << 1 << "";
+ QTest::newRow("set2") << "{append({'foo':123});set(0,{'foo':456});get(0).foo}" << 456 << "";
+ QTest::newRow("set3a") << "{append({'foo':123,'bar':456});set(0,{'foo':999});get(0).foo}" << 999 << "";
+ QTest::newRow("set3b") << "{append({'foo':123,'bar':456});set(0,{'foo':999});get(0).bar}" << 456 << "";
+ QTest::newRow("set4a") << "{set(0,{'foo':456})}" << 0 << "QML ListModel (unknown location) set: index 0 out of range";
+ QTest::newRow("set4c") << "{set(-1,{'foo':456})}" << 0 << "QML ListModel (unknown location) set: index -1 out of range";
+ QTest::newRow("set5a") << "{append({'foo':123,'bar':456});set(0,123)}" << 0 << "QML ListModel (unknown location) set: value is not an object";
+ QTest::newRow("set5b") << "{append({'foo':123,'bar':456});set(0,[1,2,3])}" << 0 << "QML ListModel (unknown location) set: value is not an object";
+ QTest::newRow("set6") << "{append({'foo':123});set(1,{'foo':456});count}" << 2 << "";
+
+ QTest::newRow("setprop1") << "{append({'foo':123});setProperty(0,'foo',456);count}" << 1 << "";
+ QTest::newRow("setprop2") << "{append({'foo':123});setProperty(0,'foo',456);get(0).foo}" << 456 << "";
+ QTest::newRow("setprop3a") << "{append({'foo':123,'bar':456});setProperty(0,'foo',999);get(0).foo}" << 999 << "";
+ QTest::newRow("setprop3b") << "{append({'foo':123,'bar':456});setProperty(0,'foo',999);get(0).bar}" << 456 << "";
+ QTest::newRow("setprop4a") << "{setProperty(0,'foo',456)}" << 0 << "QML ListModel (unknown location) set: index 0 out of range";
+ QTest::newRow("setprop4b") << "{setProperty(-1,'foo',456)}" << 0 << "QML ListModel (unknown location) set: index -1 out of range";
+ QTest::newRow("setprop4c") << "{append({'foo':123,'bar':456});setProperty(1,'foo',456)}" << 0 << "QML ListModel (unknown location) set: index 1 out of range";
+ QTest::newRow("setprop5") << "{append({'foo':123,'bar':456});append({'foo':111});setProperty(1,'bar',222);get(1).bar}" << 222 << "";
+
+ QTest::newRow("move1a") << "{append({'foo':123});append({'foo':456});move(0,1,1);count}" << 2 << "";
+ QTest::newRow("move1b") << "{append({'foo':123});append({'foo':456});move(0,1,1);get(0).foo}" << 456 << "";
+ QTest::newRow("move1c") << "{append({'foo':123});append({'foo':456});move(0,1,1);get(1).foo}" << 123 << "";
+ QTest::newRow("move1d") << "{append({'foo':123});append({'foo':456});move(1,0,1);get(0).foo}" << 456 << "";
+ QTest::newRow("move1e") << "{append({'foo':123});append({'foo':456});move(1,0,1);get(1).foo}" << 123 << "";
+ QTest::newRow("move2a") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);count}" << 3 << "";
+ QTest::newRow("move2b") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);get(0).foo}" << 789 << "";
+ QTest::newRow("move2c") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);get(1).foo}" << 123 << "";
+ QTest::newRow("move2d") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);get(2).foo}" << 456 << "";
+ QTest::newRow("move3a") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(1,0,3)}" << 0 << "QML ListModel (unknown location) move: out of range";
+ QTest::newRow("move3b") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(1,-1,1)}" << 0 << "QML ListModel (unknown location) move: out of range";
+ QTest::newRow("move3c") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(1,0,-1)}" << 0 << "QML ListModel (unknown location) move: out of range";
+ QTest::newRow("move3d") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,3,1)}" << 0 << "QML ListModel (unknown location) move: out of range";
+
+ // Structured model
+
+ QTest::newRow("listprop1a") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});count}" << 1 << "";
+ QTest::newRow("listprop1b") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});get(0).bars.get(1).a}" << 2 << "";
+ QTest::newRow("listprop2a") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});get(0).bars.append({'a':4});get(0).bars.get(3).a}" << 4 << "";
+}
+
+void tst_QmlListModel::dynamic()
+{
+ QFETCH(QString, script);
+ QFETCH(int, result);
+ QFETCH(QString, warning);
+
+ QmlEngine engine;
+ QmlListModel model;
+ QmlEngine::setContextForObject(&model,engine.rootContext());
+ engine.rootContext()->addDefaultObject(&model);
+ QmlExpression e(engine.rootContext(), script, &model);
+ if (!warning.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
+ int actual = e.value().toInt();
+ if (e.hasError())
+ qDebug() << e.error(); // errors not expected
+ QVERIFY(!e.hasError());
+ QCOMPARE(actual,result);
+}
+
+void tst_QmlListModel::error_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("id not allowed in ListElement")
+ << "import Qt 4.6\nListModel { ListElement { id: fred } }"
+ << "ListElement: cannot use reserved \"id\" property";
+
+ QTest::newRow("id allowed in ListModel")
+ << "import Qt 4.6\nListModel { id:model }"
+ << "";
+
+ QTest::newRow("random properties not allowed in ListModel")
+ << "import Qt 4.6\nListModel { foo:123 }"
+ << "ListModel: undefined property 'foo'";
+
+ QTest::newRow("random properties allowed in ListElement")
+ << "import Qt 4.6\nListModel { ListElement { foo:123 } }"
+ << "";
+
+ QTest::newRow("bindings not allowed in ListElement")
+ << "import Qt 4.6\nRectangle { id: rect; ListModel { ListElement { foo: rect.color } } }"
+ << "QTBUG-6203 ListElement should not allow binding its data to something";
+
+ QTest::newRow("random object list properties allowed in ListElement")
+ << "import Qt 4.6\nListModel { ListElement { foo: [ ListElement { bar: 123 } ] } }"
+ << "";
+
+ QTest::newRow("default properties not allowed in ListElement")
+ << "import Qt 4.6\nListModel { ListElement { Item { } } }"
+ << "QTBUG-6082 ListElement should not allow child objects";
+}
+
+void tst_QmlListModel::error()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, error);
+
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(qml.toUtf8(),
+ QUrl::fromLocalFile(QString("dummy.qml")));
+ if (error.isEmpty()) {
+ QVERIFY(!component.isError());
+ } else {
+ if (error.startsWith(QLatin1String("QTBUG-")))
+ QEXPECT_FAIL("",error.toLatin1(),Abort);
+ QVERIFY(component.isError());
+ QList<QmlError> errors = component.errors();
+ QCOMPARE(errors.count(),1);
+ QCOMPARE(errors.at(0).description(),error);
+ }
+}
+
+QTEST_MAIN(tst_QmlListModel)
+
+#include "tst_qmllistmodel.moc"
diff --git a/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro b/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro
new file mode 100644
index 0000000..542c14e
--- /dev/null
+++ b/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlmetaproperty.cpp
diff --git a/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp
new file mode 100644
index 0000000..ec6b87f
--- /dev/null
+++ b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp
@@ -0,0 +1,1123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <private/qguard_p.h>
+#include <QtDeclarative/qmlbinding.h>
+#include <QtGui/QLineEdit>
+
+class MyQmlObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyQmlObject() {}
+};
+
+QML_DECLARE_TYPE(MyQmlObject);
+QML_DEFINE_TYPE(Test,1,0,MyQmlObject,MyQmlObject);
+
+class MyAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int foo READ foo WRITE setFoo)
+public:
+ MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
+
+ int foo() const { return m_foo; }
+ void setFoo(int f) { m_foo = f; }
+
+private:
+ int m_foo;
+};
+
+class MyContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<MyQmlObject*>* children READ children)
+ Q_PROPERTY(QmlList<MyQmlObject*>* qmlChildren READ qmlChildren)
+public:
+ MyContainer() {}
+
+ QList<MyQmlObject*> *children() { return &m_children; }
+ QmlConcreteList<MyQmlObject *> *qmlChildren() { return &m_qmlChildren; }
+
+ static MyAttached *qmlAttachedProperties(QObject *o) {
+ return new MyAttached(o);
+ }
+
+private:
+ QList<MyQmlObject*> m_children;
+ QmlConcreteList<MyQmlObject *> m_qmlChildren;
+};
+
+QML_DECLARE_TYPE(MyContainer);
+QML_DEFINE_TYPE(Test,1,0,MyContainer,MyContainer);
+QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
+
+class tst_qmlmetaproperty : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlmetaproperty() {}
+
+private slots:
+
+ // Constructors
+ void qmlmetaproperty();
+ void qmlmetaproperty_object();
+ void qmlmetaproperty_object_string();
+ void qmlmetaproperty_object_context();
+ void qmlmetaproperty_object_string_context();
+
+ // Methods
+ void name();
+ void read();
+ void write();
+ void reset();
+
+ // Functionality
+ void writeObjectToList();
+ void writeListToList();
+ void writeObjectToQmlList();
+
+ //writeToReadOnly();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_qmlmetaproperty::qmlmetaproperty()
+{
+ QmlMetaProperty prop;
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString());
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), QmlMetaProperty::Invalid);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), false);
+ QCOMPARE(prop.object(), (QObject *)0);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QVERIFY(prop.property().name() == 0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), -1);
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+}
+
+class PropertyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int defaultProperty READ defaultProperty);
+ Q_PROPERTY(QRect rectProperty READ rectProperty);
+ Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty);
+ Q_PROPERTY(QUrl url READ url WRITE setUrl);
+ Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty);
+
+ Q_CLASSINFO("DefaultProperty", "defaultProperty");
+public:
+ PropertyObject() : m_resetProperty(9) {}
+
+ int defaultProperty() { return 10; }
+ QRect rectProperty() { return QRect(10, 10, 1, 209); }
+
+ QRect wrectProperty() { return m_rect; }
+ void setWRectProperty(const QRect &r) { m_rect = r; }
+
+ QUrl url() { return m_url; }
+ void setUrl(const QUrl &u) { m_url = u; }
+
+ int resettableProperty() const { return m_resetProperty; }
+ void setResettableProperty(int r) { m_resetProperty = r; }
+ void resetProperty() { m_resetProperty = 9; }
+
+signals:
+ void clicked();
+
+private:
+ int m_resetProperty;
+ QRect m_rect;
+ QUrl m_url;
+};
+
+void tst_qmlmetaproperty::qmlmetaproperty_object()
+{
+ QObject object; // Has no default property
+ PropertyObject dobject; // Has default property
+
+ {
+ QmlMetaProperty prop(&object);
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString());
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), QmlMetaProperty::Invalid);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), false);
+ QCOMPARE(prop.object(), (QObject *)0);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QVERIFY(prop.property().name() == 0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), -1);
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+
+ {
+ QmlMetaProperty prop(&dobject);
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("defaultProperty"));
+ QCOMPARE(prop.read(), QVariant(10));
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), true);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), (QmlMetaProperty::Type)(QmlMetaProperty::Property | QmlMetaProperty::Default));
+ QCOMPARE(prop.isProperty(), true);
+ QCOMPARE(prop.isDefault(), true);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), true);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal);
+ QCOMPARE(prop.propertyType(), (int)QVariant::Int);
+ QCOMPARE(prop.propertyTypeName(), "int");
+ QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
+ QVERIFY(prop.binding() == 0);
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:-1: Unable to assign null to int");
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding != 0);
+ QVERIFY(prop.binding() == binding);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+}
+
+void tst_qmlmetaproperty::qmlmetaproperty_object_string()
+{
+ QObject object;
+ PropertyObject dobject;
+
+ {
+ QmlMetaProperty prop(&object, QString("defaultProperty"));
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString());
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), QmlMetaProperty::Invalid);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), false);
+ QCOMPARE(prop.object(), (QObject *)0);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QVERIFY(prop.property().name() == 0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), -1);
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+
+ {
+ QmlMetaProperty prop(&dobject, QString("defaultProperty"));
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("defaultProperty"));
+ QCOMPARE(prop.read(), QVariant(10));
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), true);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), QmlMetaProperty::Property);
+ QCOMPARE(prop.isProperty(), true);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), true);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal);
+ QCOMPARE(prop.propertyType(), (int)QVariant::Int);
+ QCOMPARE(prop.propertyTypeName(), "int");
+ QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
+ QVERIFY(prop.binding() == 0);
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:-1: Unable to assign null to int");
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding != 0);
+ QVERIFY(prop.binding() == binding);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+
+ {
+ QmlMetaProperty prop(&dobject, QString("onClicked"));
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("onClicked"));
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant("Hello")), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
+ QCOMPARE(prop.type(), QmlMetaProperty::SignalProperty);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QCOMPARE(prop.property().name(), (const char *)0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression != 0);
+ QVERIFY(prop.signalExpression() == expression);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfMethod("clicked()"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+}
+
+void tst_qmlmetaproperty::qmlmetaproperty_object_context()
+{
+ QObject object; // Has no default property
+ PropertyObject dobject; // Has default property
+
+ {
+ QmlMetaProperty prop(&object, engine.rootContext());
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString());
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), QmlMetaProperty::Invalid);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), false);
+ QCOMPARE(prop.object(), (QObject *)0);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QVERIFY(prop.property().name() == 0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), -1);
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+
+ {
+ QmlMetaProperty prop(&dobject, engine.rootContext());
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("defaultProperty"));
+ QCOMPARE(prop.read(), QVariant(10));
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), true);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), (QmlMetaProperty::Type)(QmlMetaProperty::Property | QmlMetaProperty::Default));
+ QCOMPARE(prop.isProperty(), true);
+ QCOMPARE(prop.isDefault(), true);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), true);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal);
+ QCOMPARE(prop.propertyType(), (int)QVariant::Int);
+ QCOMPARE(prop.propertyTypeName(), "int");
+ QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
+ QVERIFY(prop.binding() == 0);
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:-1: Unable to assign null to int");
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding != 0);
+ QVERIFY(prop.binding() == binding);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+}
+
+void tst_qmlmetaproperty::qmlmetaproperty_object_string_context()
+{
+ QObject object;
+ PropertyObject dobject;
+
+ {
+ QmlMetaProperty prop(&object, QString("defaultProperty"), engine.rootContext());
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString());
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), QmlMetaProperty::Invalid);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), false);
+ QCOMPARE(prop.object(), (QObject *)0);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QVERIFY(prop.property().name() == 0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), -1);
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+
+ {
+ QmlMetaProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("defaultProperty"));
+ QCOMPARE(prop.read(), QVariant(10));
+ QCOMPARE(prop.write(QVariant()), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), true);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QVERIFY(prop.method().signature() == 0);
+ QCOMPARE(prop.type(), QmlMetaProperty::Property);
+ QCOMPARE(prop.isProperty(), true);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), true);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal);
+ QCOMPARE(prop.propertyType(), (int)QVariant::Int);
+ QCOMPARE(prop.propertyTypeName(), "int");
+ QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
+ QVERIFY(prop.binding() == 0);
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:-1: Unable to assign null to int");
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding != 0);
+ QVERIFY(prop.binding() == binding);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression == 0);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+
+ {
+ QmlMetaProperty prop(&dobject, QString("onClicked"), engine.rootContext());
+
+ QGuard<QmlBinding> binding(new QmlBinding(QString(), 0, 0));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QmlExpression> expression(new QmlExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("onClicked"));
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant("Hello")), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
+ QCOMPARE(prop.type(), QmlMetaProperty::SignalProperty);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QCOMPARE(prop.property().name(), (const char *)0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression != 0);
+ QVERIFY(prop.signalExpression() == expression);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfMethod("clicked()"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
+}
+
+void tst_qmlmetaproperty::name()
+{
+ {
+ QmlMetaProperty p;
+ QCOMPARE(p.name(), QString());
+ }
+
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o);
+ QCOMPARE(p.name(), QString("defaultProperty"));
+ }
+
+ {
+ QObject o;
+ QmlMetaProperty p(&o, QString("objectName"));
+ QCOMPARE(p.name(), QString("objectName"));
+ }
+
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, "onClicked");
+ QCOMPARE(p.name(), QString("onClicked"));
+ }
+
+ {
+ QObject o;
+ QmlMetaProperty p(&o, "onClicked");
+ QCOMPARE(p.name(), QString());
+ }
+
+ {
+ QObject o;
+ QmlMetaProperty p(&o, "foo");
+ QCOMPARE(p.name(), QString());
+ }
+
+ {
+ QmlMetaProperty p(0, "foo");
+ QCOMPARE(p.name(), QString());
+ }
+
+ {
+ PropertyObject o;
+ QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty");
+ QCOMPARE(p.name(), QString("rectProperty"));
+ }
+
+ {
+ PropertyObject o;
+ QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.x");
+ QCOMPARE(p.name(), QString("rectProperty.x"));
+ }
+
+ {
+ PropertyObject o;
+ QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.foo");
+ QCOMPARE(p.name(), QString());
+ }
+}
+
+void tst_qmlmetaproperty::read()
+{
+ // Invalid
+ {
+ QmlMetaProperty p;
+ QCOMPARE(p.read(), QVariant());
+ }
+
+ // Default prop
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o);
+ QCOMPARE(p.read(), QVariant(10));
+ }
+
+ // Invalid default prop
+ {
+ QObject o;
+ QmlMetaProperty p(&o);
+ QCOMPARE(p.read(), QVariant());
+ }
+
+ // Value prop by name
+ {
+ QObject o;
+
+ QmlMetaProperty p(&o, "objectName");
+ QCOMPARE(p.read(), QVariant(QString()));
+
+ o.setObjectName("myName");
+
+ QCOMPARE(p.read(), QVariant("myName"));
+ }
+
+ // Value-type prop
+ {
+ PropertyObject o;
+ QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.x");
+ QCOMPARE(p.read(), QVariant(10));
+ }
+
+ // Invalid value-type prop
+ {
+ PropertyObject o;
+ QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.foo");
+ QCOMPARE(p.read(), QVariant());
+ }
+
+ // Signal property
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, "onClicked");
+ QCOMPARE(p.read(), QVariant());
+
+ QVERIFY(0 == p.setSignalExpression(new QmlExpression()));
+ QVERIFY(0 != p.signalExpression());
+
+ QCOMPARE(p.read(), QVariant());
+ }
+
+ // Deleted object
+ {
+ PropertyObject *o = new PropertyObject;
+ QmlMetaProperty p = QmlMetaProperty::createProperty(o, "rectProperty.x");
+ QCOMPARE(p.read(), QVariant(10));
+ delete o;
+ QCOMPARE(p.read(), QVariant());
+ }
+
+ // Attached property
+ {
+ QmlComponent component(&engine);
+ component.setData("import Test 1.0\nMyContainer { }", QUrl());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QmlMetaProperty p = QmlMetaProperty::createProperty(object, "MyContainer.foo", qmlContext(object));
+ QCOMPARE(p.read(), QVariant(13));
+ delete object;
+ }
+ {
+ QmlComponent component(&engine);
+ component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QmlMetaProperty p = QmlMetaProperty::createProperty(object, "MyContainer.foo", qmlContext(object));
+ QCOMPARE(p.read(), QVariant(10));
+ delete object;
+ }
+ {
+ QmlComponent component(&engine);
+ component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QmlMetaProperty p = QmlMetaProperty::createProperty(object, "Foo.MyContainer.foo", qmlContext(object));
+ QCOMPARE(p.read(), QVariant(10));
+ delete object;
+ }
+}
+
+void tst_qmlmetaproperty::write()
+{
+ // Invalid
+ {
+ QmlMetaProperty p;
+ QCOMPARE(p.write(QVariant(10)), false);
+ }
+
+ // Read-only default prop
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o);
+ QCOMPARE(p.write(QVariant(10)), false);
+ }
+
+ // Invalid default prop
+ {
+ QObject o;
+ QmlMetaProperty p(&o);
+ QCOMPARE(p.write(QVariant(10)), false);
+ }
+
+ // Read-only prop by name
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, QString("defaultProperty"));
+ QCOMPARE(p.write(QVariant(10)), false);
+ }
+
+ // Writable prop by name
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, QString("objectName"));
+ QCOMPARE(o.objectName(), QString());
+ QCOMPARE(p.write(QVariant(QString("myName"))), true);
+ QCOMPARE(o.objectName(), QString("myName"));
+ }
+
+ // Deleted object
+ {
+ PropertyObject *o = new PropertyObject;
+ QmlMetaProperty p(o, QString("objectName"));
+ QCOMPARE(p.write(QVariant(QString("myName"))), true);
+ QCOMPARE(o->objectName(), QString("myName"));
+
+ delete o;
+
+ QCOMPARE(p.write(QVariant(QString("myName"))), false);
+ }
+
+ // Signal property
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, "onClicked");
+ QCOMPARE(p.write(QVariant("console.log(1921)")), false);
+
+ QVERIFY(0 == p.setSignalExpression(new QmlExpression()));
+ QVERIFY(0 != p.signalExpression());
+
+ QCOMPARE(p.write(QVariant("console.log(1921)")), false);
+
+ QVERIFY(0 != p.signalExpression());
+ }
+
+ // Value-type property
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, "wrectProperty");
+
+ QCOMPARE(o.wrectProperty(), QRect());
+ QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
+ QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
+
+ QmlMetaProperty p2 = QmlMetaProperty::createProperty(&o, "wrectProperty.x");
+ QCOMPARE(p2.read(), QVariant(1));
+ QCOMPARE(p2.write(QVariant(6)), true);
+ QCOMPARE(p2.read(), QVariant(6));
+ QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
+ }
+
+ // URL-property
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, "url");
+
+ QCOMPARE(p.write(QUrl("main.qml")), true);
+ QCOMPARE(o.url(), QUrl("main.qml"));
+
+ QmlMetaProperty p2(&o, "url", engine.rootContext());
+
+ QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
+ QVERIFY(result != QUrl("main.qml"));
+
+ QCOMPARE(p2.write(QUrl("main.qml")), true);
+ QCOMPARE(o.url(), result);
+ }
+
+ // Attached property
+ {
+ QmlComponent component(&engine);
+ component.setData("import Test 1.0\nMyContainer { }", QUrl());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QmlMetaProperty p = QmlMetaProperty::createProperty(object, "MyContainer.foo", qmlContext(object));
+ p.write(QVariant(99));
+ QCOMPARE(p.read(), QVariant(99));
+ delete object;
+ }
+ {
+ QmlComponent component(&engine);
+ component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QmlMetaProperty p = QmlMetaProperty::createProperty(object, "Foo.MyContainer.foo", qmlContext(object));
+ p.write(QVariant(99));
+ QCOMPARE(p.read(), QVariant(99));
+ delete object;
+ }
+}
+
+void tst_qmlmetaproperty::reset()
+{
+ // Invalid
+ {
+ QmlMetaProperty p;
+ QCOMPARE(p.isResettable(), false);
+ QCOMPARE(p.reset(), false);
+ }
+
+ // Read-only default prop
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o);
+ QCOMPARE(p.isResettable(), false);
+ QCOMPARE(p.reset(), false);
+ }
+
+ // Invalid default prop
+ {
+ QObject o;
+ QmlMetaProperty p(&o);
+ QCOMPARE(p.isResettable(), false);
+ QCOMPARE(p.reset(), false);
+ }
+
+ // Non-resettable-only prop by name
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, QString("defaultProperty"));
+ QCOMPARE(p.isResettable(), false);
+ QCOMPARE(p.reset(), false);
+ }
+
+ // Resettable prop by name
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, QString("resettableProperty"));
+
+ QCOMPARE(p.read(), QVariant(9));
+ QCOMPARE(p.write(QVariant(11)), true);
+ QCOMPARE(p.read(), QVariant(11));
+
+ QCOMPARE(p.isResettable(), true);
+ QCOMPARE(p.reset(), true);
+
+ QCOMPARE(p.read(), QVariant(9));
+ }
+
+ // Deleted object
+ {
+ PropertyObject *o = new PropertyObject;
+
+ QmlMetaProperty p(o, QString("resettableProperty"));
+
+ QCOMPARE(p.isResettable(), true);
+ QCOMPARE(p.reset(), true);
+
+ delete o;
+
+ QCOMPARE(p.isResettable(), false);
+ QCOMPARE(p.reset(), false);
+ }
+
+ // Signal property
+ {
+ PropertyObject o;
+ QmlMetaProperty p(&o, "onClicked");
+
+ QCOMPARE(p.isResettable(), false);
+ QCOMPARE(p.reset(), false);
+ }
+}
+
+void tst_qmlmetaproperty::writeObjectToList()
+{
+ QmlComponent containerComponent(&engine);
+ containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->children()->size() == 1);
+
+ MyQmlObject *object = new MyQmlObject;
+ QmlMetaProperty prop(container, "children");
+ prop.write(qVariantFromValue(object));
+ QCOMPARE(container->children()->size(), 2);
+ QCOMPARE(container->children()->at(1), object);
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void tst_qmlmetaproperty::writeListToList()
+{
+ QmlComponent containerComponent(&engine);
+ containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->children()->size() == 1);
+
+ QList<QObject*> objList;
+ objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
+ QmlMetaProperty prop(container, "children");
+ prop.write(qVariantFromValue(objList));
+ QCOMPARE(container->children()->size(), 4);
+
+ //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
+ /*QList<MyQmlObject*> typedObjList;
+ typedObjList << new MyQmlObject();
+ prop.write(qVariantFromValue(&typedObjList));
+ QCOMPARE(container->children()->size(), 1);*/
+}
+
+void tst_qmlmetaproperty::writeObjectToQmlList()
+{
+ QmlComponent containerComponent(&engine);
+ containerComponent.setData("import Test 1.0\nMyContainer { qmlChildren: MyQmlObject {} }", QUrl());
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qmlChildren()->size() == 1);
+
+ MyQmlObject *object = new MyQmlObject;
+ QmlMetaProperty prop(container, "qmlChildren");
+ prop.write(qVariantFromValue(object));
+ QCOMPARE(container->qmlChildren()->size(), 2);
+ QCOMPARE(container->qmlChildren()->at(1), object);
+}
+
+QTEST_MAIN(tst_qmlmetaproperty)
+
+#include "tst_qmlmetaproperty.moc"
diff --git a/tests/auto/declarative/qmlmetatype/qmlmetatype.pro b/tests/auto/declarative/qmlmetatype/qmlmetatype.pro
new file mode 100644
index 0000000..3a9a400
--- /dev/null
+++ b/tests/auto/declarative/qmlmetatype/qmlmetatype.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlmetatype.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlmetatype/tst_qmlmetatype.cpp b/tests/auto/declarative/qmlmetatype/tst_qmlmetatype.cpp
new file mode 100644
index 0000000..ccb8f30
--- /dev/null
+++ b/tests/auto/declarative/qmlmetatype/tst_qmlmetatype.cpp
@@ -0,0 +1,445 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlMetaType>
+#include <QLocale>
+#include <QPixmap>
+#include <QBitmap>
+#include <QPen>
+#include <QTextLength>
+#include <QMatrix4x4>
+#include <QVector2D>
+#include <QVector3D>
+#include <QVector4D>
+#include <QQuaternion>
+#include <qml.h>
+
+class tst_qmlmetatype : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlmetatype() {}
+
+private slots:
+ void copy();
+
+ void qmlParserStatusCast();
+ void qmlPropertyValueSourceCast();
+ void qmlPropertyValueInterceptorCast();
+
+ void isList();
+ void isQmlList();
+
+ void listCount();
+ void listAt();
+
+ void defaultObject();
+};
+
+class TestType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int foo READ foo);
+
+ Q_CLASSINFO("DefaultProperty", "foo");
+public:
+ int foo() { return 0; }
+};
+QML_DECLARE_TYPE(TestType);
+QML_DEFINE_TYPE(Test, 1, 0, TestType, TestType);
+
+class ParserStatusTestType : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_CLASSINFO("DefaultProperty", "foo"); // Missing default property
+};
+QML_DECLARE_TYPE(ParserStatusTestType);
+QML_DEFINE_TYPE(Test, 1, 0, ParserStatusTestType, ParserStatusTestType);
+
+class ValueSourceTestType : public QObject, public QmlPropertyValueSource
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlPropertyValueSource)
+public:
+ virtual void setTarget(const QmlMetaProperty &) {}
+};
+QML_DECLARE_TYPE(ValueSourceTestType);
+QML_DEFINE_TYPE(Test, 1, 0, ValueSourceTestType, ValueSourceTestType);
+
+class ValueInterceptorTestType : public QObject, public QmlPropertyValueInterceptor
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlPropertyValueInterceptor)
+public:
+ virtual void setTarget(const QmlMetaProperty &) {}
+ virtual void write(const QVariant &) {}
+};
+QML_DECLARE_TYPE(ValueInterceptorTestType);
+QML_DEFINE_TYPE(Test, 1, 0, ValueInterceptorTestType, ValueInterceptorTestType);
+
+
+#define COPY_TEST(cpptype, metatype, value, defaultvalue) \
+{ \
+ cpptype v = (value); cpptype v2 = (value); \
+ QVERIFY(QmlMetaType::copy(QMetaType:: metatype, &v, 0)); \
+ QVERIFY(v == (defaultvalue)); \
+ QVERIFY(QmlMetaType::copy(QMetaType:: metatype, &v, &v2)); \
+ QVERIFY(v == (value)); \
+}
+
+#define QT_COPY_TEST(type, value) \
+{ \
+ type v = (value); type v2 = (value); \
+ QVERIFY(QmlMetaType::copy(QMetaType:: type, &v, 0)); \
+ QVERIFY(v == (type ())); \
+ QVERIFY(QmlMetaType::copy(QMetaType:: type, &v, &v2)); \
+ QVERIFY(v == (value)); \
+}
+
+void tst_qmlmetatype::copy()
+{
+ QVERIFY(QmlMetaType::copy(QMetaType::Void, 0, 0));
+
+ COPY_TEST(bool, Bool, true, false);
+ COPY_TEST(int, Int, 10, 0);
+ COPY_TEST(unsigned int, UInt, 10, 0);
+ COPY_TEST(long long, LongLong, 10, 0);
+ COPY_TEST(unsigned long long, ULongLong, 10, 0);
+ COPY_TEST(double, Double, 19.2, 0);
+
+ QT_COPY_TEST(QChar, QChar('a'));
+
+ QVariantMap variantMap;
+ variantMap.insert("Hello World!", QVariant(10));
+ QT_COPY_TEST(QVariantMap, variantMap);
+
+ QT_COPY_TEST(QVariantList, QVariantList() << QVariant(19.2));
+ QT_COPY_TEST(QString, QString("QML Rocks!"));
+ QT_COPY_TEST(QStringList, QStringList() << "QML" << "Rocks");
+ QT_COPY_TEST(QByteArray, QByteArray("0x1102DDD"));
+ QT_COPY_TEST(QBitArray, QBitArray(102, true));
+ QT_COPY_TEST(QDate, QDate::currentDate());
+ QT_COPY_TEST(QTime, QTime::currentTime());
+ QT_COPY_TEST(QDateTime, QDateTime::currentDateTime());
+ QT_COPY_TEST(QUrl, QUrl("http://www.nokia.com"));
+ QT_COPY_TEST(QLocale, QLocale(QLocale::English, QLocale::Australia));
+ QT_COPY_TEST(QRect, QRect(-10, 10, 102, 99));
+ QT_COPY_TEST(QRectF, QRectF(-10.2, 1.2, 102, 99.6));
+ QT_COPY_TEST(QSize, QSize(100, 2));
+ QT_COPY_TEST(QSizeF, QSizeF(20.2, -100234.2));
+ QT_COPY_TEST(QLine, QLine(0, 0, 100, 100));
+ QT_COPY_TEST(QLineF, QLineF(-10.2, 0, 103, 1));
+ QT_COPY_TEST(QPoint, QPoint(-1912, 1613));
+ QT_COPY_TEST(QPointF, QPointF(-908.1, 1612));
+ QT_COPY_TEST(QRegExp, QRegExp("(\\d+)(?:\\s*)(cm|inch)"));
+
+ QVariantHash variantHash;
+ variantHash.insert("Hello World!", QVariant(19));
+ QT_COPY_TEST(QVariantHash, variantHash);
+
+#ifdef QT3_SUPPORT
+ QT_COPY_TEST(QColorGroup, QColorGroup(Qt::red, Qt::red, Qt::red, Qt::red, Qt::red, Qt::red, Qt::red));
+#endif
+
+ QT_COPY_TEST(QFont, QFont("Helvetica", 1024));
+
+ {
+ QPixmap v = QPixmap(100, 100); QPixmap v2 = QPixmap(100, 100);
+ QVERIFY(QmlMetaType::copy(QMetaType::QPixmap, &v, 0));
+ QVERIFY(v.size() == QPixmap().size());
+ QVERIFY(QmlMetaType::copy(QMetaType::QPixmap , &v, &v2));
+ QVERIFY(v.size() == QPixmap(100,100).size());
+ }
+
+ QT_COPY_TEST(QBrush, QBrush(Qt::blue));
+ QT_COPY_TEST(QColor, QColor("lightsteelblue"));
+ QT_COPY_TEST(QPalette, QPalette(Qt::green));
+
+ {
+ QPixmap icon(100, 100);
+
+ QIcon v = QIcon(icon); QIcon v2 = QIcon(icon);
+ QVERIFY(QmlMetaType::copy(QMetaType::QIcon, &v, 0));
+ QVERIFY(v.isNull() == QIcon().isNull());
+ QVERIFY(QmlMetaType::copy(QMetaType::QIcon , &v, &v2));
+ QVERIFY(v.isNull() == QIcon(icon).isNull());
+ }
+
+ {
+ QImage v = QImage(100, 100, QImage::Format_RGB32);
+ QImage v2 = QImage(100, 100, QImage::Format_RGB32);
+ QVERIFY(QmlMetaType::copy(QMetaType::QImage, &v, 0));
+ QVERIFY(v.size() == QImage().size());
+ QVERIFY(QmlMetaType::copy(QMetaType::QImage , &v, &v2));
+ QVERIFY(v.size() == QImage(100,100, QImage::Format_RGB32).size());
+ }
+
+ QT_COPY_TEST(QPolygon, QPolygon(QRect(100, 100, 200, 103)));
+ QT_COPY_TEST(QRegion, QRegion(QRect(0, 10, 99, 87)));
+
+ {
+ QBitmap v = QBitmap(100, 100); QBitmap v2 = QBitmap(100, 100);
+ QVERIFY(QmlMetaType::copy(QMetaType::QBitmap, &v, 0));
+ QVERIFY(v.size() == QBitmap().size());
+ QVERIFY(QmlMetaType::copy(QMetaType::QBitmap , &v, &v2));
+ QVERIFY(v.size() == QBitmap(100,100).size());
+ }
+
+ {
+ QCursor v = QCursor(Qt::SizeFDiagCursor); QCursor v2 = QCursor(Qt::SizeFDiagCursor);
+ QVERIFY(QmlMetaType::copy(QMetaType::QCursor, &v, 0));
+ QVERIFY(v.shape() == QCursor().shape());
+ QVERIFY(QmlMetaType::copy(QMetaType::QCursor , &v, &v2));
+ QVERIFY(v.shape() == QCursor(Qt::SizeFDiagCursor).shape());
+ }
+
+ QT_COPY_TEST(QSizePolicy, QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum));
+ QT_COPY_TEST(QKeySequence, QKeySequence("Ctrl+O"));
+ QT_COPY_TEST(QPen, QPen(Qt::red));
+ QT_COPY_TEST(QTextLength, QTextLength(QTextLength::FixedLength, 10.2));
+ QT_COPY_TEST(QTextFormat, QTextFormat(QTextFormat::ListFormat));
+ QT_COPY_TEST(QMatrix, QMatrix().translate(10, 10));
+ QT_COPY_TEST(QTransform, QTransform().translate(10, 10));
+ QT_COPY_TEST(QMatrix4x4, QMatrix4x4(1,0,2,3,0,1,0,0,9,0,1,0,0,0,10,1));
+ QT_COPY_TEST(QVector2D, QVector2D(10.2, 1));
+ QT_COPY_TEST(QVector3D, QVector3D(10.2, 1, -2));
+ QT_COPY_TEST(QVector4D, QVector4D(10.2, 1, -2, 1.2));
+ QT_COPY_TEST(QQuaternion, QQuaternion(1.0, 10.2, 1, -2));
+
+ int voidValue;
+ COPY_TEST(void *, VoidStar, (void *)&voidValue, (void *)0);
+ COPY_TEST(long, Long, 10, 0);
+ COPY_TEST(short, Short, 10, 0);
+ COPY_TEST(char, Char, 'a', 0);
+ COPY_TEST(unsigned long, ULong, 10, 0);
+ COPY_TEST(unsigned short, UShort, 10, 0);
+ COPY_TEST(unsigned char, UChar, 'a', 0);
+ COPY_TEST(float, Float, 10.5, 0);
+
+ QObject objectValue;
+ QWidget widgetValue;
+ COPY_TEST(QObject *, QObjectStar, &objectValue, 0);
+ COPY_TEST(QWidget *, QWidgetStar, &widgetValue, 0);
+ COPY_TEST(qreal, QReal, 10.2, 0);
+
+ {
+ QVariant tv = QVariant::fromValue(QVariant(10));
+ QVariant v(tv); QVariant v2(tv);
+ QVERIFY(QmlMetaType::copy(qMetaTypeId<QVariant>(), &v, 0));
+ QVERIFY(v == QVariant());
+ QVERIFY(QmlMetaType::copy(qMetaTypeId<QVariant>(), &v, &v2));
+ QVERIFY(v == tv);
+ }
+
+ {
+ TestType t; QVariant tv = QVariant::fromValue(&t);
+
+ QVariant v(tv); QVariant v2(tv);
+ QVERIFY(QmlMetaType::copy(qMetaTypeId<TestType *>(), &v, 0));
+ QVERIFY(v == QVariant::fromValue((TestType *)0));
+ QVERIFY(QmlMetaType::copy(qMetaTypeId<TestType *>(), &v, &v2));
+ QVERIFY(v == tv);
+ }
+}
+
+void tst_qmlmetatype::qmlParserStatusCast()
+{
+ QVERIFY(QmlMetaType::qmlType(QVariant::Int) == 0);
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
+ QCOMPARE(QmlMetaType::qmlType(qMetaTypeId<TestType *>())->parserStatusCast(), -1);
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()) != 0);
+ QCOMPARE(QmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>())->parserStatusCast(), -1);
+
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
+ int cast = QmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->parserStatusCast();
+ QVERIFY(cast != -1);
+ QVERIFY(cast != 0);
+
+ ParserStatusTestType t;
+ QVERIFY(reinterpret_cast<char *>((QObject *)&t) != reinterpret_cast<char *>((QmlParserStatus *)&t));
+
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>((QObject *)&t) + cast);
+ QCOMPARE(status, &t);
+}
+
+void tst_qmlmetatype::qmlPropertyValueSourceCast()
+{
+ QVERIFY(QmlMetaType::qmlType(QVariant::Int) == 0);
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
+ QCOMPARE(QmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueSourceCast(), -1);
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
+ QCOMPARE(QmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->propertyValueSourceCast(), -1);
+
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()) != 0);
+ int cast = QmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>())->propertyValueSourceCast();
+ QVERIFY(cast != -1);
+ QVERIFY(cast != 0);
+
+ ValueSourceTestType t;
+ QVERIFY(reinterpret_cast<char *>((QObject *)&t) != reinterpret_cast<char *>((QmlPropertyValueSource *)&t));
+
+ QmlPropertyValueSource *source = reinterpret_cast<QmlPropertyValueSource *>(reinterpret_cast<char *>((QObject *)&t) + cast);
+ QCOMPARE(source, &t);
+}
+
+void tst_qmlmetatype::qmlPropertyValueInterceptorCast()
+{
+ QVERIFY(QmlMetaType::qmlType(QVariant::Int) == 0);
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<TestType *>()) != 0);
+ QCOMPARE(QmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueInterceptorCast(), -1);
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
+ QCOMPARE(QmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->propertyValueInterceptorCast(), -1);
+
+ QVERIFY(QmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>()) != 0);
+ int cast = QmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>())->propertyValueInterceptorCast();
+ QVERIFY(cast != -1);
+ QVERIFY(cast != 0);
+
+ ValueInterceptorTestType t;
+ QVERIFY(reinterpret_cast<char *>((QObject *)&t) != reinterpret_cast<char *>((QmlPropertyValueInterceptor *)&t));
+
+ QmlPropertyValueInterceptor *interceptor = reinterpret_cast<QmlPropertyValueInterceptor *>(reinterpret_cast<char *>((QObject *)&t) + cast);
+ QCOMPARE(interceptor, &t);
+}
+
+void tst_qmlmetatype::isList()
+{
+ QCOMPARE(QmlMetaType::isList(QVariant()), false);
+ QCOMPARE(QmlMetaType::isList(QVariant::Invalid), false);
+ QCOMPARE(QmlMetaType::isList(QVariant::Int), false);
+ QCOMPARE(QmlMetaType::isList(QVariant(10)), false);
+
+ QList<TestType *> list;
+ QmlConcreteList<TestType *> qmllist;
+
+ QCOMPARE(QmlMetaType::isList(qMetaTypeId<QList<TestType *>*>()), true);
+ QCOMPARE(QmlMetaType::isList(QVariant::fromValue(&list)), true);
+ QCOMPARE(QmlMetaType::isList(qMetaTypeId<QmlList<TestType *>*>()), false);
+ QCOMPARE(QmlMetaType::isList(QVariant::fromValue((QmlList<TestType *>*)&qmllist)), false);
+}
+
+void tst_qmlmetatype::isQmlList()
+{
+ QCOMPARE(QmlMetaType::isQmlList(QVariant::Invalid), false);
+ QCOMPARE(QmlMetaType::isQmlList(QVariant::Int), false);
+
+ QCOMPARE(QmlMetaType::isQmlList(qMetaTypeId<QList<TestType *>*>()), false);
+ QCOMPARE(QmlMetaType::isQmlList(qMetaTypeId<QmlList<TestType *>*>()), true);
+}
+
+void tst_qmlmetatype::listCount()
+{
+ QCOMPARE(QmlMetaType::listCount(QVariant()), 0);
+ QCOMPARE(QmlMetaType::listCount(QVariant(10)), 0);
+
+ QList<TestType *> list;
+ QVariant listVar = QVariant::fromValue(&list);
+ QmlConcreteList<TestType *> qmllist;
+ QVariant qmllistVar = QVariant::fromValue((QmlList<TestType *>*)&qmllist);
+
+ QCOMPARE(QmlMetaType::listCount(listVar), 0);
+ QCOMPARE(QmlMetaType::listCount(qmllistVar), 0);
+
+ list.append(0); list.append(0); list.append(0);
+ qmllist.append(0); qmllist.append(0); qmllist.append(0);
+
+ QCOMPARE(QmlMetaType::listCount(listVar), 3);
+ QCOMPARE(QmlMetaType::listCount(qmllistVar), 0);
+}
+
+void tst_qmlmetatype::listAt()
+{
+ QCOMPARE(QmlMetaType::listAt(QVariant(), 0), QVariant());
+ QCOMPARE(QmlMetaType::listAt(QVariant(10), 0), QVariant());
+ QCOMPARE(QmlMetaType::listAt(QVariant(), 10), QVariant());
+ QCOMPARE(QmlMetaType::listAt(QVariant(10), 10), QVariant());
+ QCOMPARE(QmlMetaType::listAt(QVariant(), -10), QVariant());
+ QCOMPARE(QmlMetaType::listAt(QVariant(10), -10), QVariant());
+
+ QList<TestType *> list;
+ QVariant listVar = QVariant::fromValue(&list);
+ QmlConcreteList<TestType *> qmllist;
+ QVariant qmllistVar = QVariant::fromValue((QmlList<TestType *>*)&qmllist);
+
+ QCOMPARE(QmlMetaType::listAt(listVar, 0), QVariant());
+ QCOMPARE(QmlMetaType::listAt(listVar, 2), QVariant());
+ QCOMPARE(QmlMetaType::listAt(listVar, -1), QVariant());
+
+ QCOMPARE(QmlMetaType::listAt(qmllistVar, 0), QVariant());
+ QCOMPARE(QmlMetaType::listAt(qmllistVar, 2), QVariant());
+ QCOMPARE(QmlMetaType::listAt(qmllistVar, -1), QVariant());
+
+ TestType ttype;
+ QVariant ttypeVar = QVariant::fromValue(&ttype);
+ QVariant nullttypeVar = QVariant::fromValue((TestType *)0);
+
+ list.append(0); list.append(&ttype); list.append(0);
+ qmllist.append(0); qmllist.append(&ttype); qmllist.append(0);
+
+ QCOMPARE(QmlMetaType::listAt(listVar, 0), nullttypeVar);
+ QCOMPARE(QmlMetaType::listAt(listVar, 1), ttypeVar);
+ QCOMPARE(QmlMetaType::listAt(listVar, -1), QVariant());
+
+ QCOMPARE(QmlMetaType::listAt(qmllistVar, 0), QVariant());
+ QCOMPARE(QmlMetaType::listAt(qmllistVar, 2), QVariant());
+ QCOMPARE(QmlMetaType::listAt(qmllistVar, -1), QVariant());
+}
+
+void tst_qmlmetatype::defaultObject()
+{
+ QVERIFY(QmlMetaType::defaultProperty(&QObject::staticMetaObject).name() == 0);
+ QVERIFY(QmlMetaType::defaultProperty(&ParserStatusTestType::staticMetaObject).name() == 0);
+ QCOMPARE(QString(QmlMetaType::defaultProperty(&TestType::staticMetaObject).name()), QString("foo"));
+
+ QObject o;
+ TestType t;
+ ParserStatusTestType p;
+
+ QVERIFY(QmlMetaType::defaultProperty((QObject *)0).name() == 0);
+ QVERIFY(QmlMetaType::defaultProperty(&o).name() == 0);
+ QVERIFY(QmlMetaType::defaultProperty(&p).name() == 0);
+ QCOMPARE(QString(QmlMetaType::defaultProperty(&t).name()), QString("foo"));
+}
+
+QTEST_MAIN(tst_qmlmetatype)
+
+#include "tst_qmlmetatype.moc"
diff --git a/tests/auto/declarative/qmlmoduleplugin/plugin.qml b/tests/auto/declarative/qmlmoduleplugin/plugin.qml
new file mode 100644
index 0000000..f29ae24
--- /dev/null
+++ b/tests/auto/declarative/qmlmoduleplugin/plugin.qml
@@ -0,0 +1,3 @@
+import com.nokia.AutoTestQmlPluginType 1.0
+
+MyPluginType { value: 123 }
diff --git a/tests/auto/declarative/qmlmoduleplugin/plugin/plugin.cpp b/tests/auto/declarative/qmlmoduleplugin/plugin/plugin.cpp
new file mode 100644
index 0000000..10adda0
--- /dev/null
+++ b/tests/auto/declarative/qmlmoduleplugin/plugin/plugin.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtDeclarative/qmlmoduleplugin.h>
+#include <QtDeclarative/qml.h>
+#include <QDebug>
+
+class MyPluginType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+
+public:
+ MyPluginType(QObject *parent=0) : QObject(parent)
+ {
+ qWarning("import worked");
+ }
+
+ int value() const { return v; }
+ void setValue(int i) { v = i; }
+
+private:
+ int v;
+};
+
+QML_DECLARE_TYPE(MyPluginType);
+QML_DEFINE_TYPE(com.nokia.AutoTestQmlPluginType,1,0,MyPluginType,MyPluginType);
+
+
+class MyPlugin : public QmlModulePlugin
+{
+ Q_OBJECT
+public:
+ MyPlugin()
+ {
+ qWarning("plugin created");
+ }
+
+ QStringList keys() const
+ {
+ return QStringList() << QLatin1String("com.nokia.AutoTestQmlPluginType");
+ }
+};
+
+#include "plugin.moc"
+
+Q_EXPORT_PLUGIN2(plugin, MyPlugin);
diff --git a/tests/auto/declarative/qmlmoduleplugin/plugin/plugin.pro b/tests/auto/declarative/qmlmoduleplugin/plugin/plugin.pro
new file mode 100644
index 0000000..0625ea3
--- /dev/null
+++ b/tests/auto/declarative/qmlmoduleplugin/plugin/plugin.pro
@@ -0,0 +1,5 @@
+TEMPLATE = lib
+CONFIG += plugin
+SOURCES = plugin.cpp
+QT = core declarative
+DESTDIR = qmlmodules
diff --git a/tests/auto/declarative/qmlmoduleplugin/qmlmoduleplugin.pro b/tests/auto/declarative/qmlmoduleplugin/qmlmoduleplugin.pro
new file mode 100644
index 0000000..c60743d
--- /dev/null
+++ b/tests/auto/declarative/qmlmoduleplugin/qmlmoduleplugin.pro
@@ -0,0 +1,7 @@
+QT = core
+TEMPLATE = subdirs
+SUBDIRS = plugin
+tst_qmlmoduleplugin_pro.depends += plugin
+SUBDIRS += tst_qmlmoduleplugin.pro
+
+
diff --git a/tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.cpp b/tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.cpp
new file mode 100644
index 0000000..3f97abd
--- /dev/null
+++ b/tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <qdir.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QDebug>
+
+class tst_qmlmoduleplugin : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlmoduleplugin() {
+ QCoreApplication::addLibraryPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("plugin"));
+qDebug() << QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("plugin");
+ }
+
+private slots:
+ void importsPlugin();
+};
+
+#define VERIFY_ERRORS(errorfile) \
+ if (!errorfile) { \
+ if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
+ qWarning() << "Unexpected Errors:" << component.errors(); \
+ QVERIFY(!component.isError()); \
+ QVERIFY(component.errors().isEmpty()); \
+ } else { \
+ QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
+ QVERIFY(file.open(QIODevice::ReadOnly)); \
+ QByteArray data = file.readAll(); \
+ file.close(); \
+ QList<QByteArray> expected = data.split('\n'); \
+ expected.removeAll(QByteArray("")); \
+ QList<QmlError> errors = component.errors(); \
+ QList<QByteArray> actual; \
+ for (int ii = 0; ii < errors.count(); ++ii) { \
+ const QmlError &error = errors.at(ii); \
+ QByteArray errorStr = QByteArray::number(error.line()) + ":" + \
+ QByteArray::number(error.column()) + ":" + \
+ error.description().toUtf8(); \
+ actual << errorStr; \
+ } \
+ if (qgetenv("DEBUG") != "" && expected != actual) \
+ qWarning() << "Expected:" << expected << "Actual:" << actual; \
+ if (qgetenv("QMLLANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
+ QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
+ QVERIFY(file.open(QIODevice::WriteOnly)); \
+ for (int ii = 0; ii < actual.count(); ++ii) { \
+ file.write(actual.at(ii)); file.write("\n"); \
+ } \
+ file.close(); \
+ } else { \
+ QCOMPARE(expected, actual); \
+ } \
+ }
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ QFileInfo fileInfo(__FILE__);
+ return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(filename));
+}
+
+
+void tst_qmlmoduleplugin::importsPlugin()
+{
+ QmlEngine engine;
+ QTest::ignoreMessage(QtWarningMsg, "plugin created");
+ QTest::ignoreMessage(QtWarningMsg, "import worked");
+ QmlComponent component(&engine, TEST_FILE("plugin.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("value").toInt(),123);
+}
+
+QTEST_MAIN(tst_qmlmoduleplugin)
+
+#include "tst_qmlmoduleplugin.moc"
diff --git a/tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.pro b/tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.pro
new file mode 100644
index 0000000..3c8a568
--- /dev/null
+++ b/tests/auto/declarative/qmlmoduleplugin/tst_qmlmoduleplugin.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES = tst_qmlmoduleplugin.cpp
+QT += declarative
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlnumberformatter/qmlnumberformatter.pro b/tests/auto/declarative/qmlnumberformatter/qmlnumberformatter.pro
new file mode 100644
index 0000000..8113278
--- /dev/null
+++ b/tests/auto/declarative/qmlnumberformatter/qmlnumberformatter.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlnumberformatter.cpp
diff --git a/tests/auto/declarative/qmlnumberformatter/tst_qmlnumberformatter.cpp b/tests/auto/declarative/qmlnumberformatter/tst_qmlnumberformatter.cpp
new file mode 100644
index 0000000..bf71625
--- /dev/null
+++ b/tests/auto/declarative/qmlnumberformatter/tst_qmlnumberformatter.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QDebug>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qnumberformat_p.h>
+#include <private/qmlnumberformatter_p.h>
+
+class tst_numberformat : public QObject
+{
+ Q_OBJECT
+public:
+ tst_numberformat();
+
+ void init() {}
+ void initTestCase() {}
+
+ void cleanup() {}
+ void cleanupTestCase() {}
+
+private slots:
+ void text_data();
+ void text();
+
+private:
+ QStringList strings;
+ QStringList formats;
+ QStringList texts;
+};
+
+tst_numberformat::tst_numberformat()
+{
+ strings << "100.0"
+ << "12345"
+ << "1234567"
+ << "0.123"
+ << "0.9999"
+ << "0.989"
+ << "1"
+ << "1.0"
+ << "1.01";
+
+ formats << ""
+ << "0000"
+ << "0000.00"
+ << "##"
+ << "##.##"
+ << "#0.00#"
+ << "##,##0.##"
+ << "(000) 000 - 000"
+ << "00000,000.0000";
+
+ //US locale only.
+ texts << "100.000000"
+ << "12345.000000"
+ << "1234567.000000"
+ << "0.123000"
+ << "0.999900"
+ << "0.989000"
+ << "1.000000"
+ << "1.000000"
+ << "1.010000" //end ""
+ << "0100"
+ << "12345"
+ << "1234567"
+ << "0000"
+ << "0001"
+ << "0001"
+ << "0001"
+ << "0001"
+ << "0001" // end "0000"
+ << "0100.00"
+ << "12345.00"
+ << "1234567.00"
+ << "0000.12"
+ << "0001.00"
+ << "0000.99"
+ << "0001.00"
+ << "0001.00"
+ << "0001.01" // end "0000.00"
+ << "100"
+ << "12345"
+ << "1234567"
+ << "0"
+ << "1"
+ << "1"
+ << "1"
+ << "1"
+ << "1" // end "##"
+ << "100"//start "##.##"
+ << "12345"
+ << "1234567"
+ << "0.12"
+ << "1"
+ << "0.99"
+ << "1"
+ << "1"
+ << "1.01" // end "##.##" -- ### EXPECT FAIL ### QNumberFormat::formatDecimal() bug
+ << "100.00" //start "#0.00#"
+ << "12345.00"
+ << "1234567.00"
+ << "0.123"
+ << "1.00"
+ << "0.989"
+ << "1.00"
+ << "1.00"
+ << "1.01" //end "#0.00#"
+ << "100" //start "##,##0.##"
+ << "12,345"
+ << "1,234,567"
+ << "0.12"
+ << "1"
+ << "0.99"
+ << "1"
+ << "1"
+ << "1.01" //end "##,##0.##" -- ### EXPECT FAIL ### QNumberFormat::formatDecimal() bug
+ << "(000) 000 - 100" //start "(000) 000 - 000"
+ << "(000) 012 - 345"
+ << "(001) 234 - 567"
+ << "(000) 000 - 000"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001" // end "(000) 000 - 000"
+ << "00,000,100.0000" // start "00000,000.0000"
+ << "00,012,345.0000"
+ << "01,234,567.0000"
+ << "00,000,000.1230"
+ << "00,000,000.9999"
+ << "00,000,000.9890"
+ << "00,000,001.0000"
+ << "00,000,001.0000"
+ << "00,000,001.0100"; // end
+
+ qDebug() << "strings.size()" << strings.size()
+ << "\nformats.size()" << formats.size()
+ << "texts.size()" << texts.size();
+}
+
+void tst_numberformat::text_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<QString>("text");
+
+ for (int j=0; j < formats.size(); j++)
+ {
+ for (int i=0; i < strings.size(); i++)
+ {
+ QTest::newRow(QString("%1, %2").arg(strings.at(i)).arg(formats.at(j)).toAscii())
+ << strings.at(i) << formats.at(j) << texts.at(j*formats.size()+i);
+ }
+ }
+
+}
+
+void tst_numberformat::text()
+{
+ QFETCH(QString, string);
+ QFETCH(QString, format);
+ QFETCH(QString, text);
+
+ QString componentStr = QString("import Qt 4.6\nNumberFormatter { number: ") + string + QString("; format: \"") + format + QString("\" }");
+
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine);
+ formatterComponent.setData(componentStr.toUtf8(), QUrl::fromLocalFile(""));
+ if(formatterComponent.isError())
+ qDebug() << formatterComponent.errors();
+ QVERIFY(formatterComponent.isReady());
+ QmlNumberFormatter *formatter = qobject_cast<QmlNumberFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QCOMPARE(formatter->format(), format);
+ QCOMPARE(formatter->text(), text);
+
+ delete formatter;
+}
+
+QTEST_MAIN(tst_numberformat)
+
+#include "tst_qmlnumberformatter.moc"
diff --git a/tests/auto/declarative/qmlpixmapcache/data/exists.png b/tests/auto/declarative/qmlpixmapcache/data/exists.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/qmlpixmapcache/data/exists.png
Binary files differ
diff --git a/tests/auto/declarative/qmlpixmapcache/data/exists1.png b/tests/auto/declarative/qmlpixmapcache/data/exists1.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/qmlpixmapcache/data/exists1.png
Binary files differ
diff --git a/tests/auto/declarative/qmlpixmapcache/data/exists2.png b/tests/auto/declarative/qmlpixmapcache/data/exists2.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/qmlpixmapcache/data/exists2.png
Binary files differ
diff --git a/tests/auto/declarative/qmlpixmapcache/qmlpixmapcache.pro b/tests/auto/declarative/qmlpixmapcache/qmlpixmapcache.pro
new file mode 100644
index 0000000..423fa2f
--- /dev/null
+++ b/tests/auto/declarative/qmlpixmapcache/qmlpixmapcache.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+QT += network
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlpixmapcache.cpp
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
diff --git a/tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp b/tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp
new file mode 100644
index 0000000..50de8d5
--- /dev/null
+++ b/tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtTest/QtTest>
+#include <private/qmlpixmapcache_p.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QNetworkReply>
+
+// These don't let normal people run tests!
+//#include "../network-settings.h"
+
+class tst_qmlpixmapcache : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlpixmapcache() :
+ thisfile(QUrl::fromLocalFile(__FILE__))
+ {
+ }
+
+private slots:
+ void single();
+ void single_data();
+ void parallel();
+ void parallel_data();
+
+private:
+ QmlEngine engine;
+ QUrl thisfile;
+};
+
+
+static int slotters=0;
+
+class Slotter : public QObject
+{
+ Q_OBJECT
+public:
+ Slotter()
+ {
+ gotslot = false;
+ slotters++;
+ }
+ bool gotslot;
+
+public slots:
+ void got()
+ {
+ gotslot = true;
+ --slotters;
+ if (slotters==0)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+static const bool localfile_optimized = true;
+#else
+static const bool localfile_optimized = false;
+#endif
+
+void tst_qmlpixmapcache::single_data()
+{
+ // Note, since QmlPixmapCache is shared, tests affect each other!
+ // so use different files fore all test functions.
+
+ QTest::addColumn<QUrl>("target");
+ QTest::addColumn<bool>("incache");
+ QTest::addColumn<bool>("exists");
+ QTest::addColumn<bool>("neterror");
+
+ // File URLs are optimized
+ QTest::newRow("local") << thisfile.resolved(QUrl("data/exists.png")) << localfile_optimized << true << false;
+ QTest::newRow("local") << thisfile.resolved(QUrl("data/notexists.png")) << localfile_optimized << false << false;
+ QTest::newRow("remote") << QUrl("http://qt.nokia.com/logo.png") << false << true << false;
+ QTest::newRow("remote") << QUrl("http://qt.nokia.com/thereisnologo.png") << false << false << true;
+}
+
+void tst_qmlpixmapcache::single()
+{
+ QFETCH(QUrl, target);
+ QFETCH(bool, incache);
+ QFETCH(bool, exists);
+ QFETCH(bool, neterror);
+
+ if (neterror) {
+ QString expected = "\"Error downloading " + target.toString() + " - server replied: Not Found\" ";
+ QTest::ignoreMessage(QtWarningMsg, expected.toLatin1());
+ } else if (!exists) {
+ QString expected = "Cannot open QUrl( \"" + target.toString() + "\" ) ";
+ QTest::ignoreMessage(QtWarningMsg, expected.toLatin1());
+ }
+
+ QPixmap pixmap;
+ QVERIFY(pixmap.width() <= 0); // Check Qt assumption
+ QmlPixmapReply::Status status = QmlPixmapCache::get(target, &pixmap);
+
+ if (incache) {
+ if (exists) {
+ QVERIFY(status == QmlPixmapReply::Ready);
+ QVERIFY(pixmap.width() > 0);
+ } else {
+ QVERIFY(status == QmlPixmapReply::Error);
+ QVERIFY(pixmap.width() <= 0);
+ }
+ } else {
+ QmlPixmapReply *reply = QmlPixmapCache::request(&engine, target);
+ QVERIFY(reply);
+ QVERIFY(pixmap.width() <= 0);
+
+ Slotter getter;
+ connect(reply, SIGNAL(finished()), &getter, SLOT(got()));
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(getter.gotslot);
+ if (exists) {
+ QVERIFY(QmlPixmapCache::get(target, &pixmap) == QmlPixmapReply::Ready);
+ QVERIFY(pixmap.width() > 0);
+ } else {
+ QVERIFY(QmlPixmapCache::get(target, &pixmap) == QmlPixmapReply::Error);
+ QVERIFY(pixmap.width() <= 0);
+ }
+ }
+
+ QCOMPARE(QmlPixmapCache::pendingRequests(), 0);
+}
+
+void tst_qmlpixmapcache::parallel_data()
+{
+ // Note, since QmlPixmapCache is shared, tests affect each other!
+ // so use different files fore all test functions.
+
+ QTest::addColumn<QUrl>("target1");
+ QTest::addColumn<QUrl>("target2");
+ QTest::addColumn<int>("incache");
+ QTest::addColumn<int>("cancel"); // which one to cancel
+ QTest::addColumn<int>("requests");
+
+ QTest::newRow("local")
+ << thisfile.resolved(QUrl("data/exists1.png"))
+ << thisfile.resolved(QUrl("data/exists2.png"))
+ << (localfile_optimized ? 2 : 0)
+ << -1
+ << (localfile_optimized ? 0 : 2)
+ ;
+
+ QTest::newRow("remote")
+ << QUrl("http://qt.nokia.com/images/template/checkbox-on.png")
+ << QUrl("http://qt.nokia.com/images/products/qt-logo/image_tile")
+ << 0
+ << -1
+ << 2
+ ;
+
+ QTest::newRow("remoteagain")
+ << QUrl("http://qt.nokia.com/images/template/checkbox-on.png")
+ << QUrl("http://qt.nokia.com/images/products/qt-logo/image_tile")
+ << 2
+ << -1
+ << 0
+ ;
+
+ QTest::newRow("remotecopy")
+ << QUrl("http://qt.nokia.com/images/template/checkbox-off.png")
+ << QUrl("http://qt.nokia.com/images/template/checkbox-off.png")
+ << 0
+ << -1
+ << 1
+ ;
+
+ QTest::newRow("remotecopycancel")
+ << QUrl("http://qt.nokia.com/rounded_block_bg.png")
+ << QUrl("http://qt.nokia.com/rounded_block_bg.png")
+ << 0
+ << 0
+ << 1
+ ;
+}
+
+void tst_qmlpixmapcache::parallel()
+{
+ QFETCH(QUrl, target1);
+ QFETCH(QUrl, target2);
+ QFETCH(int, incache);
+ QFETCH(int, cancel);
+ QFETCH(int, requests);
+
+ QList<QUrl> targets;
+ targets << target1 << target2;
+
+ QList<QmlPixmapReply*> replies;
+ QList<Slotter*> getters;
+ for (int i=0; i<targets.count(); ++i) {
+ QUrl target = targets.at(i);
+ QPixmap pixmap;
+ QmlPixmapReply::Status status = QmlPixmapCache::get(target, &pixmap);
+ QmlPixmapReply *reply = 0;
+ if (status != QmlPixmapReply::Error && status != QmlPixmapReply::Ready)
+ reply = QmlPixmapCache::request(&engine, target);
+ replies.append(reply);
+ if (!reply) {
+ QVERIFY(pixmap.width() > 0);
+ getters.append(0);
+ } else {
+ QVERIFY(pixmap.width() <= 0);
+ getters.append(new Slotter);
+ connect(reply, SIGNAL(finished()), getters[i], SLOT(got()));
+ }
+ }
+
+ QCOMPARE(incache+slotters, targets.count());
+ QCOMPARE(QmlPixmapCache::pendingRequests(), requests);
+
+ if (cancel >= 0) {
+ QmlPixmapCache::cancel(targets.at(cancel), getters[cancel]);
+ slotters--;
+ }
+
+ if (slotters) {
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ }
+
+ for (int i=0; i<targets.count(); ++i) {
+ QmlPixmapReply *reply = replies[i];
+ if (reply) {
+ if (i == cancel) {
+ QVERIFY(!getters[i]->gotslot);
+ } else {
+ QVERIFY(getters[i]->gotslot);
+ QPixmap pixmap;
+ QVERIFY(QmlPixmapCache::get(targets[i], &pixmap) == QmlPixmapReply::Ready);
+ QVERIFY(pixmap.width() > 0);
+ }
+ delete getters[i];
+ }
+ }
+
+ QCOMPARE(QmlPixmapCache::pendingRequests(), 0);
+}
+
+QTEST_MAIN(tst_qmlpixmapcache)
+
+#include "tst_qmlpixmapcache.moc"
diff --git a/tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro b/tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro
new file mode 100644
index 0000000..967ab76
--- /dev/null
+++ b/tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlpropertymap.cpp
diff --git a/tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp b/tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp
new file mode 100644
index 0000000..8c457e6
--- /dev/null
+++ b/tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlpropertymap.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicstext_p.h>
+#include <QSignalSpy>
+
+class tst_QmlPropertyMap : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlPropertyMap() {}
+
+private slots:
+ void insert();
+ void operatorInsert();
+ void operatorValue();
+ void clear();
+ void changed();
+ void count();
+};
+
+void tst_QmlPropertyMap::insert()
+{
+ QmlPropertyMap map;
+ map.insert(QLatin1String("key1"),100);
+ map.insert(QLatin1String("key2"),200);
+ QVERIFY(map.keys().count() == 2);
+ QVERIFY(map.contains(QLatin1String("key1")));
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
+ QCOMPARE(map.value(QLatin1String("key2")), QVariant(200));
+
+ map.insert(QLatin1String("key1"),"Hello World");
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World"));
+}
+
+void tst_QmlPropertyMap::operatorInsert()
+{
+ QmlPropertyMap map;
+ map[QLatin1String("key1")] = 100;
+ map[QLatin1String("key2")] = 200;
+ QVERIFY(map.keys().count() == 2);
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
+ QCOMPARE(map.value(QLatin1String("key2")), QVariant(200));
+
+ map[QLatin1String("key1")] = "Hello World";
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World"));
+}
+
+void tst_QmlPropertyMap::operatorValue()
+{
+ QmlPropertyMap map;
+ map.insert(QLatin1String("key1"),100);
+ map.insert(QLatin1String("key2"),200);
+ QVERIFY(map.count() == 2);
+ QVERIFY(map.contains(QLatin1String("key1")));
+
+ const QmlPropertyMap &constMap = map;
+
+ QCOMPARE(constMap.value(QLatin1String("key1")), QVariant(100));
+ QCOMPARE(constMap.value(QLatin1String("key2")), QVariant(200));
+ QCOMPARE(constMap[QLatin1String("key1")], constMap.value(QLatin1String("key1")));
+ QCOMPARE(constMap[QLatin1String("key2")], constMap.value(QLatin1String("key2")));
+}
+
+void tst_QmlPropertyMap::clear()
+{
+ QmlPropertyMap map;
+ map.insert(QLatin1String("key1"),100);
+ QVERIFY(map.keys().count() == 1);
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
+
+ map.clear(QLatin1String("key1"));
+ QVERIFY(map.keys().count() == 1);
+ QVERIFY(map.contains(QLatin1String("key1")));
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant());
+}
+
+void tst_QmlPropertyMap::changed()
+{
+ QmlPropertyMap map;
+ QSignalSpy spy(&map, SIGNAL(valueChanged(const QString&)));
+ map.insert(QLatin1String("key1"),100);
+ map.insert(QLatin1String("key2"),200);
+ QCOMPARE(spy.count(), 0);
+
+ map.clear(QLatin1String("key1"));
+ QCOMPARE(spy.count(), 0);
+
+ //make changes in QML
+ QmlEngine engine;
+ QmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty(QLatin1String("testdata"), &map);
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6\nText { text: { testdata.key1 = 'Hello World'; 'X' } }",
+ QUrl::fromLocalFile(""));
+ QVERIFY(component.isReady());
+ QmlGraphicsText *txt = qobject_cast<QmlGraphicsText*>(component.create());
+ QVERIFY(txt);
+ QCOMPARE(txt->text(), QString('X'));
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toString(),QLatin1String("key1"));
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World"));
+}
+
+void tst_QmlPropertyMap::count()
+{
+ QmlPropertyMap map;
+ QCOMPARE(map.isEmpty(), true);
+ map.insert(QLatin1String("key1"),100);
+ map.insert(QLatin1String("key2"),200);
+ QCOMPARE(map.count(), 2);
+ QCOMPARE(map.isEmpty(), false);
+
+ map.insert(QLatin1String("key3"),"Hello World");
+ QCOMPARE(map.count(), 3);
+
+ //clearing doesn't remove the key
+ map.clear(QLatin1String("key3"));
+ QCOMPARE(map.count(), 3);
+ QCOMPARE(map.size(), map.count());
+}
+
+QTEST_MAIN(tst_QmlPropertyMap)
+
+#include "tst_qmlpropertymap.moc"
diff --git a/tests/auto/declarative/qmlqt/data/closestangle.qml b/tests/auto/declarative/qmlqt/data/closestangle.qml
new file mode 100644
index 0000000..b5f7fc6
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/closestangle.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+
+QtObject {
+ property var testSame: Qt.closestAngle(0,1)
+ property var testLess: Qt.closestAngle(0,-359)
+ property var testMore: Qt.closestAngle(0,361)
+ property var testFail: Qt.closestAngle(0)
+ property var test5: Qt.closestAngle(0,1,2)
+ property var test6: Qt.closestAngle(123.45465768,1.11)
+ property var test7: Qt.closestAngle(-3.1415,1.11)
+}
+
diff --git a/tests/auto/declarative/qmlqt/data/consoleLog.qml b/tests/auto/declarative/qmlqt/data/consoleLog.qml
new file mode 100644
index 0000000..e657ff1
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/consoleLog.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ Component.onCompleted: {
+ console.log("completed", "ok")
+ console.log("completed ok")
+ }
+}
diff --git a/tests/auto/declarative/qmlqt/data/createComponent.qml b/tests/auto/declarative/qmlqt/data/createComponent.qml
new file mode 100644
index 0000000..d9b70ec
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/createComponent.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property bool incorrectArgCount1: false
+ property bool incorrectArgCount2: false
+ property bool emptyArg: false
+
+ property string relativeUrl
+ property string absoluteUrl
+
+ Component.onCompleted: {
+ // Test that using incorrect argument count returns a null object
+ incorrectArgCount1 = (createComponent() == null);
+ incorrectArgCount2 = (createComponent("main.qml", 10) == null);
+ emptyArg = (createComponent("") == null);
+
+ var r = createComponent("createComponentData.qml");
+ relativeUrl = r.url;
+
+ var a = createComponent("http://www.example.com/test.qml");
+ absoluteUrl = a.url;
+ }
+}
diff --git a/tests/auto/declarative/qmlqt/data/createComponentData.qml b/tests/auto/declarative/qmlqt/data/createComponentData.qml
new file mode 100644
index 0000000..a5e99a0
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/createComponentData.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+ property int test: 1913
+}
diff --git a/tests/auto/declarative/qmlqt/data/createQmlObject.qml b/tests/auto/declarative/qmlqt/data/createQmlObject.qml
new file mode 100644
index 0000000..9150782
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/createQmlObject.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Item {
+ id: root
+
+ property bool incorrectArgCount1: false
+ property bool incorrectArgCount2: false
+ property bool emptyArg: false
+ property bool noParent: false
+ property bool notReady: false
+ property bool runtimeError: false
+ property bool errors: false
+
+ property bool success: false
+
+ Component.onCompleted: {
+ // errors
+ incorrectArgCount1 = (createQmlObject() == null);
+ incorrectArgCount2 = (createQmlObject("import Qt 4.6\nQtObject{}", root, "main.qml", 10) == null);
+ emptyArg = (createQmlObject("", root) == null);
+ errors = (createQmlObject("import Qt 4.6\nQtObject{\nproperty int test: 13\nproperty int test: 13\n}", root, "main.qml") == null);
+ noParent = (createQmlObject("import Qt 4.6\nQtObject{\nproperty int test: 13}", 0) == null);
+ notReady = (createQmlObject("import Qt 4.6\nQtObject{\nBlah{}\n}", root, "http://www.example.com/main.qml") == null);
+ runtimeError = (createQmlObject("import Qt 4.6\nQtObject{property int test\nonTestChanged: QtObject{}\n}", root) == null);
+
+ var o = createQmlObject("import Qt 4.6\nQtObject{\nproperty int test: 13\n}", root);
+ success = (o.test == 13);
+
+ createQmlObject("import Qt 4.6\nItem {}\n", root);
+ }
+}
diff --git a/tests/auto/declarative/qmlqt/data/darker.qml b/tests/auto/declarative/qmlqt/data/darker.qml
new file mode 100644
index 0000000..2df067e
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/darker.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ property var test1: Qt.darker(Qt.rgba(1, 0.8, 0.3))
+ property var test2: Qt.darker()
+ property var test3: Qt.darker(Qt.rgba(1, 0.8, 0.3), 10)
+ property var test4: Qt.darker("red");
+ property var test5: Qt.darker("perfectred"); // Non-existant color
+ property var test6: Qt.darker(10);
+}
+
diff --git a/tests/auto/declarative/qmlqt/data/enums.qml b/tests/auto/declarative/qmlqt/data/enums.qml
new file mode 100644
index 0000000..1efa6f5
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/enums.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ property int test1: Qt.Key_Escape
+ property int test2: Qt.DescendingOrder
+ property int test3: Qt.ElideMiddle
+ property int test4: Qt.AlignRight
+}
+
diff --git a/tests/auto/declarative/qmlqt/data/hsla.qml b/tests/auto/declarative/qmlqt/data/hsla.qml
new file mode 100644
index 0000000..df51ccd
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/hsla.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ property color test1: Qt.hsla(1, 0, 0, 0.8);
+ property color test2: Qt.hsla(1, 0.5, 0.3);
+ property color test3: Qt.hsla(1, 1);
+ property color test4: Qt.hsla(1, 1, 1, 1, 1);
+ property color test5: Qt.hsla(1.2, 1, 1);
+ property color test6: Qt.hsla(-0.1, 1, 1);
+}
+
diff --git a/tests/auto/declarative/qmlqt/data/lighter.qml b/tests/auto/declarative/qmlqt/data/lighter.qml
new file mode 100644
index 0000000..4e0c431
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/lighter.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+QtObject {
+ property var test1: Qt.lighter(Qt.rgba(1, 0.8, 0.3))
+ property var test2: Qt.lighter()
+ property var test3: Qt.lighter(Qt.rgba(1, 0.8, 0.3), 10)
+ property var test4: Qt.lighter("red");
+ property var test5: Qt.lighter("perfectred"); // Non-existant color
+ property var test6: Qt.lighter(10);
+}
diff --git a/tests/auto/declarative/qmlqt/data/md5.qml b/tests/auto/declarative/qmlqt/data/md5.qml
new file mode 100644
index 0000000..c474b71
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/md5.qml
@@ -0,0 +1,6 @@
+import Qt 4.6
+
+QtObject {
+ property string test1: Qt.md5()
+ property string test2: Qt.md5("Hello World")
+}
diff --git a/tests/auto/declarative/qmlqt/data/point.qml b/tests/auto/declarative/qmlqt/data/point.qml
new file mode 100644
index 0000000..c383beb
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/point.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ property var test1: Qt.point(19, 34);
+ property var test2: Qt.point(-3, 109.2);
+ property var test3: Qt.point(-3);
+ property var test4: Qt.point(-3, 109.2, 1);
+}
+
diff --git a/tests/auto/declarative/qmlqt/data/rect.qml b/tests/auto/declarative/qmlqt/data/rect.qml
new file mode 100644
index 0000000..82b6428
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/rect.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ property var test1: Qt.rect(10, 13, 100, 109)
+ property var test2: Qt.rect(-10, 13, 100, 109.6)
+ property var test3: Qt.rect(10, 13);
+ property var test4: Qt.rect(10, 13, 100, 109, 10)
+ property var test5: Qt.rect(10, 13, 100, -109)
+}
diff --git a/tests/auto/declarative/qmlqt/data/rgba.qml b/tests/auto/declarative/qmlqt/data/rgba.qml
new file mode 100644
index 0000000..6dd6565
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/rgba.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+QtObject {
+ property color test1: Qt.rgba(1, 0, 0, 0.8);
+ property color test2: Qt.rgba(1, 0.5, 0.3);
+ property color test3: Qt.rgba(1, 1);
+ property color test4: Qt.rgba(1, 1, 1, 1, 1);
+ property color test5: Qt.rgba(1.2, 1, 1);
+ property color test6: Qt.rgba(-0.1, 1, 1);
+}
diff --git a/tests/auto/declarative/qmlqt/data/size.qml b/tests/auto/declarative/qmlqt/data/size.qml
new file mode 100644
index 0000000..05b0317
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/size.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+QtObject {
+ property var test1: Qt.size(19, 34);
+ property var test2: Qt.size(3, 109.2);
+ property var test3: Qt.size(-3, 10);
+ property var test4: Qt.size(3);
+ property var test5: Qt.size(3, 109.2, 1);
+}
+
+
diff --git a/tests/auto/declarative/qmlqt/data/tint.qml b/tests/auto/declarative/qmlqt/data/tint.qml
new file mode 100644
index 0000000..da8afe2
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/tint.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+
+QtObject {
+ property color test1: Qt.tint("red", "blue");
+ property color test2: Qt.tint(Qt.rgba(1, 0, 0), Qt.rgba(0, 0, 0, 0));
+ property color test3: Qt.tint("red", Qt.rgba(0, 0, 1, 0.5)); // XXX - what should this be?
+ property color test4: Qt.tint("red", Qt.rgba(0, 0, 1, 0.5), 10);
+ property color test5: Qt.tint("red")
+}
diff --git a/tests/auto/declarative/qmlqt/data/vector.qml b/tests/auto/declarative/qmlqt/data/vector.qml
new file mode 100644
index 0000000..a471c7a
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/vector.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+QtObject {
+ property var test1: Qt.vector3d(1, 0, 0.9);
+ property var test2: Qt.vector3d(102, -10, -982.1);
+ property var test3: Qt.vector3d(102, -10);
+ property var test4: Qt.vector3d(102, -10, -982.1, 10);
+}
diff --git a/tests/auto/declarative/qmlqt/qmlqt.pro b/tests/auto/declarative/qmlqt/qmlqt.pro
new file mode 100644
index 0000000..5e79ea6
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/qmlqt.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlqt.cpp
+macx:CONFIG -= app_bundle
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
diff --git a/tests/auto/declarative/qmlqt/tst_qmlqt.cpp b/tests/auto/declarative/qmlqt/tst_qmlqt.cpp
new file mode 100644
index 0000000..78f39be
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/tst_qmlqt.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QDebug>
+#include <QmlEngine>
+#include <QFileInfo>
+#include <QmlComponent>
+#include <QDir>
+#include <QVector3D>
+#include <QCryptographicHash>
+#include <QmlGraphicsItem>
+
+class tst_qmlqt : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlqt() {}
+
+private slots:
+ void enums();
+ void rgba();
+ void hsla();
+ void rect();
+ void point();
+ void size();
+ void vector();
+ void lighter();
+ void darker();
+ void tint();
+ void closestAngle();
+ void playSound();
+ void openUrlExternally();
+ void md5();
+ void createComponent();
+ void createQmlObject();
+ void consoleLog();
+
+private:
+ QmlEngine engine;
+};
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
+}
+
+void tst_qmlqt::enums()
+{
+ QmlComponent component(&engine, TEST_FILE("enums.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), (int)Qt::Key_Escape);
+ QCOMPARE(object->property("test2").toInt(), (int)Qt::DescendingOrder);
+ QCOMPARE(object->property("test3").toInt(), (int)Qt::ElideMiddle);
+ QCOMPARE(object->property("test4").toInt(), (int)Qt::AlignRight);
+
+ delete object;
+}
+
+void tst_qmlqt::rgba()
+{
+ QmlComponent component(&engine, TEST_FILE("rgba.qml"));
+
+ QString warning1 = component.url().toString() + ":6: Unable to assign null to QColor";
+ QString warning2 = component.url().toString() + ":7: Unable to assign null to QColor";
+ QString warning3 = component.url().toString() + ":8: Unable to assign null to QColor";
+ QString warning4 = component.url().toString() + ":9: Unable to assign null to QColor";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning4));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+
+ QCOMPARE(qvariant_cast<QColor>(object->property("test1")), QColor::fromRgbF(1, 0, 0, 0.8));
+ QCOMPARE(qvariant_cast<QColor>(object->property("test2")), QColor::fromRgbF(1, 0.5, 0.3, 1));
+ QCOMPARE(qvariant_cast<QColor>(object->property("test3")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test4")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test5")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test6")), QColor());
+
+ delete object;
+}
+
+void tst_qmlqt::hsla()
+{
+ QmlComponent component(&engine, TEST_FILE("hsla.qml"));
+
+ QString warning1 = component.url().toString() + ":6: Unable to assign null to QColor";
+ QString warning2 = component.url().toString() + ":7: Unable to assign null to QColor";
+ QString warning3 = component.url().toString() + ":8: Unable to assign null to QColor";
+ QString warning4 = component.url().toString() + ":9: Unable to assign null to QColor";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning4));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QColor>(object->property("test1")), QColor::fromHslF(1, 0, 0, 0.8));
+ QCOMPARE(qvariant_cast<QColor>(object->property("test2")), QColor::fromHslF(1, 0.5, 0.3, 1));
+ QCOMPARE(qvariant_cast<QColor>(object->property("test3")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test4")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test5")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test6")), QColor());
+
+ delete object;
+}
+
+void tst_qmlqt::rect()
+{
+ QmlComponent component(&engine, TEST_FILE("rect.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QRectF>(object->property("test1")), QRectF(10, 13, 100, 109));
+ QCOMPARE(qvariant_cast<QRectF>(object->property("test2")), QRectF(-10, 13, 100, 109.6));
+ QCOMPARE(qvariant_cast<QRectF>(object->property("test3")), QRectF());
+ QCOMPARE(qvariant_cast<QRectF>(object->property("test4")), QRectF());
+ QCOMPARE(qvariant_cast<QRectF>(object->property("test5")), QRectF());
+
+ delete object;
+}
+
+void tst_qmlqt::point()
+{
+ QmlComponent component(&engine, TEST_FILE("point.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QPointF>(object->property("test1")), QPointF(19, 34));
+ QCOMPARE(qvariant_cast<QPointF>(object->property("test2")), QPointF(-3, 109.2));
+ QCOMPARE(qvariant_cast<QPointF>(object->property("test3")), QPointF());
+ QCOMPARE(qvariant_cast<QPointF>(object->property("test4")), QPointF());
+
+ delete object;
+}
+
+void tst_qmlqt::size()
+{
+ QmlComponent component(&engine, TEST_FILE("size.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QSizeF>(object->property("test1")), QSizeF(19, 34));
+ QCOMPARE(qvariant_cast<QSizeF>(object->property("test2")), QSizeF(3, 109.2));
+ QCOMPARE(qvariant_cast<QSizeF>(object->property("test3")), QSizeF(-3, 10));
+ QCOMPARE(qvariant_cast<QSizeF>(object->property("test4")), QSizeF());
+ QCOMPARE(qvariant_cast<QSizeF>(object->property("test5")), QSizeF());
+
+ delete object;
+}
+
+void tst_qmlqt::vector()
+{
+ QmlComponent component(&engine, TEST_FILE("vector.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QVector3D>(object->property("test1")), QVector3D(1, 0, 0.9));
+ QCOMPARE(qvariant_cast<QVector3D>(object->property("test2")), QVector3D(102, -10, -982.1));
+ QCOMPARE(qvariant_cast<QVector3D>(object->property("test3")), QVector3D());
+ QCOMPARE(qvariant_cast<QVector3D>(object->property("test4")), QVector3D());
+
+ delete object;
+}
+
+void tst_qmlqt::lighter()
+{
+ QmlComponent component(&engine, TEST_FILE("lighter.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QColor>(object->property("test1")), QColor::fromRgbF(1, 0.8, 0.3).lighter());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test2")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test3")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test4")), QColor("red").lighter());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test5")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test6")), QColor());
+
+ delete object;
+}
+
+void tst_qmlqt::darker()
+{
+ QmlComponent component(&engine, TEST_FILE("darker.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QColor>(object->property("test1")), QColor::fromRgbF(1, 0.8, 0.3).darker());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test2")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test3")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test4")), QColor("red").darker());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test5")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test6")), QColor());
+
+ delete object;
+}
+
+void tst_qmlqt::tint()
+{
+ QmlComponent component(&engine, TEST_FILE("tint.qml"));
+
+ QString warning1 = component.url().toString() + ":7: Unable to assign null to QColor";
+ QString warning2 = component.url().toString() + ":8: Unable to assign null to QColor";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QColor>(object->property("test1")), QColor::fromRgbF(0, 0, 1));
+ QCOMPARE(qvariant_cast<QColor>(object->property("test2")), QColor::fromRgbF(1, 0, 0));
+ QEXPECT_FAIL("", "QT-2424",Continue);
+ QCOMPARE(qvariant_cast<QColor>(object->property("test3")), QColor::fromRgbF(1, 0, 0));
+ QCOMPARE(qvariant_cast<QColor>(object->property("test4")), QColor());
+ QCOMPARE(qvariant_cast<QColor>(object->property("test5")), QColor());
+
+ delete object;
+}
+
+void tst_qmlqt::closestAngle()
+{
+ QmlComponent component(&engine, TEST_FILE("closestangle.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<qreal>(object->property("testSame")), 1.0);
+ QCOMPARE(qvariant_cast<qreal>(object->property("testLess")), 1.0);
+ QCOMPARE(qvariant_cast<qreal>(object->property("testMore")), 1.0);
+ QCOMPARE(qvariant_cast<qreal>(object->property("testFail")), 0.0);
+ QCOMPARE(qvariant_cast<qreal>(object->property("test5")), 1.0);
+ QCOMPARE(qvariant_cast<qreal>(object->property("test6")), 1.11);
+ QCOMPARE(qvariant_cast<qreal>(object->property("test7")), 1.11);
+
+ delete object;
+}
+
+void tst_qmlqt::playSound()
+{
+ QEXPECT_FAIL("", "How do we test this?", Abort);
+ QVERIFY(false);
+}
+
+void tst_qmlqt::openUrlExternally()
+{
+ QEXPECT_FAIL("", "How do we test this?", Abort);
+ QVERIFY(false);
+}
+
+void tst_qmlqt::md5()
+{
+ QmlComponent component(&engine, TEST_FILE("md5.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toString(), QLatin1String(QCryptographicHash::hash(QByteArray(), QCryptographicHash::Md5).toHex()));
+ QCOMPARE(object->property("test2").toString(), QLatin1String(QCryptographicHash::hash("Hello World", QCryptographicHash::Md5).toHex()));
+
+ delete object;
+}
+
+void tst_qmlqt::createComponent()
+{
+ QmlComponent component(&engine, TEST_FILE("createComponent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("incorrectArgCount1").toBool(), true);
+ QCOMPARE(object->property("incorrectArgCount2").toBool(), true);
+ QCOMPARE(object->property("emptyArg").toBool(), true);
+
+ QCOMPARE(object->property("absoluteUrl").toString(), QString("http://www.example.com/test.qml"));
+ QCOMPARE(object->property("relativeUrl").toString(), TEST_FILE("createComponentData.qml").toString());
+
+ delete object;
+}
+
+void tst_qmlqt::createQmlObject()
+{
+ QmlComponent component(&engine, TEST_FILE("createQmlObject.qml"));
+
+ QString warning1 = "QmlEngine::createQmlObject():";
+ QString warning2 = " " + TEST_FILE("main.qml").toString() + ":4:1: Duplicate property name";
+ QString warning3 = "QmlEngine::createQmlObject(): Component is not ready";
+ QString warning4 = "QmlEngine::createQmlObject():";
+ QString warning5 = " " + TEST_FILE("inline").toString() + ":3: Cannot assign object type QObject with no default method";
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning4));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning5));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("incorrectArgCount1").toBool(), true);
+ QCOMPARE(object->property("incorrectArgCount2").toBool(), true);
+ QCOMPARE(object->property("emptyArg").toBool(), true);
+ QCOMPARE(object->property("errors").toBool(), true);
+ QCOMPARE(object->property("noParent").toBool(), true);
+ QCOMPARE(object->property("notReady").toBool(), true);
+ QCOMPARE(object->property("runtimeError").toBool(), true);
+ QCOMPARE(object->property("success").toBool(), true);
+
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(object);
+ QVERIFY(item != 0);
+ QVERIFY(item->childItems().count() == 1);
+
+ delete object;
+}
+
+void tst_qmlqt::consoleLog()
+{
+ QTest::ignoreMessage(QtDebugMsg, "completed ok");
+ QTest::ignoreMessage(QtDebugMsg, "completed ok");
+ QmlComponent component(&engine, TEST_FILE("consoleLog.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ delete object;
+}
+
+QTEST_MAIN(tst_qmlqt)
+
+#include "tst_qmlqt.moc"
diff --git a/tests/auto/declarative/qmlspringfollow/data/springfollow1.qml b/tests/auto/declarative/qmlspringfollow/data/springfollow1.qml
new file mode 100644
index 0000000..959d206
--- /dev/null
+++ b/tests/auto/declarative/qmlspringfollow/data/springfollow1.qml
@@ -0,0 +1,4 @@
+import Qt 4.6
+
+SpringFollow {
+}
diff --git a/tests/auto/declarative/qmlspringfollow/data/springfollow2.qml b/tests/auto/declarative/qmlspringfollow/data/springfollow2.qml
new file mode 100644
index 0000000..7c81fb5
--- /dev/null
+++ b/tests/auto/declarative/qmlspringfollow/data/springfollow2.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+SpringFollow {
+ source: 1.44; velocity: 0.9
+ spring: 1.0; damping: 0.5
+ epsilon: 0.25; modulus: 360.0
+ mass: 2.0; enabled: true
+}
diff --git a/tests/auto/declarative/qmlspringfollow/data/springfollow3.qml b/tests/auto/declarative/qmlspringfollow/data/springfollow3.qml
new file mode 100644
index 0000000..6fec55b
--- /dev/null
+++ b/tests/auto/declarative/qmlspringfollow/data/springfollow3.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+SpringFollow {
+ source: 1.44; velocity: 0.9
+ spring: 1.0; damping: 0.5
+ epsilon: 0.25; modulus: 360.0
+ mass: 2.0; enabled: false
+}
diff --git a/tests/auto/declarative/qmlspringfollow/qmlspringfollow.pro b/tests/auto/declarative/qmlspringfollow/qmlspringfollow.pro
new file mode 100644
index 0000000..ffaa97f
--- /dev/null
+++ b/tests/auto/declarative/qmlspringfollow/qmlspringfollow.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlspringfollow.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlspringfollow/tst_qmlspringfollow.cpp b/tests/auto/declarative/qmlspringfollow/tst_qmlspringfollow.cpp
new file mode 100644
index 0000000..f17b5d4
--- /dev/null
+++ b/tests/auto/declarative/qmlspringfollow/tst_qmlspringfollow.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlspringfollow_p.h>
+#include <private/qmlvaluetype_p.h>
+#include "../../../shared/util.h"
+
+class tst_qmlspringfollow : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlspringfollow();
+
+private slots:
+ void defaultValues();
+ void values();
+ void disabled();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlspringfollow::tst_qmlspringfollow()
+{
+}
+
+void tst_qmlspringfollow::defaultValues()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/springfollow1.qml"));
+ QmlSpringFollow *obj = qobject_cast<QmlSpringFollow*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->sourceValue(), 0.);
+ QCOMPARE(obj->velocity(), 0.);
+ QCOMPARE(obj->spring(), 0.);
+ QCOMPARE(obj->damping(), 0.);
+ QCOMPARE(obj->epsilon(), 0.01);
+ QCOMPARE(obj->modulus(), 0.);
+ QCOMPARE(obj->value(), 0.);
+ QCOMPARE(obj->mass(), 1.);
+ QCOMPARE(obj->enabled(), true);
+ QCOMPARE(obj->inSync(), true);
+
+ delete obj;
+}
+
+void tst_qmlspringfollow::values()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/springfollow2.qml"));
+ QmlSpringFollow *obj = qobject_cast<QmlSpringFollow*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->sourceValue(), 1.44);
+ QCOMPARE(obj->velocity(), 0.9);
+ QCOMPARE(obj->spring(), 1.0);
+ QCOMPARE(obj->damping(), 0.5);
+ QCOMPARE(obj->epsilon(), 0.25);
+ QCOMPARE(obj->modulus(), 360.0);
+ QCOMPARE(obj->mass(), 2.0);
+ QCOMPARE(obj->enabled(), true);
+
+ QTRY_COMPARE(obj->value(), 1.44);
+ QTRY_COMPARE(obj->inSync(), true);
+
+ delete obj;
+}
+
+void tst_qmlspringfollow::disabled()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/springfollow3.qml"));
+ QmlSpringFollow *obj = qobject_cast<QmlSpringFollow*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->sourceValue(), 1.44);
+ QCOMPARE(obj->velocity(), 0.9);
+ QCOMPARE(obj->spring(), 1.0);
+ QCOMPARE(obj->damping(), 0.5);
+ QCOMPARE(obj->epsilon(), 0.25);
+ QCOMPARE(obj->modulus(), 360.0);
+ QCOMPARE(obj->mass(), 2.0);
+ QCOMPARE(obj->enabled(), false);
+
+ QCOMPARE(obj->value(), 0.0);
+ QCOMPARE(obj->inSync(), false);
+
+ delete obj;
+}
+
+QTEST_MAIN(tst_qmlspringfollow)
+
+#include "tst_qmlspringfollow.moc"
diff --git a/tests/auto/declarative/qmlstates/data/ExtendedRectangle.qml b/tests/auto/declarative/qmlstates/data/ExtendedRectangle.qml
new file mode 100644
index 0000000..8d64663
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/ExtendedRectangle.qml
@@ -0,0 +1,19 @@
+import Qt 4.6
+Rectangle {
+ id: extendedRect
+ objectName: "extendedRect"
+ property color extendedColor: "orange"
+
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "green"
+ PropertyChanges {
+ target: rect
+ onDidSomething: {
+ extendedRect.color = "green"
+ extendedColor = "green"
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/anchorChanges.qml b/tests/auto/declarative/qmlstates/data/anchorChanges.qml
new file mode 100644
index 0000000..7dce889
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/anchorChanges.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+ width: 200; height: 200
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ width: 50; height: 50
+ color: "green";
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ }
+ states: State {
+ name: "right"
+ AnchorChanges {
+ id: ancCh
+ target: myRect;
+ reset: "left"
+ right: container.right
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/anchorChanges2.qml b/tests/auto/declarative/qmlstates/data/anchorChanges2.qml
new file mode 100644
index 0000000..545345e
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/anchorChanges2.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 200
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ width: 50; height: 50
+ color: "green";
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ }
+ states: State {
+ name: "right"
+ AnchorChanges {
+ target: myRect;
+ reset: "left"
+ right: parent.right
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/anchorChanges3.qml b/tests/auto/declarative/qmlstates/data/anchorChanges3.qml
new file mode 100644
index 0000000..9d5b317
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/anchorChanges3.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+ width: 200; height: 200
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ color: "green";
+ anchors.left: parent.left
+ anchors.right: rightGuideline.left
+ anchors.top: topGuideline.top
+ anchors.bottom: container.bottom
+ }
+ Item { objectName: "LeftGuideline"; id: leftGuideline; x: 10 }
+ Item { id: rightGuideline; x: 150 }
+ Item { id: topGuideline; y: 10 }
+ Item { objectName: "BottomGuideline"; id: bottomGuideline; y: 150 }
+ states: State {
+ name: "reanchored"
+ AnchorChanges {
+ target: myRect;
+ left: leftGuideline.left
+ right: container.right
+ top: container.top
+ bottom: bottomGuideline.bottom
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/anchorChanges4.qml b/tests/auto/declarative/qmlstates/data/anchorChanges4.qml
new file mode 100644
index 0000000..f128989
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/anchorChanges4.qml
@@ -0,0 +1,22 @@
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 200
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ color: "green";
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ Item { objectName: "LeftGuideline"; id: leftGuideline; x: 10 }
+ Item { objectName: "BottomGuideline"; id: bottomGuideline; y: 150 }
+ states: State {
+ name: "reanchored"
+ AnchorChanges {
+ target: myRect;
+ horizontalCenter: bottomGuideline.horizontalCenter
+ verticalCenter: leftGuideline.verticalCenter
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/anchorChanges5.qml b/tests/auto/declarative/qmlstates/data/anchorChanges5.qml
new file mode 100644
index 0000000..4e6d34b
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/anchorChanges5.qml
@@ -0,0 +1,22 @@
+import Qt 4.6
+
+Rectangle {
+ width: 200; height: 200
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ color: "green";
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.baseline: parent.baseline
+ }
+ Item { objectName: "LeftGuideline"; id: leftGuideline; x: 10 }
+ Item { objectName: "BottomGuideline"; id: bottomGuideline; y: 150 }
+ states: State {
+ name: "reanchored"
+ AnchorChanges {
+ target: myRect;
+ horizontalCenter: bottomGuideline.horizontalCenter
+ baseline: leftGuideline.baseline
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/autoStateAtStartupRestoreBug.qml b/tests/auto/declarative/qmlstates/data/autoStateAtStartupRestoreBug.qml
new file mode 100644
index 0000000..693a5c5
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/autoStateAtStartupRestoreBug.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Item {
+ id: root
+ property int input: 1
+ property int test: 9
+
+ states: [
+ State {
+ name: "portrait"
+ when: root.input == 1
+ PropertyChanges {
+ target: root
+ test: 3
+ }
+ }
+ ]
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicBinding.qml b/tests/auto/declarative/qmlstates/data/basicBinding.qml
new file mode 100644
index 0000000..6528113
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicBinding.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+
+ property color sourceColor: "blue"
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: sourceColor }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicBinding2.qml b/tests/auto/declarative/qmlstates/data/basicBinding2.qml
new file mode 100644
index 0000000..2e7b4cf
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicBinding2.qml
@@ -0,0 +1,12 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+
+ property color sourceColor: "red"
+ width: 100; height: 100
+ color: sourceColor
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue" }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicBinding3.qml b/tests/auto/declarative/qmlstates/data/basicBinding3.qml
new file mode 100644
index 0000000..a3c47d9
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicBinding3.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+
+ property color sourceColor: "red"
+ property color sourceColor2: "blue"
+ width: 100; height: 100
+ color: sourceColor
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: sourceColor2 }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicBinding4.qml b/tests/auto/declarative/qmlstates/data/basicBinding4.qml
new file mode 100644
index 0000000..1f52d0e
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicBinding4.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+
+ property color sourceColor: "blue"
+ width: 100; height: 100
+ color: "red"
+ states: [
+ State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: sourceColor }
+ },
+ State {
+ name: "green"
+ PropertyChanges { target: myRectangle; color: "green" }
+ }]
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicChanges.qml b/tests/auto/declarative/qmlstates/data/basicChanges.qml
new file mode 100644
index 0000000..88ea256
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicChanges.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue" }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicChanges2.qml b/tests/auto/declarative/qmlstates/data/basicChanges2.qml
new file mode 100644
index 0000000..4dd293f
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicChanges2.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: [
+ State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue" }
+ },
+ State {
+ name: "green"
+ PropertyChanges { target: myRectangle; color: "green" }
+ }]
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicChanges3.qml b/tests/auto/declarative/qmlstates/data/basicChanges3.qml
new file mode 100644
index 0000000..62ab1d5
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicChanges3.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: [
+ State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue" }
+ },
+ State {
+ name: "bordered"
+ PropertyChanges { target: myRectangle; border.width: 2 }
+ }]
+}
diff --git a/tests/auto/declarative/qmlstates/data/basicExtension.qml b/tests/auto/declarative/qmlstates/data/basicExtension.qml
new file mode 100644
index 0000000..1836f8a
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/basicExtension.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: [
+ State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue" }
+ },
+ State {
+ name: "bordered"
+ extend: "blue"
+ PropertyChanges { target: myRectangle; border.width: 2 }
+ }]
+}
diff --git a/tests/auto/declarative/qmlstates/data/deleting.qml b/tests/auto/declarative/qmlstates/data/deleting.qml
new file mode 100644
index 0000000..3da0b12
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/deleting.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue"; objectName: "pc1" }
+ PropertyChanges { target: myRectangle; radius: 5; objectName: "pc2" }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/deletingState.qml b/tests/auto/declarative/qmlstates/data/deletingState.qml
new file mode 100644
index 0000000..a5e8ed3
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/deletingState.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ StateGroup {
+ id: stateGroup
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue" }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/explicit.qml b/tests/auto/declarative/qmlstates/data/explicit.qml
new file mode 100644
index 0000000..7543f84
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/explicit.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ property color sourceColor: "blue"
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ PropertyChanges {
+ objectName: "changes"
+ target: myRectangle; explicit: true
+ color: sourceColor
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/fakeExtension.qml b/tests/auto/declarative/qmlstates/data/fakeExtension.qml
new file mode 100644
index 0000000..c7975e1
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/fakeExtension.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: [
+ State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; color: "blue" }
+ },
+ State {
+ name: "green"
+ extend: "blue"
+ PropertyChanges { target: myRectangle; color: "green" }
+ }]
+}
diff --git a/tests/auto/declarative/qmlstates/data/illegalTempState.qml b/tests/auto/declarative/qmlstates/data/illegalTempState.qml
new file mode 100644
index 0000000..2702be4
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/illegalTempState.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+Rectangle {
+ id: card
+ width: 100; height: 100
+
+ states: [
+ State {
+ name: "placed"
+ PropertyChanges { target: card; state: "idle" }
+ },
+ State {
+ name: "idle"
+ }
+ ]
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: card.state = "placed"
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/legalTempState.qml b/tests/auto/declarative/qmlstates/data/legalTempState.qml
new file mode 100644
index 0000000..54c97b9
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/legalTempState.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+Rectangle {
+ id: card
+ width: 100; height: 100
+
+ states: [
+ State {
+ name: "placed"
+ onCompleted: card.state = "idle"
+ StateChangeScript { script: console.log("entering placed") }
+ },
+ State {
+ name: "idle"
+ StateChangeScript { script: console.log("entering idle") }
+ }
+ ]
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: card.state = "placed"
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/nonExistantProp.qml b/tests/auto/declarative/qmlstates/data/nonExistantProp.qml
new file mode 100644
index 0000000..a5dd86a
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/nonExistantProp.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; colr: "blue" }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/parentChange.qml b/tests/auto/declarative/qmlstates/data/parentChange.qml
new file mode 100644
index 0000000..087da6b
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/parentChange.qml
@@ -0,0 +1,37 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 400
+ Item {
+ x: 10; y: 10
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ x: 5
+ width: 100; height: 100
+ color: "red"
+ }
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ Item {
+ x: -100; y: -50
+ Item {
+ id: newParent
+ objectName: "NewParent"
+ x: 248; y: 360
+ }
+ }
+
+ states: State {
+ name: "reparented"
+ when: clickable.pressed
+ ParentChange {
+ target: myRect
+ parent: newParent
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/parentChange2.qml b/tests/auto/declarative/qmlstates/data/parentChange2.qml
new file mode 100644
index 0000000..f0b00f5
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/parentChange2.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Rectangle {
+ id: newParent
+ width: 400; height: 400
+ Item {
+ scale: .5
+ rotation: 15
+ x: 10; y: 10
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ x: 5
+ width: 100; height: 100
+ color: "red"
+ }
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ states: State {
+ name: "reparented"
+ when: clickable.pressed
+ ParentChange {
+ target: myRect
+ parent: newParent
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/parentChange3.qml b/tests/auto/declarative/qmlstates/data/parentChange3.qml
new file mode 100644
index 0000000..2aa507c
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/parentChange3.qml
@@ -0,0 +1,42 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 400
+ Item {
+ scale: .5
+ rotation: 15
+ transformOrigin: "Center"
+ x: 10; y: 10
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ x: 5
+ width: 100; height: 100
+ transformOrigin: "BottomLeft"
+ color: "red"
+ }
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ Item {
+ x: 200; y: 200
+ rotation: 52;
+ scale: 2
+ Item {
+ id: newParent
+ x: 100; y: 100
+ }
+ }
+
+ states: State {
+ name: "reparented"
+ when: clickable.pressed
+ ParentChange {
+ target: myRect
+ parent: newParent
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/parentChange4.qml b/tests/auto/declarative/qmlstates/data/parentChange4.qml
new file mode 100644
index 0000000..d00274b
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/parentChange4.qml
@@ -0,0 +1,30 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 400
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ x: 5; y: 5
+ width: 100; height: 100
+ color: "red"
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ Item {
+ id: newParent
+ transform: Scale { xScale: .5; yScale: .7}
+ }
+
+ states: State {
+ name: "reparented"
+ when: clickable.pressed
+ ParentChange {
+ target: myRect
+ parent: newParent
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/parentChange5.qml b/tests/auto/declarative/qmlstates/data/parentChange5.qml
new file mode 100644
index 0000000..f75e2a3
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/parentChange5.qml
@@ -0,0 +1,30 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 400
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ x: 5; y: 5
+ width: 100; height: 100
+ color: "red"
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ Item {
+ id: newParent
+ transform: Rotation { angle: 30; axis { x: 0; y: 1; z: 0 } }
+ }
+
+ states: State {
+ name: "reparented"
+ when: clickable.pressed
+ ParentChange {
+ target: myRect
+ parent: newParent
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/propertyErrors.qml b/tests/auto/declarative/qmlstates/data/propertyErrors.qml
new file mode 100644
index 0000000..080e833
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/propertyErrors.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ PropertyChanges { target: myRectangle; colr: "blue"; wantsFocus: true }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/restoreEntryValues.qml b/tests/auto/declarative/qmlstates/data/restoreEntryValues.qml
new file mode 100644
index 0000000..088c608
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/restoreEntryValues.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ PropertyChanges {
+ target: myRectangle
+ restoreEntryValues: false
+ color: "blue"
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/script.qml b/tests/auto/declarative/qmlstates/data/script.qml
new file mode 100644
index 0000000..3c5f33e
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/script.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+Rectangle {
+ id: myRectangle
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "blue"
+ StateChangeScript { script: myRectangle.color = "blue"; }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/signalOverride.qml b/tests/auto/declarative/qmlstates/data/signalOverride.qml
new file mode 100644
index 0000000..5ba1566
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/signalOverride.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+import Qt.test 1.0
+
+MyRectangle {
+ id: rect
+
+ onDidSomething: color = "blue"
+
+ width: 100; height: 100
+ color: "red"
+ states: State {
+ name: "green"
+ PropertyChanges {
+ target: rect
+ onDidSomething: color = "green"
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/data/signalOverride2.qml b/tests/auto/declarative/qmlstates/data/signalOverride2.qml
new file mode 100644
index 0000000..527e165
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/signalOverride2.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+import Qt.test 1.0
+
+MyRectangle {
+ id: rect
+ onDidSomething: color = "blue"
+ width: 100; height: 100
+ ExtendedRectangle {}
+}
diff --git a/tests/auto/declarative/qmlstates/data/signalOverrideCrash.qml b/tests/auto/declarative/qmlstates/data/signalOverrideCrash.qml
new file mode 100644
index 0000000..702fa86
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/data/signalOverrideCrash.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+import Qt.test 1.0
+
+MyRectangle {
+ id: rect
+
+ width: 100; height: 100
+ states: State {
+ name: "overridden"
+ PropertyChanges {
+ target: rect
+ onDidSomething: rect.state = ""
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlstates/qmlstates.pro b/tests/auto/declarative/qmlstates/qmlstates.pro
new file mode 100644
index 0000000..538734a
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/qmlstates.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlstates.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlstates/tst_qmlstates.cpp b/tests/auto/declarative/qmlstates/tst_qmlstates.cpp
new file mode 100644
index 0000000..fc348a5
--- /dev/null
+++ b/tests/auto/declarative/qmlstates/tst_qmlstates.cpp
@@ -0,0 +1,887 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicsanchors_p_p.h>
+#include <private/qmlgraphicsrectangle_p.h>
+#include <private/qmlpropertychanges_p.h>
+#include <private/qmlstategroup_p.h>
+
+class tst_states : public QObject
+{
+ Q_OBJECT
+public:
+ tst_states() {}
+
+private:
+ static QByteArray fullDataPath(const QString &path);
+
+private slots:
+ void basicChanges();
+ void basicExtension();
+ void basicBinding();
+ void signalOverride();
+ void signalOverrideCrash();
+ void parentChange();
+ void parentChangeErrors();
+ void anchorChanges();
+ void anchorChanges2();
+ void anchorChanges3();
+ void anchorChanges4();
+ void anchorChanges5();
+ void script();
+ void restoreEntryValues();
+ void explicitChanges();
+ void propertyErrors();
+ void incorrectRestoreBug();
+ void autoStateAtStartupRestoreBug();
+ void deletingChange();
+ void deletingState();
+ void tempState();
+ void illegalTempState();
+ void nonExistantProperty();
+};
+
+QByteArray tst_states::fullDataPath(const QString &path)
+{
+ return QUrl::fromLocalFile(SRCDIR + path).toString().toUtf8();
+}
+
+void tst_states::basicChanges()
+{
+ QmlEngine engine;
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicChanges.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicChanges2.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicChanges3.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1);
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1);
+
+ rect->setState("bordered");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),2);
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1);
+ //### we should be checking that this is an implicit rather than explicit 1 (which currently fails)
+
+ rect->setState("bordered");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),2);
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1);
+
+ }
+}
+
+void tst_states::basicExtension()
+{
+ QmlEngine engine;
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicExtension.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1);
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1);
+
+ rect->setState("bordered");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),2);
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1);
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1);
+
+ rect->setState("bordered");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),2);
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1);
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/fakeExtension.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+ }
+}
+
+void tst_states::basicBinding()
+{
+ QmlEngine engine;
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicBinding.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("yellow"));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicBinding2.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("green"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("yellow"));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicBinding3.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("red"));
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor2", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor2", QColor("green"));
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicBinding4.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+
+ rect->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+ rect->setProperty("sourceColor", QColor("purple"));
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("purple"));
+
+ rect->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ }
+}
+
+class MyRect : public QmlGraphicsRectangle
+{
+ Q_OBJECT
+public:
+ MyRect() {}
+ void doSomething() { emit didSomething(); }
+Q_SIGNALS:
+ void didSomething();
+};
+
+QML_DECLARE_TYPE(MyRect)
+QML_DEFINE_TYPE(Qt.test, 1, 0, MyRectangle,MyRect);
+
+void tst_states::signalOverride()
+{
+ QmlEngine engine;
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/signalOverride.qml");
+ MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("green");
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("green"));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/signalOverride2.qml");
+ MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("white"));
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("extendedRect"));
+
+ innerRect->setState("green");
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(innerRect->color(),QColor("green"));
+ QCOMPARE(innerRect->property("extendedColor").value<QColor>(),QColor("green"));
+ }
+}
+
+void tst_states::signalOverrideCrash()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/signalOverrideCrash.qml");
+ MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ rect->setState("overridden");
+ rect->doSomething();
+}
+
+void tst_states::parentChange()
+{
+ QmlEngine engine;
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/parentChange.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ qmlExecuteDeferred(rect->states()->at(0));
+ QmlParentChange *pChange = qobject_cast<QmlParentChange*>(rect->states()->at(0)->changes()->at(0));
+ QVERIFY(pChange != 0);
+ QmlGraphicsItem *nParent = qobject_cast<QmlGraphicsItem*>(rect->findChild<QmlGraphicsItem*>("NewParent"));
+ QVERIFY(nParent != 0);
+
+ QCOMPARE(pChange->parent(), nParent);
+
+ rect->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(-133));
+ QCOMPARE(innerRect->y(), qreal(-300));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/parentChange2.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ rect->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(15));
+ QCOMPARE(innerRect->scale(), qreal(.5));
+ QEXPECT_FAIL("", "QTBUG-2919", Continue);
+ QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(12.4148145657));
+ QEXPECT_FAIL("", "QTBUG-2919", Continue);
+ QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(10.6470476128));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/parentChange3.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ rect->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(-37));
+ QCOMPARE(innerRect->scale(), qreal(.25));
+ QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-217.305));
+ QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-164.413));
+
+ rect->setState("");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(5));
+ QEXPECT_FAIL("", "QTBUG-2919", Continue);
+ QCOMPARE(innerRect->y(), qreal(0));
+ }
+}
+
+void tst_states::parentChangeErrors()
+{
+ QmlEngine engine;
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/parentChange4.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QTest::ignoreMessage(QtWarningMsg, QByteArray("QML ParentChange (" + fullDataPath("/data/parentChange4.qml") + ":25:9) Unable to preserve appearance under non-uniform scale").constData());
+ rect->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(5));
+ QCOMPARE(innerRect->y(), qreal(5));
+ }
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/parentChange5.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QTest::ignoreMessage(QtWarningMsg, QByteArray("QML ParentChange (" + fullDataPath("/data/parentChange5.qml") + ":25:9) Unable to preserve appearance under complex transform").constData());
+ rect->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(5));
+ QCOMPARE(innerRect->y(), qreal(5));
+ }
+}
+
+void tst_states::anchorChanges()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/anchorChanges.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ qmlExecuteDeferred(rect->states()->at(0));
+ QmlAnchorChanges *aChanges = qobject_cast<QmlAnchorChanges*>(rect->states()->at(0)->changes()->at(0));
+ QVERIFY(aChanges != 0);
+
+ rect->setState("right");
+ QCOMPARE(innerRect->x(), qreal(150));
+ QCOMPARE(aChanges->reset(), QString("left"));
+ QCOMPARE(aChanges->object(), innerRect);
+ QCOMPARE(aChanges->right().item, rect->right().item);
+ QCOMPARE(aChanges->right().anchorLine, rect->right().anchorLine);
+
+ rect->setState("");
+ QCOMPARE(innerRect->x(), qreal(5));
+
+ delete rect;
+}
+
+void tst_states::anchorChanges2()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/anchorChanges2.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ rect->setState("right");
+ QEXPECT_FAIL("", "QTBUG-5338", Continue);
+ QCOMPARE(innerRect->x(), qreal(150));
+
+ rect->setState("");
+ QCOMPARE(innerRect->x(), qreal(5));
+
+ delete rect;
+}
+
+void tst_states::anchorChanges3()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/anchorChanges3.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QmlGraphicsItem *leftGuideline = qobject_cast<QmlGraphicsItem*>(rect->findChild<QmlGraphicsItem*>("LeftGuideline"));
+ QVERIFY(leftGuideline != 0);
+
+ QmlGraphicsItem *bottomGuideline = qobject_cast<QmlGraphicsItem*>(rect->findChild<QmlGraphicsItem*>("BottomGuideline"));
+ QVERIFY(bottomGuideline != 0);
+
+ qmlExecuteDeferred(rect->states()->at(0));
+ QmlAnchorChanges *aChanges = qobject_cast<QmlAnchorChanges*>(rect->states()->at(0)->changes()->at(0));
+ QVERIFY(aChanges != 0);
+
+ rect->setState("reanchored");
+ QCOMPARE(aChanges->object(), innerRect);
+ QCOMPARE(aChanges->left().item, leftGuideline->left().item);
+ QCOMPARE(aChanges->left().anchorLine, leftGuideline->left().anchorLine);
+ QCOMPARE(aChanges->right().item, rect->right().item);
+ QCOMPARE(aChanges->right().anchorLine, rect->right().anchorLine);
+ QCOMPARE(aChanges->top().item, rect->top().item);
+ QCOMPARE(aChanges->top().anchorLine, rect->top().anchorLine);
+ QCOMPARE(aChanges->bottom().item, bottomGuideline->bottom().item);
+ QCOMPARE(aChanges->bottom().anchorLine, bottomGuideline->bottom().anchorLine);
+
+ QCOMPARE(innerRect->x(), qreal(10));
+ QCOMPARE(innerRect->y(), qreal(0));
+ QCOMPARE(innerRect->width(), qreal(190));
+ QCOMPARE(innerRect->height(), qreal(150));
+
+ rect->setState("");
+ QCOMPARE(innerRect->x(), qreal(0));
+ QCOMPARE(innerRect->y(), qreal(10));
+ QCOMPARE(innerRect->width(), qreal(150));
+ QCOMPARE(innerRect->height(), qreal(190));
+
+ delete rect;
+}
+
+void tst_states::anchorChanges4()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/anchorChanges4.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QmlGraphicsItem *leftGuideline = qobject_cast<QmlGraphicsItem*>(rect->findChild<QmlGraphicsItem*>("LeftGuideline"));
+ QVERIFY(leftGuideline != 0);
+
+ QmlGraphicsItem *bottomGuideline = qobject_cast<QmlGraphicsItem*>(rect->findChild<QmlGraphicsItem*>("BottomGuideline"));
+ QVERIFY(bottomGuideline != 0);
+
+ qmlExecuteDeferred(rect->states()->at(0));
+ QmlAnchorChanges *aChanges = qobject_cast<QmlAnchorChanges*>(rect->states()->at(0)->changes()->at(0));
+ QVERIFY(aChanges != 0);
+
+ rect->setState("reanchored");
+ QCOMPARE(aChanges->object(), innerRect);
+ QCOMPARE(aChanges->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
+ QCOMPARE(aChanges->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
+ QCOMPARE(aChanges->verticalCenter().item, leftGuideline->verticalCenter().item);
+ QCOMPARE(aChanges->verticalCenter().anchorLine, leftGuideline->verticalCenter().anchorLine);
+
+ delete rect;
+}
+
+void tst_states::anchorChanges5()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/anchorChanges5.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlGraphicsRectangle *innerRect = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QmlGraphicsItem *leftGuideline = qobject_cast<QmlGraphicsItem*>(rect->findChild<QmlGraphicsItem*>("LeftGuideline"));
+ QVERIFY(leftGuideline != 0);
+
+ QmlGraphicsItem *bottomGuideline = qobject_cast<QmlGraphicsItem*>(rect->findChild<QmlGraphicsItem*>("BottomGuideline"));
+ QVERIFY(bottomGuideline != 0);
+
+ qmlExecuteDeferred(rect->states()->at(0));
+ QmlAnchorChanges *aChanges = qobject_cast<QmlAnchorChanges*>(rect->states()->at(0)->changes()->at(0));
+ QVERIFY(aChanges != 0);
+
+ rect->setState("reanchored");
+ QCOMPARE(aChanges->object(), innerRect);
+ QCOMPARE(aChanges->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
+ QCOMPARE(aChanges->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
+ QCOMPARE(aChanges->baseline().item, leftGuideline->baseline().item);
+ QCOMPARE(aChanges->baseline().anchorLine, leftGuideline->baseline().anchorLine);
+
+ delete rect;
+}
+
+void tst_states::script()
+{
+ QmlEngine engine;
+
+ {
+ QmlComponent rectComponent(&engine, SRCDIR "/data/script.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
+ }
+}
+
+void tst_states::restoreEntryValues()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/restoreEntryValues.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("blue"));
+}
+
+void tst_states::explicitChanges()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/explicit.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ qmlExecuteDeferred(rect->states()->at(0));
+ QmlPropertyChanges *changes = qobject_cast<QmlPropertyChanges*>(rect->findChild<QmlPropertyChanges*>("changes"));
+ QVERIFY(changes != 0);
+ QVERIFY(changes->isExplicit());
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("yellow"));
+}
+
+void tst_states::propertyErrors()
+{
+ QmlEngine engine;
+ QmlComponent rectComponent(&engine, SRCDIR "/data/propertyErrors.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ QTest::ignoreMessage(QtWarningMsg, QByteArray("QML PropertyChanges (" + fullDataPath("/data/propertyErrors.qml") + ":8:9) Cannot assign to non-existant property \"colr\"").constData());
+ QTest::ignoreMessage(QtWarningMsg, QByteArray("QML PropertyChanges (" + fullDataPath("/data/propertyErrors.qml") + ":8:9) Cannot assign to read-only property \"wantsFocus\"").constData());
+ rect->setState("blue");
+}
+
+void tst_states::incorrectRestoreBug()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/basicChanges.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ // make sure if we change the base state value, we then restore to it correctly
+ rect->setColor(QColor("green"));
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("green"));
+}
+
+void tst_states::autoStateAtStartupRestoreBug()
+{
+ QmlEngine engine;
+
+ QmlComponent component(&engine, SRCDIR "/data/autoStateAtStartupRestoreBug.qml");
+ QObject *obj = component.create();
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 3);
+
+ obj->setProperty("input", 2);
+
+ QCOMPARE(obj->property("test").toInt(), 9);
+
+ delete obj;
+}
+
+void tst_states::deletingChange()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/deleting.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->radius(),qreal(5));
+
+ rect->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->radius(),qreal(0));
+
+ QmlPropertyChanges *pc = rect->findChild<QmlPropertyChanges*>("pc1");
+ QVERIFY(pc != 0);
+ delete pc;
+
+ QmlState *state = rect->findChild<QmlState*>();
+ QVERIFY(state != 0);
+ qmlExecuteDeferred(state);
+ QCOMPARE(state->changes()->count(), 1);
+
+ rect->setState("blue");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->radius(),qreal(5));
+
+ delete rect;
+}
+
+void tst_states::deletingState()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/deletingState.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QmlStateGroup *sg = rect->findChild<QmlStateGroup*>();
+ QVERIFY(sg != 0);
+ QVERIFY(sg->findState("blue") != 0);
+
+ sg->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ sg->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ QmlState *state = rect->findChild<QmlState*>();
+ QVERIFY(state != 0);
+ delete state;
+
+ QVERIFY(sg->findState("blue") == 0);
+
+ //### should we warn that state doesn't exist
+ sg->setState("blue");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ delete rect;
+}
+
+void tst_states::tempState()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/legalTempState.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QTest::ignoreMessage(QtDebugMsg, "entering placed");
+ QTest::ignoreMessage(QtDebugMsg, "entering idle");
+ rect->setState("placed");
+ QCOMPARE(rect->state(), QLatin1String("idle"));
+}
+
+void tst_states::illegalTempState()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/illegalTempState.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QTest::ignoreMessage(QtWarningMsg, "Can't apply a state change as part of a state definition. ");
+ rect->setState("placed");
+ QCOMPARE(rect->state(), QLatin1String("placed"));
+}
+
+void tst_states::nonExistantProperty()
+{
+ QmlEngine engine;
+
+ QmlComponent rectComponent(&engine, SRCDIR "/data/nonExistantProp.qml");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QTest::ignoreMessage(QtWarningMsg, QByteArray("QML PropertyChanges (" + fullDataPath("/data/nonExistantProp.qml") + ":9:9) Cannot assign to non-existant property \"colr\"").constData());
+ rect->setState("blue");
+ QCOMPARE(rect->state(), QLatin1String("blue"));
+}
+
+QTEST_MAIN(tst_states)
+
+#include "tst_qmlstates.moc"
diff --git a/tests/auto/declarative/qmlsystempalette/qmlsystempalette.pro b/tests/auto/declarative/qmlsystempalette/qmlsystempalette.pro
new file mode 100644
index 0000000..4d55b46
--- /dev/null
+++ b/tests/auto/declarative/qmlsystempalette/qmlsystempalette.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlsystempalette.cpp
diff --git a/tests/auto/declarative/qmlsystempalette/tst_qmlsystempalette.cpp b/tests/auto/declarative/qmlsystempalette/tst_qmlsystempalette.cpp
new file mode 100644
index 0000000..7da7f68
--- /dev/null
+++ b/tests/auto/declarative/qmlsystempalette/tst_qmlsystempalette.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QDebug>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlsystempalette_p.h>
+#include <qpalette.h>
+#include "../../../shared/util.h"
+
+class tst_qmlsystempalette : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlsystempalette();
+
+private slots:
+ void activePalette();
+ void inactivePalette();
+ void disabledPalette();
+ void paletteChanged();
+
+private:
+ QmlEngine engine;
+};
+
+tst_qmlsystempalette::tst_qmlsystempalette()
+{
+}
+
+void tst_qmlsystempalette::activePalette()
+{
+ QString componentStr = "import Qt 4.6\nSystemPalette { }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlSystemPalette *object = qobject_cast<QmlSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+
+ QPalette palette;
+ palette.setCurrentColorGroup(QPalette::Active);
+ QCOMPARE(palette.window().color(), object->window());
+ QCOMPARE(palette.windowText().color(), object->windowText());
+ QCOMPARE(palette.base().color(), object->base());
+ QCOMPARE(palette.text().color(), object->text());
+ QCOMPARE(palette.alternateBase().color(), object->alternateBase());
+ QCOMPARE(palette.button().color(), object->button());
+ QCOMPARE(palette.buttonText().color(), object->buttonText());
+ QCOMPARE(palette.light().color(), object->light());
+ QCOMPARE(palette.midlight().color(), object->midlight());
+ QCOMPARE(palette.dark().color(), object->dark());
+ QCOMPARE(palette.mid().color(), object->mid());
+ QCOMPARE(palette.shadow().color(), object->shadow());
+ QCOMPARE(palette.highlight().color(), object->highlight());
+ QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+
+ delete object;
+}
+
+void tst_qmlsystempalette::inactivePalette()
+{
+ QString componentStr = "import Qt 4.6\nSystemPalette { colorGroup: SystemPalette.Inactive }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlSystemPalette *object = qobject_cast<QmlSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+ QVERIFY(object->colorGroup() == QmlSystemPalette::Inactive);
+
+ QPalette palette;
+ palette.setCurrentColorGroup(QPalette::Inactive);
+ QCOMPARE(palette.window().color(), object->window());
+ QCOMPARE(palette.windowText().color(), object->windowText());
+ QCOMPARE(palette.base().color(), object->base());
+ QCOMPARE(palette.text().color(), object->text());
+ QCOMPARE(palette.alternateBase().color(), object->alternateBase());
+ QCOMPARE(palette.button().color(), object->button());
+ QCOMPARE(palette.buttonText().color(), object->buttonText());
+ QCOMPARE(palette.light().color(), object->light());
+ QCOMPARE(palette.midlight().color(), object->midlight());
+ QCOMPARE(palette.dark().color(), object->dark());
+ QCOMPARE(palette.mid().color(), object->mid());
+ QCOMPARE(palette.shadow().color(), object->shadow());
+ QCOMPARE(palette.highlight().color(), object->highlight());
+ QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+
+ delete object;
+}
+
+void tst_qmlsystempalette::disabledPalette()
+{
+ QString componentStr = "import Qt 4.6\nSystemPalette { colorGroup: SystemPalette.Disabled }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlSystemPalette *object = qobject_cast<QmlSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+ QVERIFY(object->colorGroup() == QmlSystemPalette::Disabled);
+
+ QPalette palette;
+ palette.setCurrentColorGroup(QPalette::Disabled);
+ QCOMPARE(palette.window().color(), object->window());
+ QCOMPARE(palette.windowText().color(), object->windowText());
+ QCOMPARE(palette.base().color(), object->base());
+ QCOMPARE(palette.text().color(), object->text());
+ QCOMPARE(palette.alternateBase().color(), object->alternateBase());
+ QCOMPARE(palette.button().color(), object->button());
+ QCOMPARE(palette.buttonText().color(), object->buttonText());
+ QCOMPARE(palette.light().color(), object->light());
+ QCOMPARE(palette.midlight().color(), object->midlight());
+ QCOMPARE(palette.dark().color(), object->dark());
+ QCOMPARE(palette.mid().color(), object->mid());
+ QCOMPARE(palette.shadow().color(), object->shadow());
+ QCOMPARE(palette.highlight().color(), object->highlight());
+ QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+
+ delete object;
+}
+
+void tst_qmlsystempalette::paletteChanged()
+{
+ QString componentStr = "import Qt 4.6\nSystemPalette { }";
+ QmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QmlSystemPalette *object = qobject_cast<QmlSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+
+ QPalette p;
+ p.setCurrentColorGroup(QPalette::Active);
+ p.setColor(QPalette::Active, QPalette::Text, QColor("red"));
+ p.setColor(QPalette::Active, QPalette::ButtonText, QColor("green"));
+ p.setColor(QPalette::Active, QPalette::WindowText, QColor("blue"));
+
+ qApp->setPalette(p);
+
+ object->setColorGroup(QmlSystemPalette::Active);
+ QTRY_COMPARE(QColor("red"), object->text());
+ QTRY_COMPARE(QColor("green"), object->buttonText());
+ QTRY_COMPARE(QColor("blue"), object->windowText());
+
+ delete object;
+}
+
+QTEST_MAIN(tst_qmlsystempalette)
+
+#include "tst_qmlsystempalette.moc"
diff --git a/tests/auto/declarative/qmltimer/qmltimer.pro b/tests/auto/declarative/qmltimer/qmltimer.pro
new file mode 100644
index 0000000..2b244ed
--- /dev/null
+++ b/tests/auto/declarative/qmltimer/qmltimer.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmltimer.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmltimer/tst_qmltimer.cpp b/tests/auto/declarative/qmltimer/tst_qmltimer.cpp
new file mode 100644
index 0000000..83094d2
--- /dev/null
+++ b/tests/auto/declarative/qmltimer/tst_qmltimer.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmltimer_p.h>
+#include <QDebug>
+
+class tst_qmltimer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmltimer();
+
+private slots:
+ void notRepeating();
+ void notRepeatingStart();
+ void repeat();
+ void noTriggerIfNotRunning();
+ void triggeredOnStart();
+ void triggeredOnStartRepeat();
+ void changeDuration();
+ void restart();
+};
+
+class TimerHelper : public QObject
+{
+ Q_OBJECT
+public:
+ TimerHelper() : QObject(), count(0)
+ {
+ }
+
+ int count;
+
+public slots:
+ void timeout() {
+ ++count;
+ }
+};
+
+#if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86)
+// Increase wait as emulator startup can cause unexpected delays
+#define TIMEOUT_TIMEOUT 2000
+#else
+#define TIMEOUT_TIMEOUT 200
+#endif
+
+tst_qmltimer::tst_qmltimer()
+{
+}
+
+void tst_qmltimer::notRepeating()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nTimer { interval: 100; running: true }"), QUrl::fromLocalFile(""));
+ QmlTimer *timer = qobject_cast<QmlTimer*>(component.create());
+ QVERIFY(timer != 0);
+ QVERIFY(timer->isRunning());
+ QVERIFY(!timer->isRepeating());
+ QCOMPARE(timer->interval(), 100);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QVERIFY(timer->isRunning() == false);
+}
+
+void tst_qmltimer::notRepeatingStart()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nTimer { interval: 100 }"), QUrl::fromLocalFile(""));
+ QmlTimer *timer = qobject_cast<QmlTimer*>(component.create());
+ QVERIFY(timer != 0);
+ QVERIFY(!timer->isRunning());
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 0);
+
+ timer->start();
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QVERIFY(timer->isRunning() == false);
+
+ delete timer;
+}
+
+void tst_qmltimer::repeat()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nTimer { interval: 100; repeat: true; running: true }"), QUrl::fromLocalFile(""));
+ QmlTimer *timer = qobject_cast<QmlTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QCOMPARE(helper.count, 0);
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > 0);
+ int oldCount = helper.count;
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > oldCount);
+ QVERIFY(timer->isRunning());
+
+ oldCount = helper.count;
+ timer->stop();
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count == oldCount);
+ QVERIFY(timer->isRunning() == false);
+
+ delete timer;
+}
+
+void tst_qmltimer::triggeredOnStart()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl::fromLocalFile(""));
+ QmlTimer *timer = qobject_cast<QmlTimer*>(component.create());
+ QVERIFY(timer != 0);
+ QVERIFY(timer->triggeredOnStart());
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QTest::qWait(1);
+ QCOMPARE(helper.count, 1);
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 2);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 2);
+ QVERIFY(timer->isRunning() == false);
+
+ delete timer;
+}
+
+void tst_qmltimer::triggeredOnStartRepeat()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl::fromLocalFile(""));
+ QmlTimer *timer = qobject_cast<QmlTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QTest::qWait(1);
+ QCOMPARE(helper.count, 1);
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > 1);
+ int oldCount = helper.count;
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > oldCount);
+ QVERIFY(timer->isRunning());
+
+ delete timer;
+}
+
+void tst_qmltimer::noTriggerIfNotRunning()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray(
+ "import Qt 4.6\n"
+ "Item { property bool ok: true\n"
+ "Timer { id: t1; interval: 100; repeat: true; running: true; onTriggered: if (!running) ok=false }"
+ "Timer { interval: 10; running: true; onTriggered: t1.running=false }"
+ "}"
+ ), QUrl::fromLocalFile(""));
+ QObject *item = component.create();
+ QVERIFY(item != 0);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(item->property("ok").toBool(), true);
+
+ delete item;
+}
+
+void tst_qmltimer::changeDuration()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nTimer { interval: 200; repeat: true; running: true }"), QUrl::fromLocalFile(""));
+ QmlTimer *timer = qobject_cast<QmlTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QCOMPARE(helper.count, 0);
+
+ QTest::qWait(500);
+ QCOMPARE(helper.count, 2);
+
+ timer->setInterval(500);
+
+ QTest::qWait(600);
+ QCOMPARE(helper.count, 3);
+ QVERIFY(timer->isRunning());
+
+ delete timer;
+}
+
+void tst_qmltimer::restart()
+{
+ QmlEngine engine;
+ QmlComponent component(&engine);
+ component.setData(QByteArray("import Qt 4.6\nTimer { interval: 500; repeat: true; running: true }"), QUrl::fromLocalFile(""));
+ QmlTimer *timer = qobject_cast<QmlTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QCOMPARE(helper.count, 0);
+
+ QTest::qWait(600);
+ QCOMPARE(helper.count, 1);
+
+ QTest::qWait(300);
+
+ timer->restart();
+
+ QTest::qWait(700);
+
+ QCOMPARE(helper.count, 2);
+ QVERIFY(timer->isRunning());
+
+ delete timer;
+}
+
+QTEST_MAIN(tst_qmltimer)
+
+#include "tst_qmltimer.moc"
diff --git a/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.2.qml b/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.2.qml
new file mode 100644
index 0000000..ce2e82d
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.2.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+
+MyTypeObject {
+ property int value: 10
+ rect.x: value
+
+ onRunScript: { rect = Qt.rect(10, 10, 10, 10) }
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.3.qml b/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.3.qml
new file mode 100644
index 0000000..c82b533
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.3.qml
@@ -0,0 +1,10 @@
+import Test 1.0
+
+MyTypeObject {
+ property var value
+
+ rect: value
+
+ onRunScript: { rect.x = 44 }
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.qml b/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.qml
new file mode 100644
index 0000000..a8a72f5
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/autoBindingRemoval.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+
+MyTypeObject {
+ property int value: 10
+ rect.x: value
+
+ onRunScript: { rect.x = 42; }
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/bindingAssignment.qml b/tests/auto/declarative/qmlvaluetypes/data/bindingAssignment.qml
new file mode 100644
index 0000000..a652186
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/bindingAssignment.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+
+MyTypeObject {
+ property int value: 10
+
+ rect.x: value
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/bindingConflict.qml b/tests/auto/declarative/qmlvaluetypes/data/bindingConflict.qml
new file mode 100644
index 0000000..fd25c9f
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/bindingConflict.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ property int value: 13
+
+ rect.x: value
+ rect: "10,10,10x10"
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/bindingRead.qml b/tests/auto/declarative/qmlvaluetypes/data/bindingRead.qml
new file mode 100644
index 0000000..538d776
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/bindingRead.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ property int value: rect.x
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/bindingVariantCopy.qml b/tests/auto/declarative/qmlvaluetypes/data/bindingVariantCopy.qml
new file mode 100644
index 0000000..691a56c
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/bindingVariantCopy.qml
@@ -0,0 +1,13 @@
+import Test 1.0
+
+MyTypeObject {
+ property var object
+ object: MyTypeObject {
+ rect.x: 19
+ rect.y: 33
+ rect.width: 5
+ rect.height: 99
+ }
+
+ rect: object.rect
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/deletedObject.js b/tests/auto/declarative/qmlvaluetypes/data/deletedObject.js
new file mode 100644
index 0000000..af298ff
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/deletedObject.js
@@ -0,0 +1,13 @@
+var savedReference;
+
+function startup()
+{
+ savedReference = object.rect;
+ console.log("Test: " + savedReference.x);
+}
+
+function afterDelete()
+{
+ console.log("Test: " + savedReference.x);
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/deletedObject.qml b/tests/auto/declarative/qmlvaluetypes/data/deletedObject.qml
new file mode 100644
index 0000000..05459f4
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/deletedObject.qml
@@ -0,0 +1,12 @@
+import Test 1.0
+import Qt 4.6
+
+MyTypeObject {
+ property var object
+
+ Script { source: "deletedObject.js" }
+
+ object: MyTypeObject {}
+ Component.onCompleted: startup()
+ onRunScript: afterDelete()
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/font_read.qml b/tests/auto/declarative/qmlvaluetypes/data/font_read.qml
new file mode 100644
index 0000000..e1d1ce0
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/font_read.qml
@@ -0,0 +1,18 @@
+import Test 1.0
+
+MyTypeObject {
+ property string f_family: font.family
+ property bool f_bold: font.bold
+ property int f_weight: font.weight
+ property bool f_italic: font.italic
+ property bool f_underline: font.underline
+ property bool f_overline: font.overline
+ property bool f_strikeout: font.strikeout
+ property real f_pointSize: font.pointSize
+ property int f_pixelSize: font.pixelSize
+ property int f_capitalization: font.capitalization
+ property real f_letterSpacing: font.letterSpacing
+ property real f_wordSpacing: font.wordSpacing;
+ property var copy: font
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/font_write.2.qml b/tests/auto/declarative/qmlvaluetypes/data/font_write.2.qml
new file mode 100644
index 0000000..b559389
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/font_write.2.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ font.pixelSize: 10
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/font_write.3.qml b/tests/auto/declarative/qmlvaluetypes/data/font_write.3.qml
new file mode 100644
index 0000000..913ac50
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/font_write.3.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+
+MyTypeObject {
+ font.pixelSize: 10
+ font.pointSize: 19
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/font_write.qml b/tests/auto/declarative/qmlvaluetypes/data/font_write.qml
new file mode 100644
index 0000000..ff4d0a1
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/font_write.qml
@@ -0,0 +1,16 @@
+import Test 1.0
+
+MyTypeObject {
+ font.family: if(1) "Helvetica"
+ font.bold: if(1) false
+ font.weight: "Normal"
+ font.italic: if(1) false
+ font.underline: if(1) false
+ font.overline: if(1) false
+ font.strikeout: if(1) false
+ font.pointSize: if(1) 15
+ font.capitalization: "AllLowercase"
+ font.letterSpacing: if(1) 9.7
+ font.wordSpacing: if(1) 11.2
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/point_read.qml b/tests/auto/declarative/qmlvaluetypes/data/point_read.qml
new file mode 100644
index 0000000..3e67de6
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/point_read.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+
+MyTypeObject {
+ property int p_x: point.x
+ property int p_y: point.y
+ property var copy: point
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/point_write.qml b/tests/auto/declarative/qmlvaluetypes/data/point_write.qml
new file mode 100644
index 0000000..063525a
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/point_write.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ point.x: if (true) 11
+ point.y: if (true) 12
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/pointf_read.qml b/tests/auto/declarative/qmlvaluetypes/data/pointf_read.qml
new file mode 100644
index 0000000..d845a5b
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/pointf_read.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ property real p_x: pointf.x
+ property real p_y: pointf.y
+ property var copy: pointf
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/pointf_write.qml b/tests/auto/declarative/qmlvaluetypes/data/pointf_write.qml
new file mode 100644
index 0000000..9ee3fc1
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/pointf_write.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ pointf.x: if (true) 6.8
+ pointf.y: if (true) 9.3
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/rect_read.qml b/tests/auto/declarative/qmlvaluetypes/data/rect_read.qml
new file mode 100644
index 0000000..5364431
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/rect_read.qml
@@ -0,0 +1,10 @@
+import Test 1.0
+
+MyTypeObject {
+ property int r_x: rect.x
+ property int r_y: rect.y
+ property int r_width: rect.width
+ property int r_height: rect.height
+ property var copy: rect
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/rect_write.qml b/tests/auto/declarative/qmlvaluetypes/data/rect_write.qml
new file mode 100644
index 0000000..8add453
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/rect_write.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+
+MyTypeObject {
+ rect.x: if (true) 1234
+ rect.y: if (true) 7
+ rect.width: if (true) 56
+ rect.height: if (true) 63
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/rectf_read.qml b/tests/auto/declarative/qmlvaluetypes/data/rectf_read.qml
new file mode 100644
index 0000000..aeb9f41
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/rectf_read.qml
@@ -0,0 +1,10 @@
+import Test 1.0
+
+MyTypeObject {
+ property real r_x: rectf.x
+ property real r_y: rectf.y
+ property real r_width: rectf.width
+ property real r_height: rectf.height
+ property var copy: rectf
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/rectf_write.qml b/tests/auto/declarative/qmlvaluetypes/data/rectf_write.qml
new file mode 100644
index 0000000..1e6ff4f
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/rectf_write.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+
+MyTypeObject {
+ rectf.x: if (true) 70.1
+ rectf.y: if (true) -113.2
+ rectf.width: if (true) 80924.8
+ rectf.height: if (true) 99.2
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/scriptAccess.qml b/tests/auto/declarative/qmlvaluetypes/data/scriptAccess.qml
new file mode 100644
index 0000000..96592eb
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/scriptAccess.qml
@@ -0,0 +1,9 @@
+import Qt 4.6
+import Test 1.0
+
+MyTypeObject {
+ property int valuePre;
+ property int valuePost;
+
+ Component.onCompleted: { valuePre = rect.x; rect.x = 19; valuePost = rect.x; }
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/scriptVariantCopy.qml b/tests/auto/declarative/qmlvaluetypes/data/scriptVariantCopy.qml
new file mode 100644
index 0000000..29157e8
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/scriptVariantCopy.qml
@@ -0,0 +1,14 @@
+import Test 1.0
+
+MyTypeObject {
+ property var object
+ object: MyTypeObject {
+ rect.x: 19
+ rect.y: 33
+ rect.width: 5
+ rect.height: 99
+ }
+
+ onRunScript: rect = object.rect
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/size_read.qml b/tests/auto/declarative/qmlvaluetypes/data/size_read.qml
new file mode 100644
index 0000000..86dba03
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/size_read.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ property int s_width: size.width
+ property int s_height: size.height
+ property var copy: size
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/size_write.qml b/tests/auto/declarative/qmlvaluetypes/data/size_write.qml
new file mode 100644
index 0000000..2f9d10e
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/size_write.qml
@@ -0,0 +1,7 @@
+import Test 1.0
+
+MyTypeObject {
+ size.width: if (true) 13
+ size.height: if (true) 88
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/sizef_read.qml b/tests/auto/declarative/qmlvaluetypes/data/sizef_read.qml
new file mode 100644
index 0000000..c6f34e4
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/sizef_read.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+
+MyTypeObject {
+ property real s_width: sizef.width
+ property real s_height: sizef.height
+ property var copy: sizef
+}
+
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/sizef_write.qml b/tests/auto/declarative/qmlvaluetypes/data/sizef_write.qml
new file mode 100644
index 0000000..f16f0bd
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/sizef_write.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+MyTypeObject {
+ sizef.width: if (true) 44.3
+ sizef.height: if (true) 92.8
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/staticAssignment.qml b/tests/auto/declarative/qmlvaluetypes/data/staticAssignment.qml
new file mode 100644
index 0000000..b687f89
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/staticAssignment.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ rect.x: 9
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/valueInterceptors.qml b/tests/auto/declarative/qmlvaluetypes/data/valueInterceptors.qml
new file mode 100644
index 0000000..026ae83
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/valueInterceptors.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ property int value: 13;
+
+ rect.x: MyOffsetValueInterceptor {}
+ rect.x: value
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/valueSources.qml b/tests/auto/declarative/qmlvaluetypes/data/valueSources.qml
new file mode 100644
index 0000000..d4d4391
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/valueSources.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyTypeObject {
+ rect.x: MyConstantValueSource {}
+}
diff --git a/tests/auto/declarative/qmlvaluetypes/data/vector3d_read.qml b/tests/auto/declarative/qmlvaluetypes/data/vector3d_read.qml
new file mode 100644
index 0000000..abdf9f0
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/vector3d_read.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+
+MyTypeObject {
+ property real v_x: vector.x
+ property real v_y: vector.y
+ property real v_z: vector.z
+ property var copy: vector
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/data/vector3d_write.qml b/tests/auto/declarative/qmlvaluetypes/data/vector3d_write.qml
new file mode 100644
index 0000000..9c1bf76
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/data/vector3d_write.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ vector.x: if (true) -0.3
+ vector.y: if (true) -12.9
+ vector.z: if (true) 907.4
+}
+
diff --git a/tests/auto/declarative/qmlvaluetypes/qmlvaluetypes.pro b/tests/auto/declarative/qmlvaluetypes/qmlvaluetypes.pro
new file mode 100644
index 0000000..82d067e
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/qmlvaluetypes.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+HEADERS += testtypes.h
+
+SOURCES += tst_qmlvaluetypes.cpp \
+ testtypes.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlvaluetypes/testtypes.cpp b/tests/auto/declarative/qmlvaluetypes/testtypes.cpp
new file mode 100644
index 0000000..565eb1c
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/testtypes.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "testtypes.h"
+
+QML_DEFINE_TYPE(Test, 1, 0, MyTypeObject, MyTypeObject);
+QML_DEFINE_TYPE(Test, 1, 0, MyConstantValueSource, MyConstantValueSource);
+QML_DEFINE_TYPE(Test, 1, 0, MyOffsetValueInterceptor, MyOffsetValueInterceptor);
diff --git a/tests/auto/declarative/qmlvaluetypes/testtypes.h b/tests/auto/declarative/qmlvaluetypes/testtypes.h
new file mode 100644
index 0000000..67e32f5
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/testtypes.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TESTTYPES_H
+#define TESTTYPES_H
+
+#include <QObject>
+#include <QPoint>
+#include <QPointF>
+#include <QSize>
+#include <QSizeF>
+#include <QRect>
+#include <QRectF>
+#include <QVector3D>
+#include <QFont>
+#include <qml.h>
+#include <QmlPropertyValueSource>
+
+class MyTypeObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPoint point READ point WRITE setPoint NOTIFY changed);
+ Q_PROPERTY(QPointF pointf READ pointf WRITE setPointf NOTIFY changed);
+ Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY changed);
+ Q_PROPERTY(QSizeF sizef READ sizef WRITE setSizef NOTIFY changed);
+ Q_PROPERTY(QRect rect READ rect WRITE setRect NOTIFY changed);
+ Q_PROPERTY(QRectF rectf READ rectf WRITE setRectf NOTIFY changed);
+ Q_PROPERTY(QVector3D vector READ vector WRITE setVector NOTIFY changed);
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed);
+
+public:
+ MyTypeObject() :
+ m_point(10, 4),
+ m_pointf(11.3, -10.9),
+ m_size(1912, 1913),
+ m_sizef(0.1, 100923.2),
+ m_rect(2, 3, 109, 102),
+ m_rectf(103.8, 99.2, 88.1, 77.6),
+ m_vector(23.88, 3.1, 4.3)
+ {
+ m_font.setFamily("Arial");
+ m_font.setBold(true);
+ m_font.setWeight(QFont::DemiBold);
+ m_font.setItalic(true);
+ m_font.setUnderline(true);
+ m_font.setOverline(true);
+ m_font.setStrikeOut(true);
+ m_font.setPointSize(29);
+ m_font.setCapitalization(QFont::AllUppercase);
+ m_font.setLetterSpacing(QFont::AbsoluteSpacing, 10.2);
+ m_font.setWordSpacing(19.7);
+ }
+
+ QPoint m_point;
+ QPoint point() const { return m_point; }
+ void setPoint(const QPoint &v) { m_point = v; emit changed(); }
+
+ QPointF m_pointf;
+ QPointF pointf() const { return m_pointf; }
+ void setPointf(const QPointF &v) { m_pointf = v; emit changed(); }
+
+ QSize m_size;
+ QSize size() const { return m_size; }
+ void setSize(const QSize &v) { m_size = v; emit changed(); }
+
+ QSizeF m_sizef;
+ QSizeF sizef() const { return m_sizef; }
+ void setSizef(const QSizeF &v) { m_sizef = v; emit changed(); }
+
+ QRect m_rect;
+ QRect rect() const { return m_rect; }
+ void setRect(const QRect &v) { m_rect = v; emit changed(); }
+
+ QRectF m_rectf;
+ QRectF rectf() const { return m_rectf; }
+ void setRectf(const QRectF &v) { m_rectf = v; emit changed(); }
+
+ QVector3D m_vector;
+ QVector3D vector() const { return m_vector; }
+ void setVector(const QVector3D &v) { m_vector = v; emit changed(); }
+
+ QFont m_font;
+ QFont font() const { return m_font; }
+ void setFont(const QFont &v) { m_font = v; emit changed(); }
+
+ void emitRunScript() { emit runScript(); }
+
+signals:
+ void changed();
+ void runScript();
+};
+QML_DECLARE_TYPE(MyTypeObject);
+
+class MyConstantValueSource : public QObject, public QmlPropertyValueSource
+{
+ Q_OBJECT
+public:
+ virtual void setTarget(const QmlMetaProperty &p) { p.write(3345); }
+};
+QML_DECLARE_TYPE(MyConstantValueSource);
+
+class MyOffsetValueInterceptor : public QObject, public QmlPropertyValueInterceptor
+{
+ Q_OBJECT
+public:
+ virtual void setTarget(const QmlMetaProperty &p) { prop = p; }
+ virtual void write(const QVariant &value) { prop.write(value.toInt() + 13, QmlMetaProperty::BypassInterceptor); }
+
+private:
+ QmlMetaProperty prop;
+};
+QML_DECLARE_TYPE(MyOffsetValueInterceptor);
+
+#endif // TESTTYPES_H
diff --git a/tests/auto/declarative/qmlvaluetypes/tst_qmlvaluetypes.cpp b/tests/auto/declarative/qmlvaluetypes/tst_qmlvaluetypes.cpp
new file mode 100644
index 0000000..49655db
--- /dev/null
+++ b/tests/auto/declarative/qmlvaluetypes/tst_qmlvaluetypes.cpp
@@ -0,0 +1,588 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include <private/qmlvaluetype_p.h>
+#include "testtypes.h"
+
+class tst_valuetypes : public QObject
+{
+ Q_OBJECT
+public:
+ tst_valuetypes() {}
+
+private slots:
+ void point();
+ void pointf();
+ void size();
+ void sizef();
+ void rect();
+ void rectf();
+ void vector3d();
+ void font();
+
+ void bindingAssignment();
+ void bindingRead();
+ void staticAssignment();
+ void scriptAccess();
+ void autoBindingRemoval();
+ void valueSources();
+ void valueInterceptors();
+ void bindingConflict();
+ void deletedObject();
+ void bindingVariantCopy();
+ void scriptVariantCopy();
+ void cppClasses();
+
+private:
+ QmlEngine engine;
+};
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
+}
+
+void tst_valuetypes::point()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("point_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("p_x").toInt(), 10);
+ QCOMPARE(object->property("p_y").toInt(), 4);
+ QCOMPARE(object->property("copy"), QVariant(QPoint(10, 4)));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("point_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->point(), QPoint(11, 12));
+
+ delete object;
+ }
+}
+
+void tst_valuetypes::pointf()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("pointf_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("p_x").toDouble(), 11.3);
+ QCOMPARE(object->property("p_y").toDouble(), -10.9);
+ QCOMPARE(object->property("copy"), QVariant(QPointF(11.3, -10.9)));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("pointf_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->pointf(), QPointF(6.8, 9.3));
+
+ delete object;
+ }
+}
+
+void tst_valuetypes::size()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("size_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("s_width").toInt(), 1912);
+ QCOMPARE(object->property("s_height").toInt(), 1913);
+ QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("size_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->size(), QSize(13, 88));
+
+ delete object;
+ }
+}
+
+void tst_valuetypes::sizef()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("sizef_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("s_width").toDouble(), 0.1);
+ QCOMPARE(object->property("s_height").toDouble(), 100923.2);
+ QCOMPARE(object->property("copy"), QVariant(QSizeF(0.1, 100923.2)));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("sizef_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->sizef(), QSizeF(44.3, 92.8));
+
+ delete object;
+ }
+}
+
+void tst_valuetypes::rect()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("rect_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("r_x").toInt(), 2);
+ QCOMPARE(object->property("r_y").toInt(), 3);
+ QCOMPARE(object->property("r_width").toInt(), 109);
+ QCOMPARE(object->property("r_height").toInt(), 102);
+ QCOMPARE(object->property("copy"), QVariant(QRect(2, 3, 109, 102)));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("rect_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect(), QRect(1234, 7, 56, 63));
+
+ delete object;
+ }
+}
+
+void tst_valuetypes::rectf()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("rectf_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("r_x").toDouble(), 103.8);
+ QCOMPARE(object->property("r_y").toDouble(), 99.2);
+ QCOMPARE(object->property("r_width").toDouble(), 88.1);
+ QCOMPARE(object->property("r_height").toDouble(), 77.6);
+ QCOMPARE(object->property("copy"), QVariant(QRectF(103.8, 99.2, 88.1, 77.6)));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("rectf_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rectf(), QRectF(70.1, -113.2, 80924.8, 99.2));
+
+ delete object;
+ }
+}
+
+void tst_valuetypes::vector3d()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("vector3d_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE((float)object->property("v_x").toDouble(), (float)23.88);
+ QCOMPARE((float)object->property("v_y").toDouble(), (float)3.1);
+ QCOMPARE((float)object->property("v_z").toDouble(), (float)4.3);
+ QCOMPARE(object->property("copy"), QVariant(QVector3D(23.88, 3.1, 4.3)));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("vector3d_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->vector(), QVector3D(-0.3, -12.9, 907.4));
+
+ delete object;
+ }
+}
+
+void tst_valuetypes::font()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("font_read.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("f_family").toString(), object->font().family());
+ QCOMPARE(object->property("f_bold").toBool(), object->font().bold());
+ QCOMPARE(object->property("f_weight").toInt(), object->font().weight());
+ QCOMPARE(object->property("f_italic").toBool(), object->font().italic());
+ QCOMPARE(object->property("f_underline").toBool(), object->font().underline());
+ QCOMPARE(object->property("f_overline").toBool(), object->font().overline());
+ QCOMPARE(object->property("f_strikeout").toBool(), object->font().strikeOut());
+ QCOMPARE(object->property("f_pointSize").toDouble(), object->font().pointSizeF());
+ QCOMPARE(object->property("f_pixelSize").toInt(), object->font().pixelSize());
+ QCOMPARE(object->property("f_capitalization").toInt(), (int)object->font().capitalization());
+ QCOMPARE(object->property("f_letterSpacing").toDouble(), object->font().letterSpacing());
+ QCOMPARE(object->property("f_wordSpacing").toDouble(), object->font().wordSpacing());
+
+ QCOMPARE(object->property("copy"), QVariant(object->font()));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("font_write.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QFont font;
+ font.setFamily("Helvetica");
+ font.setBold(false);
+ font.setWeight(QFont::Normal);
+ font.setItalic(false);
+ font.setUnderline(false);
+ font.setStrikeOut(false);
+ font.setPointSize(15);
+ font.setCapitalization(QFont::AllLowercase);
+ font.setLetterSpacing(QFont::AbsoluteSpacing, 9.7);
+ font.setWordSpacing(11.2);
+
+ QEXPECT_FAIL("", "QT-2920", Continue);
+ QCOMPARE(object->font(), font);
+
+ delete object;
+ }
+
+ // Test pixelSize
+ {
+ QmlComponent component(&engine, TEST_FILE("font_write.2.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->font().pixelSize(), 10);
+
+ delete object;
+ }
+
+ // Test pixelSize and pointSize
+ {
+ QmlComponent component(&engine, TEST_FILE("font_write.3.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size. ");
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->font().pixelSize(), 10);
+
+ delete object;
+ }
+}
+
+// Test bindings can write to value types
+void tst_valuetypes::bindingAssignment()
+{
+ QmlComponent component(&engine, TEST_FILE("bindingAssignment.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect().x(), 10);
+
+ object->setProperty("value", QVariant(92));
+
+ QCOMPARE(object->rect().x(), 92);
+
+ delete object;
+}
+
+// Test bindings can read from value types
+void tst_valuetypes::bindingRead()
+{
+ QmlComponent component(&engine, TEST_FILE("bindingRead.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("value").toInt(), 2);
+
+ object->setRect(QRect(19, 3, 88, 2));
+
+ QCOMPARE(object->property("value").toInt(), 19);
+
+ delete object;
+}
+
+// Test static values can assign to value types
+void tst_valuetypes::staticAssignment()
+{
+ QmlComponent component(&engine, TEST_FILE("staticAssignment.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect().x(), 9);
+
+ delete object;
+}
+
+// Test scripts can read/write value types
+void tst_valuetypes::scriptAccess()
+{
+ QmlComponent component(&engine, TEST_FILE("scriptAccess.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("valuePre").toInt(), 2);
+ QCOMPARE(object->rect().x(), 19);
+ QCOMPARE(object->property("valuePost").toInt(), 19);
+
+ delete object;
+}
+
+// Test that assigning a constant from script removes any binding
+void tst_valuetypes::autoBindingRemoval()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("autoBindingRemoval.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect().x(), 10);
+
+ object->setProperty("value", QVariant(13));
+
+ QCOMPARE(object->rect().x(), 13);
+
+ object->emitRunScript();
+
+ QCOMPARE(object->rect().x(), 42);
+
+ object->setProperty("value", QVariant(92));
+
+ QEXPECT_FAIL("", "QT-2920", Continue);
+ QCOMPARE(object->rect().x(), 42);
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("autoBindingRemoval.2.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect().x(), 10);
+
+ object->setProperty("value", QVariant(13));
+
+ QCOMPARE(object->rect().x(), 13);
+
+ object->emitRunScript();
+
+ QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
+
+ object->setProperty("value", QVariant(92));
+
+ QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("autoBindingRemoval.3.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ object->setProperty("value", QVariant(QRect(9, 22, 33, 44)));
+
+ QCOMPARE(object->rect(), QRect(9, 22, 33, 44));
+
+ object->emitRunScript();
+
+ QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
+
+ object->setProperty("value", QVariant(QRect(19, 3, 4, 8)));
+
+ QEXPECT_FAIL("", "QT-2920", Continue);
+ QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
+
+ delete object;
+ }
+
+}
+
+// Test that property value sources assign to value types
+void tst_valuetypes::valueSources()
+{
+ QmlComponent component(&engine, TEST_FILE("valueSources.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect().x(), 3345);
+
+ delete object;
+}
+
+static void checkNoErrors(QmlComponent& component)
+{
+ QList<QmlError> errors = component.errors();
+ if (errors.isEmpty())
+ return;
+ for (int ii = 0; ii < errors.count(); ++ii) {
+ const QmlError &error = errors.at(ii);
+ qWarning("%d:%d:%s",error.line(),error.column(),error.description().toUtf8().constData());
+ }
+}
+
+// Test that property value interceptors can be applied to value types
+void tst_valuetypes::valueInterceptors()
+{
+ QmlComponent component(&engine, TEST_FILE("valueInterceptors.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ checkNoErrors(component);
+ QEXPECT_FAIL("", "QT-2920", Abort);
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect().x(), 26);
+
+ object->setProperty("value", 99);
+
+ QCOMPARE(object->rect().x(), 112);
+
+ delete object;
+}
+
+// Test that you can't assign a binding to the "root" value type, and a sub-property
+void tst_valuetypes::bindingConflict()
+{
+ QmlComponent component(&engine, TEST_FILE("bindingConflict.qml"));
+ QCOMPARE(component.isError(), true);
+}
+
+#define CPP_TEST(type, v) \
+{ \
+ type *t = new type; \
+ QVariant value(v); \
+ t->setValue(value); \
+ QCOMPARE(t->value(), value); \
+ delete t; \
+}
+
+// Test that accessing a reference to a valuetype after the owning object is deleted
+// doesn't crash
+void tst_valuetypes::deletedObject()
+{
+ QmlComponent component(&engine, TEST_FILE("deletedObject.qml"));
+ QTest::ignoreMessage(QtDebugMsg, "Test: 2");
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QObject *dObject = qvariant_cast<QObject *>(object->property("object"));
+ QVERIFY(dObject != 0);
+ delete dObject;
+
+ QTest::ignoreMessage(QtDebugMsg, "Test: undefined");
+ object->emitRunScript();
+
+ delete object;
+}
+
+// Test that value types can be assigned to another value type property in a binding
+void tst_valuetypes::bindingVariantCopy()
+{
+ QmlComponent component(&engine, TEST_FILE("bindingVariantCopy.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
+
+ delete object;
+}
+
+// Test that value types can be assigned to another value type property in script
+void tst_valuetypes::scriptVariantCopy()
+{
+ QmlComponent component(&engine, TEST_FILE("scriptVariantCopy.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->rect(), QRect(2, 3, 109, 102));
+
+ object->emitRunScript();
+
+ QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
+
+ delete object;
+}
+
+
+// Test that the value type classes can be used manually
+void tst_valuetypes::cppClasses()
+{
+ CPP_TEST(QmlPointValueType, QPoint(19, 33));
+ CPP_TEST(QmlPointFValueType, QPointF(33.6, -23));
+ CPP_TEST(QmlSizeValueType, QSize(-100, 18));
+ CPP_TEST(QmlSizeFValueType, QSizeF(-100.7, 18.2));
+ CPP_TEST(QmlRectValueType, QRect(13, 39, 10928, 88));
+ CPP_TEST(QmlRectFValueType, QRectF(88.2, -90.1, 103.2, 118));
+ CPP_TEST(QmlVector3DValueType, QVector3D(18.2, 19.7, 1002));
+ CPP_TEST(QmlFontValueType, QFont("Helvetica"));
+
+}
+QTEST_MAIN(tst_valuetypes)
+
+#include "tst_qmlvaluetypes.moc"
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/abort.expect b/tests/auto/declarative/qmlxmlhttprequest/data/abort.expect
new file mode 100644
index 0000000..f43e043
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/abort.expect
@@ -0,0 +1,10 @@
+PUT /testdocument.html HTTP/1.1
+Content-Type: text/plain;charset=UTF-8
+Content-Length: 9
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
+Test Data \ No newline at end of file
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/abort.qml b/tests/auto/declarative/qmlxmlhttprequest/data/abort.qml
new file mode 100644
index 0000000..d7b9266
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/abort.qml
@@ -0,0 +1,42 @@
+import Qt 4.6
+
+QtObject {
+ property string urlDummy
+ property string url
+
+ property bool seenDone: false
+ property bool didNotSeeUnsent: true
+ property bool endStateUnsent: false
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("GET", urlDummy);
+ x.setRequestHeader("Test-header", "TestValue");
+ x.send();
+
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ seenDone = true;
+ } else if (x.readyState == XMLHttpRequest.UNSENT) {
+ didNotSeeUnsent = false;
+ }
+ }
+
+ x.abort();
+
+ if (x.readyState == XMLHttpRequest.UNSENT) {
+ endStateUnsent = true;
+ }
+
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+ x.open("PUT", url);
+ x.send("Test Data");
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/abort.reply b/tests/auto/declarative/qmlxmlhttprequest/data/abort.reply
new file mode 100644
index 0000000..35b11f4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/abort.reply
@@ -0,0 +1,2 @@
+HTTP/1.0 200 OK
+Content-type: text/html; charset=UTF-8
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/abort_opened.qml b/tests/auto/declarative/qmlxmlhttprequest/data/abort_opened.qml
new file mode 100644
index 0000000..72a45e7
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/abort_opened.qml
@@ -0,0 +1,58 @@
+import Qt 4.6
+
+QtObject {
+ property string url: "testdocument.html"
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool status: false
+ property bool statusText: false
+ property bool responseText: false
+ property bool responseXML: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.abort();
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("PUT", url);
+
+ x.abort();
+
+ x.open("GET", url);
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ var a = x.status;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ status = true;
+ }
+ try {
+ var a = x.statusText;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusText = true;
+ }
+ responseText = (x.responseText == "");
+ responseXML = (x.responseXML == null);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+
+ x.send()
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/abort_unsent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/abort_unsent.qml
new file mode 100644
index 0000000..aa78cde
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/abort_unsent.qml
@@ -0,0 +1,54 @@
+import Qt 4.6
+
+QtObject {
+ property string url: "testdocument.html"
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool status: false
+ property bool statusText: false
+ property bool responseText: false
+ property bool responseXML: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.abort();
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("GET", url);
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ var a = x.status;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ status = true;
+ }
+ try {
+ var a = x.statusText;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusText = true;
+ }
+ responseText = (x.responseText == "");
+ responseXML = (x.responseXML == null);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+
+ x.send()
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/attr.qml b/tests/auto/declarative/qmlxmlhttprequest/data/attr.qml
new file mode 100644
index 0000000..9049fc7
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/attr.qml
@@ -0,0 +1,80 @@
+import Qt 4.6
+
+QtObject {
+ property bool xmlTest: false
+ property bool dataOK: false
+
+ Script {
+ function checkAttr(documentElement, attr)
+ {
+ if (attr == null)
+ return;
+
+ if (attr.name != "attr")
+ return;
+
+ if (attr.value != "myvalue")
+ return;
+
+ if (attr.ownerElement.tagName != documentElement.tagName)
+ return;
+
+ if (attr.nodeName != "attr")
+ return;
+
+ if (attr.nodeValue != "myvalue")
+ return;
+
+ if (attr.nodeType != 2)
+ return;
+
+ if (attr.childNodes.length != 0)
+ return;
+
+ if (attr.firstChild != null)
+ return;
+
+ if (attr.lastChild != null)
+ return;
+
+ if (attr.previousSibling != null)
+ return;
+
+ if (attr.nextSibling != null)
+ return;
+
+ if (attr.attributes != null)
+ return;
+
+ xmlTest = true;
+ }
+
+ function checkXML(document)
+ {
+ checkAttr(document.documentElement, document.documentElement.attributes[0]);
+ }
+ }
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "attr.xml");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+
+ dataOK = true;
+
+ if (x.responseXML != null)
+ checkXML(x.responseXML);
+
+ }
+ }
+
+ x.send()
+ }
+}
+
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/attr.xml b/tests/auto/declarative/qmlxmlhttprequest/data/attr.xml
new file mode 100644
index 0000000..2aa64a3
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/attr.xml
@@ -0,0 +1 @@
+<root attr="myvalue" />
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/callbackException.qml b/tests/auto/declarative/qmlxmlhttprequest/data/callbackException.qml
new file mode 100644
index 0000000..9255922
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/callbackException.qml
@@ -0,0 +1,25 @@
+import Qt 4.6
+
+QtObject {
+ id: obj
+ property string url
+ property string which
+ property bool threw: false
+
+ onWhichChanged: {
+ var x = new XMLHttpRequest;
+
+ x.onreadystatechange = function() {
+ if (x.readyState == which) {
+ obj.threw = true
+ throw(new Error("Exception from Callback"))
+ }
+ }
+
+ x.open("GET", url);
+ x.setRequestHeader("Test-header", "TestValue");
+ x.send();
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/cdata.qml b/tests/auto/declarative/qmlxmlhttprequest/data/cdata.qml
new file mode 100644
index 0000000..b2d0209
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/cdata.qml
@@ -0,0 +1,135 @@
+import Qt 4.6
+
+QtObject {
+ property bool xmlTest: false
+ property bool dataOK: false
+
+ Script {
+ function checkCData(text, whitespacetext)
+ {
+ // This is essentially a copy of text.qml/checkText()
+
+ if (text == null)
+ return;
+
+ if (text.nodeName != "#cdata-section")
+ return;
+
+ if (text.nodeValue != "Hello world!")
+ return;
+
+ if (text.nodeType != 4)
+ return;
+
+ if (text.parentNode.nodeName != "item")
+ return;
+
+ if (text.childNodes.length != 0)
+ return;
+
+ if (text.firstChild != null)
+ return;
+
+ if (text.lastChild != null)
+ return;
+
+ if (text.previousSibling != null)
+ return;
+
+ if (text.nextSibling != null)
+ return;
+
+ if (text.attributes != null)
+ return;
+
+ if (text.wholeText != "Hello world!")
+ return;
+
+ if (text.data != "Hello world!")
+ return;
+
+ if (text.length != 12)
+ return;
+
+ if (text.isElementContentWhitespace != false)
+ return;
+
+ if (whitespacetext.nodeName != "#cdata-section")
+ return;
+
+ if (whitespacetext.nodeValue != " ")
+ return;
+
+ if (whitespacetext.nodeType != 4)
+ return;
+
+ if (whitespacetext.parentNode.nodeName != "item")
+ return;
+
+ if (whitespacetext.childNodes.length != 0)
+ return;
+
+ if (whitespacetext.firstChild != null)
+ return;
+
+ if (whitespacetext.lastChild != null)
+ return;
+
+ if (whitespacetext.previousSibling != null)
+ return;
+
+ if (whitespacetext.nextSibling != null)
+ return;
+
+ if (whitespacetext.attributes != null)
+ return;
+
+ if (whitespacetext.wholeText != " ")
+ return;
+
+ if (whitespacetext.data != " ")
+ return;
+
+ if (whitespacetext.length != 3)
+ return;
+
+ if (whitespacetext.isElementContentWhitespace != true)
+ return;
+
+
+ xmlTest = true;
+ }
+
+ function checkXML(document)
+ {
+ checkCData(document.documentElement.childNodes[0].childNodes[0],
+ document.documentElement.childNodes[1].childNodes[0]);
+
+ }
+ }
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "cdata.xml");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+
+ dataOK = true;
+
+ if (x.responseXML != null)
+ checkXML(x.responseXML);
+
+ }
+ }
+
+ x.send()
+ }
+}
+
+
+
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/cdata.xml b/tests/auto/declarative/qmlxmlhttprequest/data/cdata.xml
new file mode 100644
index 0000000..061d37c
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/cdata.xml
@@ -0,0 +1,2 @@
+<root><item><![CDATA[Hello world!]]></item><item><![CDATA[ ]]></item></root>
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/constructor.qml b/tests/auto/declarative/qmlxmlhttprequest/data/constructor.qml
new file mode 100644
index 0000000..93e44fd
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/constructor.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+QtObject {
+ property bool calledAsConstructor
+ property bool calledAsFunction
+
+ Component.onCompleted: {
+ var x1 = new XMLHttpRequest;
+ var x2 = XMLHttpRequest();
+
+ calledAsConstructor = (x1 != null && x1 instanceof XMLHttpRequest);
+ calledAsFunction = (x2 == undefined);
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/defaultState.qml b/tests/auto/declarative/qmlxmlhttprequest/data/defaultState.qml
new file mode 100644
index 0000000..4dcf6f9
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/defaultState.qml
@@ -0,0 +1,30 @@
+import Qt 4.6
+
+QtObject {
+ property int readyState
+ property bool statusIsException: false
+ property bool statusTextIsException: false
+ property string responseText
+ property bool responseXMLIsNull
+
+ Component.onCompleted: {
+ var xhr = new XMLHttpRequest();
+
+ readyState = xhr.readyState;
+ try {
+ status = xhr.status;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusIsException = true;
+ }
+ try {
+ statusText = xhr.statusText;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusTextIsException = true;
+ }
+ responseText = xhr.responseText;
+ responseXMLIsNull = (xhr.responseXML == null);
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/document.qml b/tests/auto/declarative/qmlxmlhttprequest/data/document.qml
new file mode 100644
index 0000000..e372361
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/document.qml
@@ -0,0 +1,58 @@
+import Qt 4.6
+
+QtObject {
+ property bool xmlTest: false
+ property bool dataOK: false
+
+ Script {
+ function checkXML(document)
+ {
+ if (document.xmlVersion != "1.0")
+ return;
+
+ if (document.xmlEncoding != "UTF-8")
+ return;
+
+ if (document.xmlStandalone != true)
+ return;
+
+ if (document.documentElement == null)
+ return;
+
+ if (document.nodeName != "#document")
+ return;
+
+ if (document.nodeValue != null)
+ return;
+
+ if (document.parentNode != null)
+ return;
+
+ // ### Test other node properties
+ // ### test encoding (what is a valid qt encoding?)
+ xmlTest = true;
+ }
+ }
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "document.xml");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+
+ dataOK = true;
+
+ if (x.responseXML != null)
+ checkXML(x.responseXML);
+
+ }
+ }
+
+ x.send()
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/document.xml b/tests/auto/declarative/qmlxmlhttprequest/data/document.xml
new file mode 100644
index 0000000..fb693ea
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/document.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" standalone='yes'?>
+<root>
+</root>
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/domExceptionCodes.qml b/tests/auto/declarative/qmlxmlhttprequest/data/domExceptionCodes.qml
new file mode 100644
index 0000000..de5ee4f
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/domExceptionCodes.qml
@@ -0,0 +1,60 @@
+import Qt 4.6
+
+QtObject {
+ property int index_size_err: DOMException.INDEX_SIZE_ERR
+ property int domstring_size_err: DOMException.DOMSTRING_SIZE_ERR
+ property int hierarchy_request_err: DOMException.HIERARCHY_REQUEST_ERR
+ property int wrong_document_err: DOMException.WRONG_DOCUMENT_ERR
+ property int invalid_character_err: DOMException.INVALID_CHARACTER_ERR
+ property int no_data_allowed_err: DOMException.NO_DATA_ALLOWED_ERR
+ property int no_modification_allowed_err: DOMException.NO_MODIFICATION_ALLOWED_ERR
+ property int not_found_err: DOMException.NOT_FOUND_ERR
+ property int not_supported_err: DOMException.NOT_SUPPORTED_ERR
+ property int inuse_attribute_err: DOMException.INUSE_ATTRIBUTE_ERR
+ property int invalid_state_err: DOMException.INVALID_STATE_ERR
+ property int syntax_err: DOMException.SYNTAX_ERR
+ property int invalid_modification_err: DOMException.INVALID_MODIFICATION_ERR
+ property int namespace_err: DOMException.NAMESPACE_ERR
+ property int invalid_access_err: DOMException.INVALID_ACCESS_ERR
+ property int validation_err: DOMException.VALIDATION_ERR
+ property int type_mismatch_err: DOMException.TYPE_MISMATCH_ERR
+
+ Component.onCompleted: {
+ // Attempt to overwrite and delete values
+ DOMException.INDEX_SIZE_ERR = 44;
+ DOMException.DOMSTRING_SIZE_ERR = 44;
+ DOMException.HIERARCHY_REQUEST_ERR = 44;
+ DOMException.WRONG_DOCUMENT_ERR = 44;
+ DOMException.INVALID_CHARACTER_ERR = 44;
+ DOMException.NO_DATA_ALLOWED_ERR = 44;
+ DOMException.NO_MODIFICATION_ALLOWED_ERR = 44;
+ DOMException.NOT_FOUND_ERR = 44;
+ DOMException.NOT_SUPPORTED_ERR = 44;
+ DOMException.INUSE_ATTRIBUTE_ERR = 44;
+ DOMException.INVALID_STATE_ERR = 44;
+ DOMException.SYNTAX_ERR = 44;
+ DOMException.INVALID_MODIFICATION_ERR = 44;
+ DOMException.NAMESPACE_ERR = 44;
+ DOMException.INVALID_ACCESS_ERR = 44;
+ DOMException.VALIDATION_ERR = 44;
+ DOMException.TYPE_MISMATCH_ERR = 44;
+
+ delete DOMException.INDEX_SIZE_ERR;
+ delete DOMException.DOMSTRING_SIZE_ERR;
+ delete DOMException.HIERARCHY_REQUEST_ERR;
+ delete DOMException.WRONG_DOCUMENT_ERR;
+ delete DOMException.INVALID_CHARACTER_ERR;
+ delete DOMException.NO_DATA_ALLOWED_ERR;
+ delete DOMException.NO_MODIFICATION_ALLOWED_ERR;
+ delete DOMException.NOT_FOUND_ERR;
+ delete DOMException.NOT_SUPPORTED_ERR;
+ delete DOMException.INUSE_ATTRIBUTE_ERR;
+ delete DOMException.INVALID_STATE_ERR;
+ delete DOMException.SYNTAX_ERR;
+ delete DOMException.INVALID_MODIFICATION_ERR;
+ delete DOMException.NAMESPACE_ERR;
+ delete DOMException.INVALID_ACCESS_ERR;
+ delete DOMException.VALIDATION_ERR;
+ delete DOMException.TYPE_MISMATCH_ERR;
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/element.qml b/tests/auto/declarative/qmlxmlhttprequest/data/element.qml
new file mode 100644
index 0000000..78c0374
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/element.qml
@@ -0,0 +1,147 @@
+import Qt 4.6
+
+QtObject {
+ property bool xmlTest: false
+ property bool dataOK: false
+
+ Script {
+ function checkElement(e, person, fruit)
+ {
+ if (e.tagName != "root")
+ return;
+
+ if (e.nodeName != "root")
+ return;
+
+ if (e.nodeValue != null)
+ return;
+
+ if (e.nodeType != 1)
+ return;
+
+ var childTagNames = [ "person", "fruit" ];
+
+ if (e.childNodes.length != childTagNames.length)
+ return;
+
+ for (var ii = 0; ii < childTagNames.length; ++ii) {
+ if (e.childNodes[ii].tagName != childTagNames[ii])
+ return;
+ }
+
+ if (e.childNodes[childTagNames.length + 1] != null)
+ return;
+
+ // Check writing fails
+ e.childNodes[0] = null;
+ if (e.childNodes[0] == null)
+ return;
+
+ e.childNodes[10] = 10;
+ if (e.childNodes[10] != null)
+ return;
+
+ if (e.firstChild.tagName != e.childNodes[0].tagName)
+ return;
+
+ if (e.lastChild.tagName != e.childNodes[1].tagName)
+ return;
+
+ if (e.previousSibling != null)
+ return;
+
+ if (e.nextSibling != null)
+ return;
+
+ if (e.attributes == null)
+ return;
+
+ if (e.attributes.length != 2)
+ return;
+
+ var attr1 = e.attributes["attr"];
+ if (attr1.nodeValue != "value")
+ return;
+
+ var attrIdx = e.attributes[0];
+ if (attrIdx.nodeValue != "value")
+ return;
+
+ var attr2 = e.attributes["attr2"];
+ if (attr2.nodeValue != "value2")
+ return;
+
+ var attr3 = e.attributes["attr3"];
+ if (attr3 != null)
+ return;
+
+ var attrIdx2 = e.attributes[11];
+ if (attrIdx2 != null)
+ return;
+
+ // Check writing fails
+ e.attributes[0] = null;
+ if (e.attributes[0] == null)
+ return;
+
+ e.attributes["attr"] = null;
+ if (e.attributes["attr"] == null)
+ return;
+
+ e.attributes["attr3"] = 10;
+ if (e.attributes["attr3"] != null)
+ return;
+
+ // Check person and fruit sub elements
+ if (person.parentNode.nodeName != "root")
+ return;
+
+ if (person.previousSibling != null)
+ return;
+
+ if (person.nextSibling.nodeName != "fruit")
+ return;
+
+ if (fruit.parentNode.nodeName != "root")
+ return;
+
+ if (fruit.previousSibling.nodeName != "person")
+ return;
+
+ if (fruit.nextSibling != null)
+ return;
+
+ xmlTest = true;
+ }
+
+ function checkXML(document)
+ {
+ checkElement(document.documentElement,
+ document.documentElement.childNodes[0],
+ document.documentElement.childNodes[1]);
+ }
+ }
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "element.xml");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+
+ dataOK = true;
+
+ if (x.responseXML != null)
+ checkXML(x.responseXML);
+
+ }
+ }
+
+ x.send()
+ }
+}
+
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/element.xml b/tests/auto/declarative/qmlxmlhttprequest/data/element.xml
new file mode 100644
index 0000000..071ffae
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/element.xml
@@ -0,0 +1 @@
+<root attr="value" attr2="value2"><person /><fruit /></root>
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders.qml
new file mode 100644
index 0000000..02a8083
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders.qml
@@ -0,0 +1,65 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool unsentException: false
+ property bool openedException: false
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool headersReceivedState: false
+ property bool headersReceivedHeader: false
+
+ property bool doneState: false
+ property bool doneHeader: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("GET", url);
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
+
+ var headers = "content-type: text/html; charset=UTF-8\r\ntest-header: TestValue\r\nmultitest-header: TestValue, SecondTestValue\r\ncontent-length: 11";
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ headersReceivedState = true;
+
+ headersReceivedHeader = (x.getAllResponseHeaders() == headers);
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ doneState = headersReceivedState && true;
+
+ doneHeader = (x.getAllResponseHeaders() == headers);
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send()
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_args.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_args.qml
new file mode 100644
index 0000000..37124c7
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_args.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property bool exceptionThrown: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "testdocument.html");
+ x.send();
+
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ try {
+ x.getAllResponseHeaders("Test-header");
+ } catch (e) {
+ if (e.code == DOMException.SYNTAX_ERR)
+ exceptionThrown = true;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_sent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_sent.qml
new file mode 100644
index 0000000..505e4b1
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_sent.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+QtObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "testdocument.html");
+ x.send();
+
+ try {
+ x.getAllResponseHeaders();
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_unsent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_unsent.qml
new file mode 100644
index 0000000..20fb040
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getAllResponseHeaders_unsent.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+QtObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.getAllResponseHeaders();
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.expect b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.expect
new file mode 100644
index 0000000..a740c79
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.expect
@@ -0,0 +1,7 @@
+GET /testdocument.html HTTP/1.1
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.qml
new file mode 100644
index 0000000..2f949e1
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.qml
@@ -0,0 +1,75 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool unsentException: false
+ property bool openedException: false
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool headersReceivedState: false
+ property bool headersReceivedNullHeader: false
+ property bool headersReceivedValidHeader: false
+ property bool headersReceivedMultiValidHeader: false
+ property bool headersReceivedCookieHeader: false
+
+ property bool doneState: false
+ property bool doneNullHeader: false
+ property bool doneValidHeader: false
+ property bool doneMultiValidHeader: false
+ property bool doneCookieHeader: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("GET", url);
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ headersReceivedState = true;
+
+ headersReceivedNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
+ headersReceivedValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
+ headersReceivedMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ headersReceivedCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ doneState = headersReceivedState && true;
+
+ doneNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
+ doneValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
+ doneMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ doneCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send()
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.reply b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.reply
new file mode 100644
index 0000000..62ec67b
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader.reply
@@ -0,0 +1,7 @@
+HTTP/1.0 200 OK
+Content-type: text/html; charset=UTF-8
+Test-Header: TestValue
+MultiTest-Header: TestValue
+MultiTest-Header: SecondTestValue
+Set-Cookie: mycook=Value
+Set-Cookie2: mycook=Value
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_args.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_args.qml
new file mode 100644
index 0000000..d5aa4b1
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_args.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property bool exceptionThrown: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "testdocument.html");
+ x.send();
+
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ try {
+ x.getResponseHeader();
+ } catch (e) {
+ if (e.code == DOMException.SYNTAX_ERR)
+ exceptionThrown = true;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_sent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_sent.qml
new file mode 100644
index 0000000..7538ffd
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_sent.qml
@@ -0,0 +1,20 @@
+import Qt 4.6
+
+QtObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "testdocument.html");
+ x.send();
+
+ try {
+ x.getResponseHeader("Test-header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_unsent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_unsent.qml
new file mode 100644
index 0000000..3b55802
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/getResponseHeader_unsent.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+QtObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.getResponseHeader("Test-header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/instanceStateValues.qml b/tests/auto/declarative/qmlxmlhttprequest/data/instanceStateValues.qml
new file mode 100644
index 0000000..b8d01c4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/instanceStateValues.qml
@@ -0,0 +1,33 @@
+import Qt 4.6
+
+QtObject {
+ property int unsent
+ property int opened
+ property int headers_received
+ property int loading
+ property int done
+
+ Component.onCompleted: {
+ // Attempt to overwrite and delete values
+ var x = new XMLHttpRequest();
+
+ x.UNSENT = 9;
+ x.OPENED = 9;
+ x.HEADERS_RECEIVED = 9;
+ x.LOADING = 9;
+ x.DONE = 9;
+
+ delete x.UNSENT;
+ delete x.OPENED;
+ delete x.HEADERS_RECEIVED;
+ delete x.LOADING;
+ delete x.DONE;
+
+ unsent = x.UNSENT
+ opened = x.OPENED
+ headers_received = x.HEADERS_RECEIVED
+ loading = x.LOADING
+ done = x.DONE
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/invalidMethodUsage.qml b/tests/auto/declarative/qmlxmlhttprequest/data/invalidMethodUsage.qml
new file mode 100644
index 0000000..b30989b
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/invalidMethodUsage.qml
@@ -0,0 +1,160 @@
+import Qt 4.6
+
+QtObject {
+ property bool onreadystatechange: false
+ property bool readyState: false
+ property bool status: false
+ property bool statusText: false
+ property bool responseText: false
+ property bool responseXML: false
+
+ property bool open: false
+ property bool setRequestHeader: false
+ property bool send: false
+ property bool abort: false
+ property bool getResponseHeader: false
+ property bool getAllResponseHeaders: false
+
+ Component.onCompleted: {
+ var o = 10;
+
+ try {
+ XMLHttpRequest.prototype.onreadystatechange
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ onreadystatechange = true;
+ }
+ try {
+ XMLHttpRequest.prototype.readyState
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ readyState = true;
+ }
+ try {
+ XMLHttpRequest.prototype.status
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ status = true;
+ }
+ try {
+ XMLHttpRequest.prototype.statusText
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ statusText = true;
+ }
+ try {
+ XMLHttpRequest.prototype.responseText
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ responseText = true;
+ }
+ try {
+ XMLHttpRequest.prototype.responseXML
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ responseXML = true;
+ }
+
+ try {
+ XMLHttpRequest.prototype.open.call(o);
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ open = true;
+ }
+
+ try {
+ XMLHttpRequest.prototype.setRequestHeader.call(o);
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ setRequestHeader = true;
+ }
+
+ try {
+ XMLHttpRequest.prototype.send.call(o);
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ send = true;
+ }
+
+ try {
+ XMLHttpRequest.prototype.abort.call(o);
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ abort = true;
+ }
+
+ try {
+ XMLHttpRequest.prototype.getResponseHeader.call(o);
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ getResponseHeader = true;
+ }
+
+ try {
+ XMLHttpRequest.prototype.getAllResponseHeaders.call(o);
+ } catch (e) {
+ if (!(e instanceof ReferenceError))
+ return;
+
+ if (e.message != "Not an XMLHttpRequest object")
+ return;
+
+ getAllResponseHeaders = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open.qml b/tests/auto/declarative/qmlxmlhttprequest/data/open.qml
new file mode 100644
index 0000000..c06bae3
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open.qml
@@ -0,0 +1,53 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool status: false
+ property bool statusText: false
+ property bool responseText: false
+ property bool responseXML: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("GET", url);
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ var a = x.status;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ status = true;
+ }
+ try {
+ var a = x.statusText;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusText = true;
+ }
+ responseText = (x.responseText == "");
+ responseXML = (x.responseXML == null);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+
+ x.send()
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.1.qml b/tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.1.qml
new file mode 100644
index 0000000..b6d4c32
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.1.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+QtObject {
+ property bool exceptionThrown: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.open("GET");
+ } catch (e) {
+ if (e.code == DOMException.SYNTAX_ERR)
+ exceptionThrown = true;
+ }
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.2.qml b/tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.2.qml
new file mode 100644
index 0000000..8c86c20
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_arg_count.2.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+QtObject {
+ property bool exceptionThrown: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.open("GET", "http://www.nokia.com", true, "user", "password", "extra");
+ } catch (e) {
+ if (e.code == DOMException.SYNTAX_ERR)
+ exceptionThrown = true;
+ }
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_invalid_method.qml b/tests/auto/declarative/qmlxmlhttprequest/data/open_invalid_method.qml
new file mode 100644
index 0000000..69f79ae
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_invalid_method.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+QtObject {
+ property bool exceptionThrown: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.open("BLAH", "http://www.nokia.com");
+ } catch (e) {
+ if (e.code == DOMException.SYNTAX_ERR)
+ exceptionThrown = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_network.expect b/tests/auto/declarative/qmlxmlhttprequest/data/open_network.expect
new file mode 100644
index 0000000..a740c79
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_network.expect
@@ -0,0 +1,7 @@
+GET /testdocument.html HTTP/1.1
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_network.reply b/tests/auto/declarative/qmlxmlhttprequest/data/open_network.reply
new file mode 100644
index 0000000..35b11f4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_network.reply
@@ -0,0 +1,2 @@
+HTTP/1.0 200 OK
+Content-type: text/html; charset=UTF-8
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_network.wait b/tests/auto/declarative/qmlxmlhttprequest/data/open_network.wait
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_network.wait
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_sync.qml b/tests/auto/declarative/qmlxmlhttprequest/data/open_sync.qml
new file mode 100644
index 0000000..1477279
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_sync.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+
+QtObject {
+ property bool exceptionThrown: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.open("GET", "http://www.nokia.com", false);
+ } catch (e) {
+ if (e.code == DOMException.NOT_SUPPORTED_ERR)
+ exceptionThrown = true;
+ }
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_user.qml b/tests/auto/declarative/qmlxmlhttprequest/data/open_user.qml
new file mode 100644
index 0000000..19e37fa
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_user.qml
@@ -0,0 +1,53 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool status: false
+ property bool statusText: false
+ property bool responseText: false
+ property bool responseXML: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("GET", url, true, "username", "password");
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ var a = x.status;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ status = true;
+ }
+ try {
+ var a = x.statusText;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusText = true;
+ }
+ responseText = (x.responseText == "");
+ responseXML = (x.responseXML == null);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+
+ x.send()
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/open_username.qml b/tests/auto/declarative/qmlxmlhttprequest/data/open_username.qml
new file mode 100644
index 0000000..983ea14
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/open_username.qml
@@ -0,0 +1,54 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool status: false
+ property bool statusText: false
+ property bool responseText: false
+ property bool responseXML: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("GET", url, true, "sampleusername", "password");
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ var a = x.status;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ status = true;
+ }
+ try {
+ var a = x.statusText;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusText = true;
+ }
+ responseText = (x.responseText == "");
+ responseXML = (x.responseXML == null);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+
+ x.send()
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/redirectError.qml b/tests/auto/declarative/qmlxmlhttprequest/data/redirectError.qml
new file mode 100644
index 0000000..6b345cc
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/redirectError.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+ property bool done: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("GET", url);
+
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ done = true;
+ dataOK = x.status == 404;
+ }
+ }
+
+ x.send();
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/redirectRecur.qml b/tests/auto/declarative/qmlxmlhttprequest/data/redirectRecur.qml
new file mode 100644
index 0000000..c0321dc
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/redirectRecur.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+ property bool done: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("GET", url);
+
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ done = true;
+ dataOK = x.status == 302;
+ }
+ }
+
+ x.send();
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/redirects.qml b/tests/auto/declarative/qmlxmlhttprequest/data/redirects.qml
new file mode 100644
index 0000000..f6fabdb
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/redirects.qml
@@ -0,0 +1,22 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+ property bool done: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("GET", url);
+
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ done = true;
+ dataOK = x.responseText == "Redirected\n";
+ }
+ }
+
+ x.send();
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/redirecttarget.html b/tests/auto/declarative/qmlxmlhttprequest/data/redirecttarget.html
new file mode 100644
index 0000000..95f35e0
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/redirecttarget.html
@@ -0,0 +1 @@
+Redirected
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/responseText.qml b/tests/auto/declarative/qmlxmlhttprequest/data/responseText.qml
new file mode 100644
index 0000000..4bb3a7a
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/responseText.qml
@@ -0,0 +1,52 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+ property string expectedText
+
+ property bool unsent: false
+ property bool opened: false
+ property bool sent: false
+ property bool headersReceived: false
+
+ property bool loading: false
+ property bool done: false
+
+ property bool reset: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ unsent = (x.responseText == "");
+
+ x.open("GET", url);
+
+ opened = (x.responseText == "");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ headersReceived = (x.responseText == "");
+ } else if (x.readyState == XMLHttpRequest.LOADING) {
+ if (x.responseText == expectedText)
+ loading = true;
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.responseText == expectedText)
+ done = true;
+
+ dataOK = (x.responseText == expectedText);
+
+ x.open("GET", url);
+
+ reset = (x.responseText == "");
+ }
+ }
+
+ x.send()
+
+ sent = (x.responseText == "");
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/responseXML_invalid.qml b/tests/auto/declarative/qmlxmlhttprequest/data/responseXML_invalid.qml
new file mode 100644
index 0000000..63f288e
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/responseXML_invalid.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+QtObject {
+ property bool xmlNull: false
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "testdocument.html");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ xmlNull = (x.responseXML == null);
+ }
+ }
+
+
+ x.send()
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/seconddocument.html b/tests/auto/declarative/qmlxmlhttprequest/data/seconddocument.html
new file mode 100644
index 0000000..a33f44b
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/seconddocument.html
@@ -0,0 +1 @@
+This should not be read!
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_alreadySent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_alreadySent.qml
new file mode 100644
index 0000000..0bad7df
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_alreadySent.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+QtObject {
+ property bool dataOK: false
+ property bool test: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("GET", "testdocument.html");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send();
+
+ try {
+ x.send()
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.expect b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.expect
new file mode 100644
index 0000000..81dd4a0
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.expect
@@ -0,0 +1,10 @@
+POST /testdocument.html HTTP/1.1
+Content-Type: text/plain;charset=UTF-8
+Content-Length: 12
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
+My Sent Data \ No newline at end of file
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.qml
new file mode 100644
index 0000000..03543a9
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.1.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("POST", url);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("My Sent Data");
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.2.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.2.qml
new file mode 100644
index 0000000..79a27b6
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.2.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("POST", url);
+ x.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("My Sent Data");
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.3.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.3.qml
new file mode 100644
index 0000000..e048769
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.3.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("POST", url);
+ x.setRequestHeader("Content-Type", "text/plain;charset=latin1");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("My Sent Data");
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.expect b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.expect
new file mode 100644
index 0000000..8fcf3ac
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.expect
@@ -0,0 +1,10 @@
+POST /testdocument.html HTTP/1.1
+Content-Type: charset=UTF-8;text/plain
+Content-Length: 12
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
+My Sent Data \ No newline at end of file
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.qml
new file mode 100644
index 0000000..7ab0b27
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.4.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("POST", url);
+ x.setRequestHeader("Content-Type", "charset=UTF-8;text/plain");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("My Sent Data");
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.5.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.5.qml
new file mode 100644
index 0000000..29bf2c2
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.5.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("POST", url);
+ x.setRequestHeader("Content-Type", "charset=latin1;text/plain");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("My Sent Data");
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.expect b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.expect
new file mode 100644
index 0000000..97e6fac
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.expect
@@ -0,0 +1,10 @@
+PUT /testdocument.html HTTP/1.1
+Content-Type: text/plain;charset=UTF-8
+Content-Length: 12
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
+My Sent Data \ No newline at end of file
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.qml
new file mode 100644
index 0000000..135f45c
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.6.qml
@@ -0,0 +1,21 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("PUT", url);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("My Sent Data");
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.7.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.7.qml
new file mode 100644
index 0000000..4a09527
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.7.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("POST", url);
+ x.setRequestHeader("Content-Type", "text/plain");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("My Sent Data");
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_data.reply b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.reply
new file mode 100644
index 0000000..35b11f4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_data.reply
@@ -0,0 +1,2 @@
+HTTP/1.0 200 OK
+Content-type: text/html; charset=UTF-8
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.qml
new file mode 100644
index 0000000..dd5fa46
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.qml
@@ -0,0 +1,26 @@
+import Qt 4.6
+
+QtObject {
+ property string reqType
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open(reqType, url);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ if (reqType == "HEAD")
+ dataOK = (x.responseText == "");
+ else
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send("Data To Ignore");
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.reply b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.reply
new file mode 100644
index 0000000..35b11f4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData.reply
@@ -0,0 +1,2 @@
+HTTP/1.0 200 OK
+Content-type: text/html; charset=UTF-8
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_GET.expect b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_GET.expect
new file mode 100644
index 0000000..a740c79
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_GET.expect
@@ -0,0 +1,7 @@
+GET /testdocument.html HTTP/1.1
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_PUT.expect b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_PUT.expect
new file mode 100644
index 0000000..991bd59
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_ignoreData_PUT.expect
@@ -0,0 +1,7 @@
+HEAD /testdocument.html HTTP/1.1
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/send_unsent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/send_unsent.qml
new file mode 100644
index 0000000..7f51ecf
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/send_unsent.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+QtObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.send();
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.expect b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.expect
new file mode 100644
index 0000000..4600f2a
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.expect
@@ -0,0 +1,9 @@
+GET /testdocument.html HTTP/1.1
+TEST-HEADER: value
+TEST-HEADER2: value,value2
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.qml b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.qml
new file mode 100644
index 0000000..b0723aa
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.qml
@@ -0,0 +1,28 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", url);
+
+ x.setRequestHeader("Test-header", "value");
+ x.setRequestHeader("Test-header2", "value");
+ x.setRequestHeader("Test-header2", "value2");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send();
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.reply b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.reply
new file mode 100644
index 0000000..35b11f4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader.reply
@@ -0,0 +1,2 @@
+HTTP/1.0 200 OK
+Content-type: text/html; charset=UTF-8
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_args.qml b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_args.qml
new file mode 100644
index 0000000..8305ae1
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_args.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+QtObject {
+ property bool exceptionThrown: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "testdocument.html");
+
+ try {
+ x.setRequestHeader("Test-header");
+ } catch (e) {
+ if (e.code == DOMException.SYNTAX_ERR)
+ exceptionThrown = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_illegalName.qml b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_illegalName.qml
new file mode 100644
index 0000000..bf31eca
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_illegalName.qml
@@ -0,0 +1,57 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+ property string header
+
+ property bool readyState: false
+ property bool openedState: false
+
+ property bool status: false
+ property bool statusText: false
+ property bool responseText: false
+ property bool responseXML: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ if (x.readyState == XMLHttpRequest.UNSENT)
+ readyState = true;
+
+ x.open("GET", url);
+
+ x.setRequestHeader(header, "Value");
+
+ if (x.readyState == XMLHttpRequest.OPENED)
+ openedState = true;
+
+ try {
+ var a = x.status;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ status = true;
+ }
+ try {
+ var a = x.statusText;
+ } catch (error) {
+ if (error.code == DOMException.INVALID_STATE_ERR)
+ statusText = true;
+ }
+ responseText = (x.responseText == "");
+ responseXML = (x.responseXML == null);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+
+ x.send()
+ }
+}
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_sent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_sent.qml
new file mode 100644
index 0000000..c2bbc6e
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_sent.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+ property bool test: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", url);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+ }
+
+ x.send();
+
+ try {
+ x.setRequestHeader("Test-header", "value");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_unsent.qml b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_unsent.qml
new file mode 100644
index 0000000..30bc93e
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/setRequestHeader_unsent.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+
+QtObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ x.setRequestHeader("Test-header", "value");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ test = true;
+ }
+ }
+}
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/staticStateValues.qml b/tests/auto/declarative/qmlxmlhttprequest/data/staticStateValues.qml
new file mode 100644
index 0000000..ec1c5d8
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/staticStateValues.qml
@@ -0,0 +1,24 @@
+import Qt 4.6
+
+QtObject {
+ property int unsent: XMLHttpRequest.UNSENT
+ property int opened: XMLHttpRequest.OPENED
+ property int headers_received: XMLHttpRequest.HEADERS_RECEIVED
+ property int loading: XMLHttpRequest.LOADING
+ property int done: XMLHttpRequest.DONE
+
+ Component.onCompleted: {
+ // Attempt to overwrite and delete values
+ XMLHttpRequest.UNSENT = 9;
+ XMLHttpRequest.OPENED = 9;
+ XMLHttpRequest.HEADERS_RECEIVED = 9;
+ XMLHttpRequest.LOADING = 9;
+ XMLHttpRequest.DONE = 9;
+
+ delete XMLHttpRequest.UNSENT;
+ delete XMLHttpRequest.OPENED;
+ delete XMLHttpRequest.HEADERS_RECEIVED;
+ delete XMLHttpRequest.LOADING;
+ delete XMLHttpRequest.DONE;
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/status.200.reply b/tests/auto/declarative/qmlxmlhttprequest/data/status.200.reply
new file mode 100644
index 0000000..35b11f4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/status.200.reply
@@ -0,0 +1,2 @@
+HTTP/1.0 200 OK
+Content-type: text/html; charset=UTF-8
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/status.404.reply b/tests/auto/declarative/qmlxmlhttprequest/data/status.404.reply
new file mode 100644
index 0000000..964a7a8
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/status.404.reply
@@ -0,0 +1,2 @@
+HTTP/1.0 404 Document not found
+Content-type: text/html; charset=UTF-8
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/status.expect b/tests/auto/declarative/qmlxmlhttprequest/data/status.expect
new file mode 100644
index 0000000..a740c79
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/status.expect
@@ -0,0 +1,7 @@
+GET /testdocument.html HTTP/1.1
+Connection: Keep-Alive
+Accept-Encoding: gzip
+Accept-Language: en-US,*
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/status.qml b/tests/auto/declarative/qmlxmlhttprequest/data/status.qml
new file mode 100644
index 0000000..04202c4
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/status.qml
@@ -0,0 +1,77 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+ property int expectedStatus
+
+ property bool unsentException: false;
+ property bool openedException: false;
+ property bool sentException: false;
+
+ property bool headersReceived: false
+ property bool loading: false
+ property bool done: false
+
+ property bool resetException: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ var a = x.status;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
+
+ x.open("GET", url);
+
+ try {
+ var a = x.status;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ if (x.status == expectedStatus)
+ headersReceived = true;
+ } else if (x.readyState == XMLHttpRequest.LOADING) {
+ if (x.status == expectedStatus)
+ loading = true;
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.status == expectedStatus)
+ done = true;
+
+ if (expectedStatus == 404) {
+ dataOK = (x.responseText == "");
+ } else {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+
+ x.open("GET", url);
+
+ try {
+ var a = x.status;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ resetException = true;
+ }
+
+ }
+ }
+
+ x.send()
+
+ try {
+ var a = x.status;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ sentException = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/statusText.qml b/tests/auto/declarative/qmlxmlhttprequest/data/statusText.qml
new file mode 100644
index 0000000..8becc3b
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/statusText.qml
@@ -0,0 +1,77 @@
+import Qt 4.6
+
+QtObject {
+ property string url
+ property string expectedStatus
+
+ property bool unsentException: false;
+ property bool openedException: false;
+ property bool sentException: false;
+
+ property bool headersReceived: false
+ property bool loading: false
+ property bool done: false
+
+ property bool resetException: false
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ try {
+ var a = x.statusText;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
+
+ x.open("GET", url);
+
+ try {
+ var a = x.statusText;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ if (x.statusText == expectedStatus)
+ headersReceived = true;
+ } else if (x.readyState == XMLHttpRequest.LOADING) {
+ if (x.statusText == expectedStatus)
+ loading = true;
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.statusText == expectedStatus)
+ done = true;
+
+ if (expectedStatus != "OK") {
+ dataOK = (x.responseText == "");
+ } else {
+ dataOK = (x.responseText == "QML Rocks!\n");
+ }
+
+ x.open("GET", url);
+
+ try {
+ var a = x.statusText;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ resetException = true;
+ }
+
+ }
+ }
+
+ x.send()
+
+ try {
+ var a = x.statusText;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ sentException = true;
+ }
+ }
+}
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/testdocument.html b/tests/auto/declarative/qmlxmlhttprequest/data/testdocument.html
new file mode 100644
index 0000000..8fe0f4b
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/testdocument.html
@@ -0,0 +1 @@
+QML Rocks!
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/text.qml b/tests/auto/declarative/qmlxmlhttprequest/data/text.qml
new file mode 100644
index 0000000..4615a07
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/text.qml
@@ -0,0 +1,131 @@
+import Qt 4.6
+
+QtObject {
+ property bool xmlTest: false
+ property bool dataOK: false
+
+ Script {
+ function checkText(text, whitespacetext)
+ {
+ if (text == null)
+ return;
+
+ if (text.nodeName != "#text")
+ return;
+
+ if (text.nodeValue != "Hello world!")
+ return;
+
+ if (text.nodeType != 3)
+ return;
+
+ if (text.parentNode.nodeName != "item")
+ return;
+
+ if (text.childNodes.length != 0)
+ return;
+
+ if (text.firstChild != null)
+ return;
+
+ if (text.lastChild != null)
+ return;
+
+ if (text.previousSibling != null)
+ return;
+
+ if (text.nextSibling != null)
+ return;
+
+ if (text.attributes != null)
+ return;
+
+ if (text.wholeText != "Hello world!")
+ return;
+
+ if (text.data != "Hello world!")
+ return;
+
+ if (text.length != 12)
+ return;
+
+ if (text.isElementContentWhitespace != false)
+ return;
+
+ if (whitespacetext.nodeName != "#text")
+ return;
+
+ if (whitespacetext.nodeValue != " ")
+ return;
+
+ if (whitespacetext.nodeType != 3)
+ return;
+
+ if (whitespacetext.parentNode.nodeName != "item")
+ return;
+
+ if (whitespacetext.childNodes.length != 0)
+ return;
+
+ if (whitespacetext.firstChild != null)
+ return;
+
+ if (whitespacetext.lastChild != null)
+ return;
+
+ if (whitespacetext.previousSibling != null)
+ return;
+
+ if (whitespacetext.nextSibling != null)
+ return;
+
+ if (whitespacetext.attributes != null)
+ return;
+
+ if (whitespacetext.wholeText != " ")
+ return;
+
+ if (whitespacetext.data != " ")
+ return;
+
+ if (whitespacetext.length != 3)
+ return;
+
+ if (whitespacetext.isElementContentWhitespace != true)
+ return;
+
+ xmlTest = true;
+ }
+
+ function checkXML(document)
+ {
+ checkText(document.documentElement.childNodes[0].childNodes[0],
+ document.documentElement.childNodes[1].childNodes[0]);
+
+ }
+ }
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+
+ x.open("GET", "text.xml");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.DONE) {
+
+ dataOK = true;
+
+ if (x.responseXML != null)
+ checkXML(x.responseXML);
+
+ }
+ }
+
+ x.send()
+ }
+}
+
+
+
+
diff --git a/tests/auto/declarative/qmlxmlhttprequest/data/text.xml b/tests/auto/declarative/qmlxmlhttprequest/data/text.xml
new file mode 100644
index 0000000..e741688
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/data/text.xml
@@ -0,0 +1 @@
+<root><item>Hello world!</item><item> </item></root>
diff --git a/tests/auto/declarative/qmlxmlhttprequest/qmlxmlhttprequest.pro b/tests/auto/declarative/qmlxmlhttprequest/qmlxmlhttprequest.pro
new file mode 100644
index 0000000..ed87b2a
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/qmlxmlhttprequest.pro
@@ -0,0 +1,13 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative network
+macx:CONFIG -= app_bundle
+
+INCLUDEPATH += ../shared/
+HEADERS += ../shared/testhttpserver.h
+
+SOURCES += tst_qmlxmlhttprequest.cpp \
+ ../shared/testhttpserver.cpp
+
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlxmlhttprequest/tst_qmlxmlhttprequest.cpp b/tests/auto/declarative/qmlxmlhttprequest/tst_qmlxmlhttprequest.cpp
new file mode 100644
index 0000000..df5442c
--- /dev/null
+++ b/tests/auto/declarative/qmlxmlhttprequest/tst_qmlxmlhttprequest.cpp
@@ -0,0 +1,1315 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlEngine>
+#include <QmlComponent>
+#include <QDebug>
+#include <QNetworkCookieJar>
+#include "testhttpserver.h"
+
+#define SERVER_PORT 14445
+
+class tst_xmlhttprequest : public QObject
+{
+ Q_OBJECT
+public:
+ tst_xmlhttprequest() {}
+
+private slots:
+ void initTestCase() {
+ if (QLocale::system().name().replace(QChar::fromAscii('_'),QChar::fromAscii('-')) != QLatin1String("en-US")) {
+ qWarning() << "Test will fail unless LANG is en_US";
+ }
+ }
+
+ void domExceptionCodes();
+ void callbackException();
+ void callbackException_data();
+ void staticStateValues();
+ void instanceStateValues();
+ void constructor();
+ void defaultState();
+ void open();
+ void open_invalid_method();
+ void open_sync();
+ void open_arg_count();
+ void setRequestHeader();
+ void setRequestHeader_unsent();
+ void setRequestHeader_illegalName_data();
+ void setRequestHeader_illegalName();
+ void setRequestHeader_sent();
+ void setRequestHeader_args();
+ void send_unsent();
+ void send_alreadySent();
+ void send_ignoreData();
+ void send_withdata();
+ void abort();
+ void abort_unsent();
+ void abort_opened();
+ void getResponseHeader();
+ void getResponseHeader_unsent();
+ void getResponseHeader_sent();
+ void getResponseHeader_args();
+ void getAllResponseHeaders();
+ void getAllResponseHeaders_unsent();
+ void getAllResponseHeaders_sent();
+ void getAllResponseHeaders_args();
+ void status();
+ void statusText();
+ void responseText();
+ void responseXML_invalid();
+ void invalidMethodUsage();
+ void redirects();
+
+ // Attributes
+ void document();
+ void element();
+ void attr();
+ void text();
+ void cdata();
+
+ // Crashes
+ // void outstanding_request_at_shutdown();
+
+ // void network_errors()
+ // void readyState()
+
+private:
+ QmlEngine engine;
+};
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
+}
+
+// Test that the dom exception codes are correct
+void tst_xmlhttprequest::domExceptionCodes()
+{
+ QmlComponent component(&engine, TEST_FILE("domExceptionCodes.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("index_size_err").toInt(), 1);
+ QCOMPARE(object->property("domstring_size_err").toInt(), 2);
+ QCOMPARE(object->property("hierarchy_request_err").toInt(), 3);
+ QCOMPARE(object->property("wrong_document_err").toInt(), 4);
+ QCOMPARE(object->property("invalid_character_err").toInt(), 5);
+ QCOMPARE(object->property("no_data_allowed_err").toInt(), 6);
+ QCOMPARE(object->property("no_modification_allowed_err").toInt(), 7);
+ QCOMPARE(object->property("not_found_err").toInt(), 8);
+ QCOMPARE(object->property("not_supported_err").toInt(), 9);
+ QCOMPARE(object->property("inuse_attribute_err").toInt(), 10);
+ QCOMPARE(object->property("invalid_state_err").toInt(), 11);
+ QCOMPARE(object->property("syntax_err").toInt(), 12);
+ QCOMPARE(object->property("invalid_modification_err").toInt(), 13);
+ QCOMPARE(object->property("namespace_err").toInt(), 14);
+ QCOMPARE(object->property("invalid_access_err").toInt(), 15);
+ QCOMPARE(object->property("validation_err").toInt(), 16);
+ QCOMPARE(object->property("type_mismatch_err").toInt(), 17);
+
+ delete object;
+}
+
+#define TRY_WAIT(expr) \
+ do { \
+ for (int ii = 0; ii < 6; ++ii) { \
+ if ((expr)) break; \
+ QTest::qWait(50); \
+ } \
+ QVERIFY((expr)); \
+ } while (false)
+
+
+void tst_xmlhttprequest::callbackException_data()
+{
+ QTest::addColumn<QString>("which");
+ QTest::addColumn<int>("line");
+
+ QTest::newRow("on-opened") << "1" << 15;
+ QTest::newRow("on-loading") << "3" << 15;
+ QTest::newRow("on-done") << "4" << 15;
+}
+
+void tst_xmlhttprequest::callbackException()
+{
+ // Test exception reporting for exceptions thrown at various points.
+
+ QFETCH(QString, which);
+ QFETCH(int, line);
+
+ QString expect = TEST_FILE("callbackException.qml").toString() + ":"+QString::number(line)+": Error: Exception from Callback";
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+
+ QmlComponent component(&engine, TEST_FILE("callbackException.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "testdocument.html");
+ object->setProperty("which", which);
+ component.completeCreate();
+
+ TRY_WAIT(object->property("threw").toBool() == true);
+
+ delete object;
+}
+
+// Test that the state value properties on the XMLHttpRequest constructor have the correct values.
+// ### WebKit does not do this, but it seems to fit the standard and QML better
+void tst_xmlhttprequest::staticStateValues()
+{
+ QmlComponent component(&engine, TEST_FILE("staticStateValues.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("unsent").toInt(), 0);
+ QCOMPARE(object->property("opened").toInt(), 1);
+ QCOMPARE(object->property("headers_received").toInt(), 2);
+ QCOMPARE(object->property("loading").toInt(), 3);
+ QCOMPARE(object->property("done").toInt(), 4);
+
+ delete object;
+}
+
+// Test that the state value properties on instances have the correct values.
+void tst_xmlhttprequest::instanceStateValues()
+{
+ QmlComponent component(&engine, TEST_FILE("instanceStateValues.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("unsent").toInt(), 0);
+ QCOMPARE(object->property("opened").toInt(), 1);
+ QCOMPARE(object->property("headers_received").toInt(), 2);
+ QCOMPARE(object->property("loading").toInt(), 3);
+ QCOMPARE(object->property("done").toInt(), 4);
+
+ delete object;
+}
+
+// Test calling constructor
+void tst_xmlhttprequest::constructor()
+{
+ QmlComponent component(&engine, TEST_FILE("constructor.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("calledAsConstructor").toBool(), true);
+ QCOMPARE(object->property("calledAsFunction").toBool(), true);
+
+ delete object;
+}
+
+// Test that all the properties are set correctly before any request is sent
+void tst_xmlhttprequest::defaultState()
+{
+ QmlComponent component(&engine, TEST_FILE("defaultState.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("readState").toInt(), 0);
+ QCOMPARE(object->property("statusIsException").toBool(), true);
+ QCOMPARE(object->property("statusTextIsException").toBool(), true);
+ QCOMPARE(object->property("responseText").toString(), QString());
+ QCOMPARE(object->property("responseXMLIsNull").toBool(), true);
+
+ delete object;
+}
+
+// Test valid XMLHttpRequest.open() calls
+void tst_xmlhttprequest::open()
+{
+ // Relative url
+ {
+ QmlComponent component(&engine, TEST_FILE("open.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // Absolute url
+ {
+ QmlComponent component(&engine, TEST_FILE("open.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", TEST_FILE("testdocument.html").toString());
+ component.completeCreate();
+
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // Absolute network url
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("open_network.expect"),
+ TEST_FILE("open_network.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("open.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // User/pass
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("open_network.expect"),
+ TEST_FILE("open_network.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("open_user.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ // ### Check that the username/password were sent to the server
+
+ delete object;
+ }
+}
+
+// Test that calling XMLHttpRequest.open() with an invalid method raises an exception
+void tst_xmlhttprequest::open_invalid_method()
+{
+ QmlComponent component(&engine, TEST_FILE("open_invalid_method.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("exceptionThrown").toBool(), true);
+
+ delete object;
+}
+
+// Test that calling XMLHttpRequest.open() with sync raises an exception
+void tst_xmlhttprequest::open_sync()
+{
+ QmlComponent component(&engine, TEST_FILE("open_sync.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("exceptionThrown").toBool(), true);
+
+ delete object;
+}
+
+// Calling with incorrect arg count raises an exception
+void tst_xmlhttprequest::open_arg_count()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("open_arg_count.1.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("exceptionThrown").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("open_arg_count.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("exceptionThrown").toBool(), true);
+
+ delete object;
+ }
+}
+
+// Test valid setRequestHeader() calls
+void tst_xmlhttprequest::setRequestHeader()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("setRequestHeader.expect"),
+ TEST_FILE("setRequestHeader.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("setRequestHeader.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+}
+
+// Test setting headers before open() throws exception
+void tst_xmlhttprequest::setRequestHeader_unsent()
+{
+ QmlComponent component(&engine, TEST_FILE("setRequestHeader_unsent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
+void tst_xmlhttprequest::setRequestHeader_illegalName_data()
+{
+ QTest::addColumn<QString>("name");
+
+ QTest::newRow("Accept-Charset") << "AccePT-CHArset";
+ QTest::newRow("Accept-Encoding") << "AccEpt-EnCOding";
+ QTest::newRow("Connection") << "ConnECtion";
+ QTest::newRow("Content-Length") << "ContEnt-LenGth";
+ QTest::newRow("Cookie") << "CookIe";
+ QTest::newRow("Cookie2") << "CoOkie2";
+ QTest::newRow("Content-Transfer-Encoding") << "ConteNT-tRANSFER-eNCOding";
+ QTest::newRow("Date") << "DaTE";
+ QTest::newRow("Expect") << "ExPect";
+ QTest::newRow("Host") << "HoST";
+ QTest::newRow("Keep-Alive") << "KEEP-aLive";
+ QTest::newRow("Referer") << "ReferEr";
+ QTest::newRow("TE") << "Te";
+ QTest::newRow("Trailer") << "TraILEr";
+ QTest::newRow("Transfer-Encoding") << "tRANsfer-Encoding";
+ QTest::newRow("Upgrade") << "UpgrADe";
+ QTest::newRow("User-Agent") << "uSEr-Agent";
+ QTest::newRow("Via") << "vIa";
+ QTest::newRow("Proxy-") << "ProXy-";
+ QTest::newRow("Sec-") << "SeC-";
+ QTest::newRow("Proxy-*") << "Proxy-BLAH";
+ QTest::newRow("Sec-*") << "Sec-F";
+}
+
+// Tests that using illegal header names has no effect
+void tst_xmlhttprequest::setRequestHeader_illegalName()
+{
+ QFETCH(QString, name);
+
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("open_network.expect"),
+ TEST_FILE("open_network.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("setRequestHeader_illegalName.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("header", name);
+ component.completeCreate();
+
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+}
+
+// Test that attempting to set a header after a request is sent throws an exception
+void tst_xmlhttprequest::setRequestHeader_sent()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("open_network.expect"),
+ TEST_FILE("open_network.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("setRequestHeader_sent.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+}
+
+// Invalid arg count throws exception
+void tst_xmlhttprequest::setRequestHeader_args()
+{
+ QmlComponent component(&engine, TEST_FILE("setRequestHeader_args.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("exceptionThrown").toBool(), true);
+
+ delete object;
+}
+
+// Test that calling send() in UNSENT state throws an exception
+void tst_xmlhttprequest::send_unsent()
+{
+ QmlComponent component(&engine, TEST_FILE("send_unsent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
+// Test attempting to resend a sent request throws an exception
+void tst_xmlhttprequest::send_alreadySent()
+{
+ QmlComponent component(&engine, TEST_FILE("send_alreadySent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+}
+
+// Test that send for a GET or HEAD ignores data
+void tst_xmlhttprequest::send_ignoreData()
+{
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_ignoreData_GET.expect"),
+ TEST_FILE("send_ignoreData.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_ignoreData.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("reqType", "GET");
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_ignoreData_PUT.expect"),
+ TEST_FILE("send_ignoreData.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_ignoreData.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("reqType", "HEAD");
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+}
+
+// Test that send()'ing data works
+void tst_xmlhttprequest::send_withdata()
+{
+ // No content-type
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_data.1.expect"),
+ TEST_FILE("send_data.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_data.1.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // Correct content-type
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_data.1.expect"),
+ TEST_FILE("send_data.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_data.2.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // Incorrect content-type
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_data.1.expect"),
+ TEST_FILE("send_data.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_data.3.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // Correct content-type - out of order
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_data.4.expect"),
+ TEST_FILE("send_data.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_data.4.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // Incorrect content-type - out of order
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_data.4.expect"),
+ TEST_FILE("send_data.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_data.5.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // PUT
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_data.6.expect"),
+ TEST_FILE("send_data.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_data.6.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+
+ // Correct content-type - no charset
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_data.1.expect"),
+ TEST_FILE("send_data.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("send_data.7.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
+}
+
+// Test abort() has no effect in unsent state
+void tst_xmlhttprequest::abort_unsent()
+{
+ QmlComponent component(&engine, TEST_FILE("abort_unsent.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+}
+
+// Test abort() cancels an open (but unsent) request
+void tst_xmlhttprequest::abort_opened()
+{
+ QmlComponent component(&engine, TEST_FILE("abort_opened.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+}
+
+// Test abort() aborts in progress send
+void tst_xmlhttprequest::abort()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("abort.expect"),
+ TEST_FILE("abort.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("abort.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("urlDummy", "http://127.0.0.1:14449/testdocument.html");
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("seenDone").toBool(), true);
+ QCOMPARE(object->property("didNotSeeUnsent").toBool(), true);
+ QCOMPARE(object->property("endStateUnsent").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ delete object;
+}
+
+void tst_xmlhttprequest::getResponseHeader()
+{
+ QmlEngine engine; // Avoid cookie contamination
+
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("getResponseHeader.expect"),
+ TEST_FILE("getResponseHeader.reply"),
+ TEST_FILE("testdocument.html")));
+
+
+ QmlComponent component(&engine, TEST_FILE("getResponseHeader.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("unsentException").toBool(), true);
+ QCOMPARE(object->property("openedException").toBool(), true);
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("headersReceivedState").toBool(), true);
+ QCOMPARE(object->property("headersReceivedNullHeader").toBool(), true);
+ QCOMPARE(object->property("headersReceivedValidHeader").toBool(), true);
+ QCOMPARE(object->property("headersReceivedMultiValidHeader").toBool(), true);
+ QCOMPARE(object->property("headersReceivedCookieHeader").toBool(), true);
+
+ QCOMPARE(object->property("doneState").toBool(), true);
+ QCOMPARE(object->property("doneNullHeader").toBool(), true);
+ QCOMPARE(object->property("doneValidHeader").toBool(), true);
+ QCOMPARE(object->property("doneMultiValidHeader").toBool(), true);
+ QCOMPARE(object->property("doneCookieHeader").toBool(), true);
+
+ delete object;
+}
+
+// Test getResponseHeader throws an exception in an invalid state
+void tst_xmlhttprequest::getResponseHeader_unsent()
+{
+ QmlComponent component(&engine, TEST_FILE("getResponseHeader_unsent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
+// Test getResponseHeader throws an exception in an invalid state
+void tst_xmlhttprequest::getResponseHeader_sent()
+{
+ QmlComponent component(&engine, TEST_FILE("getResponseHeader_sent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
+// Invalid arg count throws exception
+void tst_xmlhttprequest::getResponseHeader_args()
+{
+ QmlComponent component(&engine, TEST_FILE("getResponseHeader_args.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("exceptionThrown").toBool() == true);
+
+ delete object;
+}
+
+void tst_xmlhttprequest::getAllResponseHeaders()
+{
+ QmlEngine engine; // Avoid cookie contamination
+
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("getResponseHeader.expect"),
+ TEST_FILE("getResponseHeader.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("getAllResponseHeaders.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ QCOMPARE(object->property("unsentException").toBool(), true);
+ QCOMPARE(object->property("openedException").toBool(), true);
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("openedState").toBool(), true);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("headersReceivedState").toBool(), true);
+ QCOMPARE(object->property("headersReceivedHeader").toBool(), true);
+
+ QCOMPARE(object->property("doneState").toBool(), true);
+ QCOMPARE(object->property("doneHeader").toBool(), true);
+
+ delete object;
+}
+
+// Test getAllResponseHeaders throws an exception in an invalid state
+void tst_xmlhttprequest::getAllResponseHeaders_unsent()
+{
+ QmlComponent component(&engine, TEST_FILE("getAllResponseHeaders_unsent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
+// Test getAllResponseHeaders throws an exception in an invalid state
+void tst_xmlhttprequest::getAllResponseHeaders_sent()
+{
+ QmlComponent component(&engine, TEST_FILE("getAllResponseHeaders_sent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
+// Invalid arg count throws exception
+void tst_xmlhttprequest::getAllResponseHeaders_args()
+{
+ QmlComponent component(&engine, TEST_FILE("getAllResponseHeaders_args.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("exceptionThrown").toBool() == true);
+
+ delete object;
+}
+
+void tst_xmlhttprequest::status()
+{
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("status.expect"),
+ TEST_FILE("status.200.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("status.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("expectedStatus", 200);
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("unsentException").toBool(), true);
+ QCOMPARE(object->property("openedException").toBool(), true);
+ QCOMPARE(object->property("sentException").toBool(), true);
+ QCOMPARE(object->property("headersReceived").toBool(), true);
+ QCOMPARE(object->property("loading").toBool(), true);
+ QCOMPARE(object->property("done").toBool(), true);
+ QCOMPARE(object->property("resetException").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("status.expect"),
+ TEST_FILE("status.404.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("status.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("expectedStatus", 404);
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("unsentException").toBool(), true);
+ QCOMPARE(object->property("openedException").toBool(), true);
+ QCOMPARE(object->property("sentException").toBool(), true);
+ QCOMPARE(object->property("headersReceived").toBool(), true);
+ QCOMPARE(object->property("loading").toBool(), true);
+ QCOMPARE(object->property("done").toBool(), true);
+ QCOMPARE(object->property("resetException").toBool(), true);
+
+ delete object;
+ }
+}
+
+void tst_xmlhttprequest::statusText()
+{
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("status.expect"),
+ TEST_FILE("status.200.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("statusText.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("expectedStatus", "OK");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("unsentException").toBool(), true);
+ QCOMPARE(object->property("openedException").toBool(), true);
+ QCOMPARE(object->property("sentException").toBool(), true);
+ QCOMPARE(object->property("headersReceived").toBool(), true);
+ QCOMPARE(object->property("loading").toBool(), true);
+ QCOMPARE(object->property("done").toBool(), true);
+ QCOMPARE(object->property("resetException").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("status.expect"),
+ TEST_FILE("status.404.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("statusText.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("expectedStatus", "Document not found");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("unsentException").toBool(), true);
+ QCOMPARE(object->property("openedException").toBool(), true);
+ QCOMPARE(object->property("sentException").toBool(), true);
+ QCOMPARE(object->property("headersReceived").toBool(), true);
+ QCOMPARE(object->property("loading").toBool(), true);
+ QCOMPARE(object->property("done").toBool(), true);
+ QCOMPARE(object->property("resetException").toBool(), true);
+
+ delete object;
+ }
+}
+
+void tst_xmlhttprequest::responseText()
+{
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("status.expect"),
+ TEST_FILE("status.200.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("responseText.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("expectedText", "QML Rocks!\n");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("unsent").toBool(), true);
+ QCOMPARE(object->property("opened").toBool(), true);
+ QCOMPARE(object->property("sent").toBool(), true);
+ QCOMPARE(object->property("headersReceived").toBool(), true);
+ QCOMPARE(object->property("loading").toBool(), true);
+ QCOMPARE(object->property("done").toBool(), true);
+ QCOMPARE(object->property("reset").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("status.expect"),
+ TEST_FILE("status.200.reply"),
+ QUrl()));
+
+ QmlComponent component(&engine, TEST_FILE("responseText.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("expectedText", "");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("unsent").toBool(), true);
+ QCOMPARE(object->property("opened").toBool(), true);
+ QCOMPARE(object->property("sent").toBool(), true);
+ QCOMPARE(object->property("headersReceived").toBool(), true);
+ QCOMPARE(object->property("loading").toBool(), true);
+ QCOMPARE(object->property("done").toBool(), true);
+ QCOMPARE(object->property("reset").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("status.expect"),
+ TEST_FILE("status.404.reply"),
+ TEST_FILE("testdocument.html")));
+
+ QmlComponent component(&engine, TEST_FILE("responseText.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ object->setProperty("expectedText", "");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("unsent").toBool(), true);
+ QCOMPARE(object->property("opened").toBool(), true);
+ QCOMPARE(object->property("sent").toBool(), true);
+ QCOMPARE(object->property("headersReceived").toBool(), true);
+ QCOMPARE(object->property("loading").toBool(), true);
+ QCOMPARE(object->property("done").toBool(), true);
+ QCOMPARE(object->property("reset").toBool(), true);
+
+ delete object;
+ }
+}
+
+// Test that calling hte XMLHttpRequest methods on a non-XMLHttpRequest object
+// throws an exception
+void tst_xmlhttprequest::invalidMethodUsage()
+{
+ QmlComponent component(&engine, TEST_FILE("invalidMethodUsage.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("onreadystatechange").toBool(), true);
+ QCOMPARE(object->property("readyState").toBool(), true);
+ QCOMPARE(object->property("status").toBool(), true);
+ QCOMPARE(object->property("statusText").toBool(), true);
+ QCOMPARE(object->property("responseText").toBool(), true);
+ QCOMPARE(object->property("responseXML").toBool(), true);
+
+ QCOMPARE(object->property("open").toBool(), true);
+ QCOMPARE(object->property("setRequestHeader").toBool(), true);
+ QCOMPARE(object->property("send").toBool(), true);
+ QCOMPARE(object->property("abort").toBool(), true);
+ QCOMPARE(object->property("getResponseHeader").toBool(), true);
+ QCOMPARE(object->property("getAllResponseHeaders").toBool(), true);
+
+ delete object;
+}
+
+// Test that XMLHttpRequest transparently redirects
+void tst_xmlhttprequest::redirects()
+{
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirecttarget.html");
+ server.serveDirectory("data");
+
+ QmlComponent component(&engine, TEST_FILE("redirects.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
+ object->setProperty("expectedText", "");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("done").toBool() == true);
+ QCOMPARE(object->property("dataOK").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirectmissing.html");
+ server.serveDirectory("data");
+
+ QmlComponent component(&engine, TEST_FILE("redirectError.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
+ object->setProperty("expectedText", "");
+ component.completeCreate();
+
+ TRY_WAIT(object->property("done").toBool() == true);
+ QCOMPARE(object->property("dataOK").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirect.html");
+ server.serveDirectory("data");
+
+ QmlComponent component(&engine, TEST_FILE("redirectRecur.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
+ object->setProperty("expectedText", "");
+ component.completeCreate();
+
+ for (int ii = 0; ii < 60; ++ii) {
+ if (object->property("done").toBool()) break;
+ QTest::qWait(50);
+ }
+ QVERIFY(object->property("done").toBool() == true);
+
+ QCOMPARE(object->property("dataOK").toBool(), true);
+
+ delete object;
+ }
+}
+
+void tst_xmlhttprequest::responseXML_invalid()
+{
+ QmlComponent component(&engine, TEST_FILE("responseXML_invalid.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("xmlNull").toBool(), true);
+
+ delete object;
+}
+
+// Test the Document DOM element
+void tst_xmlhttprequest::document()
+{
+ QmlComponent component(&engine, TEST_FILE("document.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("xmlTest").toBool(), true);
+
+ delete object;
+}
+
+// Test the Element DOM element
+void tst_xmlhttprequest::element()
+{
+ QmlComponent component(&engine, TEST_FILE("element.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("xmlTest").toBool(), true);
+
+ delete object;
+}
+
+// Test the Attr DOM element
+void tst_xmlhttprequest::attr()
+{
+ QmlComponent component(&engine, TEST_FILE("attr.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("xmlTest").toBool(), true);
+
+ delete object;
+}
+
+// Test the Text DOM element
+void tst_xmlhttprequest::text()
+{
+ QmlComponent component(&engine, TEST_FILE("text.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("xmlTest").toBool(), true);
+
+ delete object;
+}
+
+// Test the CDataSection DOM element
+void tst_xmlhttprequest::cdata()
+{
+ QmlComponent component(&engine, TEST_FILE("cdata.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ TRY_WAIT(object->property("dataOK").toBool() == true);
+
+ QCOMPARE(object->property("xmlTest").toBool(), true);
+
+ delete object;
+}
+
+QTEST_MAIN(tst_xmlhttprequest)
+
+#include "tst_qmlxmlhttprequest.moc"
diff --git a/tests/auto/declarative/qmlxmllistmodel/data/model.qml b/tests/auto/declarative/qmlxmllistmodel/data/model.qml
new file mode 100644
index 0000000..2cbb027
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/data/model.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "name/string()" }
+ XmlRole { name: "type"; query: "type/string()" }
+ XmlRole { name: "age"; query: "age/number()" }
+ XmlRole { name: "size"; query: "size/string()" }
+}
diff --git a/tests/auto/declarative/qmlxmllistmodel/data/model.xml b/tests/auto/declarative/qmlxmllistmodel/data/model.xml
new file mode 100644
index 0000000..40cd6d0
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/data/model.xml
@@ -0,0 +1,54 @@
+<Pets>
+ <Pet>
+ <name>Polly</name>
+ <type>Parrot</type>
+ <age>12</age>
+ <size>Small</size>
+ </Pet>
+ <Pet>
+ <name>Penny</name>
+ <type>Turtle</type>
+ <age>4</age>
+ <size>Small</size>
+ </Pet>
+ <Pet>
+ <name>Warren</name>
+ <type>Rabbit</type>
+ <age>2</age>
+ <size>Small</size>
+ </Pet>
+ <Pet>
+ <name>Spot</name>
+ <type>Dog</type>
+ <age>9</age>
+ <size>Medium</size>
+ </Pet>
+ <Pet>
+ <name>Whiskers</name>
+ <type>Cat</type>
+ <age>2</age>
+ <size>Medium</size>
+ </Pet>
+ <Pet>
+ <name>Joey</name>
+ <type>Kangaroo</type>
+ <age>1</age>
+ </Pet>
+ <Pet>
+ <name>Kimba</name>
+ <type>Bunny</type>
+ <age>65</age>
+ <size>Large</size>
+ </Pet>
+ <Pet>
+ <name>Rover</name>
+ <type>Dog</type>
+ <size>Large</size>
+ </Pet>
+ <Pet>
+ <name>Tiny</name>
+ <type>Elephant</type>
+ <age>15</age>
+ <size>Large</size>
+ </Pet>
+</Pets>
diff --git a/tests/auto/declarative/qmlxmllistmodel/data/model2.qml b/tests/auto/declarative/qmlxmllistmodel/data/model2.qml
new file mode 100644
index 0000000..140e0ad
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/data/model2.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "name/string()" }
+ XmlRole { name: "type"; query: "type/string()" }
+ XmlRole { name: "age"; query: "age/number()" }
+ XmlRole { name: "size"; query: "size/string()" }
+ XmlRole { name: "tricks"; query: "tricks/string()" }
+}
diff --git a/tests/auto/declarative/qmlxmllistmodel/data/recipes.qml b/tests/auto/declarative/qmlxmllistmodel/data/recipes.qml
new file mode 100644
index 0000000..13dea91
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/data/recipes.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "recipes.xml"
+ query: "/recipes/recipe"
+ XmlRole { name: "title"; query: "@title/string()" }
+ XmlRole { name: "picture"; query: "picture/string()" }
+ XmlRole { name: "ingredients"; query: "ingredients/string()" }
+ XmlRole { name: "preparation"; query: "method/string()" }
+}
diff --git a/tests/auto/declarative/qmlxmllistmodel/data/recipes.xml b/tests/auto/declarative/qmlxmllistmodel/data/recipes.xml
new file mode 100644
index 0000000..d71de60
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/data/recipes.xml
@@ -0,0 +1,90 @@
+<recipes>
+ <recipe title="Pancakes">
+ <picture>content/pics/pancakes.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 1 cup (150g) self-raising flour
+ <li> 1 tbs caster sugar
+ <li> 3/4 cup (185ml) milk
+ <li> 1 egg
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
+ <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
+ <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
+ <li> Turn over and cook other side until golden.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+ <recipe title="Fruit Salad">
+ <picture>content/pics/fruit-salad.jpg</picture>
+ <ingredients><![CDATA[* Seasonal Fruit]]></ingredients>
+ <method><![CDATA[* Chop fruit and place in a bowl.]]></method>
+ </recipe>
+ <recipe title="Vegetable Soup">
+ <picture>content/pics/vegetable-soup.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 1 onion
+ <li> 1 turnip
+ <li> 1 potato
+ <li> 1 carrot
+ <li> 1 head of celery
+ <li> 1 1/2 litres of water
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Chop vegetables.
+ <li> Boil in water until vegetables soften.
+ <li> Season with salt and pepper to taste.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+ <recipe title="Hamburger">
+ <picture>content/pics/hamburger.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 500g minced beef
+ <li> Seasoning
+ <li> lettuce, tomato, onion, cheese
+ <li> 1 hamburger bun for each burger
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Mix the beef, together with seasoning, in a food processor.
+ <li> Shape the beef into burgers.
+ <li> Grill the burgers for about 5 mins on each side (until cooked through)
+ <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+ <recipe title="Lemonade">
+ <picture>content/pics/lemonade.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 1 cup Lemon Juice
+ <li> 1 cup Sugar
+ <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
+ <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
+ <li> Chill or serve over ice cubes.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+</recipes>
diff --git a/tests/auto/declarative/qmlxmllistmodel/data/roleErrors.qml b/tests/auto/declarative/qmlxmllistmodel/data/roleErrors.qml
new file mode 100644
index 0000000..26c533f
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/data/roleErrors.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "/name/string()" } //starts with '/'
+ XmlRole { name: "type"; query: "type" } //no type
+ XmlRole { name: "age"; query: "age/" } //ends with '/'
+ XmlRole { name: "size"; query: "size/number()" } //wrong type
+}
diff --git a/tests/auto/declarative/qmlxmllistmodel/data/unique.qml b/tests/auto/declarative/qmlxmllistmodel/data/unique.qml
new file mode 100644
index 0000000..ed0f293
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/data/unique.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "name/string()" }
+ XmlRole { name: "name"; query: "type/string()" }
+}
diff --git a/tests/auto/declarative/qmlxmllistmodel/qmlxmllistmodel.pro b/tests/auto/declarative/qmlxmllistmodel/qmlxmllistmodel.pro
new file mode 100644
index 0000000..8e58a32
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/qmlxmllistmodel.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+contains(QT_CONFIG,xmlpatterns) {
+ QT += xmlpatterns
+ DEFINES += QTEST_XMLPATTERNS
+}
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlxmllistmodel.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp b/tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp
new file mode 100644
index 0000000..966d7de
--- /dev/null
+++ b/tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+
+#ifdef QTEST_XMLPATTERNS
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlxmllistmodel_p.h>
+#include "../../../shared/util.h"
+
+class tst_qmlxmllistmodel : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlxmllistmodel() {}
+
+private slots:
+ void buildModel();
+ void missingFields();
+ void cdata();
+ void attributes();
+ void roles();
+ void roleErrors();
+ void uniqueRoleNames();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_qmlxmllistmodel::buildModel()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model.qml"));
+ QmlXmlListModel *listModel = qobject_cast<QmlXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles;
+ roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3;
+ QHash<int, QVariant> data = listModel->data(3, roles);
+ QVERIFY(data.count() == 4);
+ QCOMPARE(data.value(Qt::UserRole).toString(), QLatin1String("Spot"));
+ QCOMPARE(data.value(Qt::UserRole+1).toString(), QLatin1String("Dog"));
+ QCOMPARE(data.value(Qt::UserRole+2).toInt(), 9);
+ QCOMPARE(data.value(Qt::UserRole+3).toString(), QLatin1String("Medium"));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::missingFields()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model2.qml"));
+ QmlXmlListModel *listModel = qobject_cast<QmlXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles;
+ roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3 << Qt::UserRole + 4;
+ QHash<int, QVariant> data = listModel->data(5, roles);
+ QVERIFY(data.count() == 5);
+ QCOMPARE(data.value(Qt::UserRole+3).toString(), QLatin1String(""));
+ QCOMPARE(data.value(Qt::UserRole+4).toString(), QLatin1String(""));
+
+ data = listModel->data(7, roles);
+ QVERIFY(data.count() == 5);
+ QCOMPARE(data.value(Qt::UserRole+2).toString(), QLatin1String(""));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::cdata()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/recipes.qml"));
+ QmlXmlListModel *listModel = qobject_cast<QmlXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 5);
+
+ QList<int> roles;
+ roles << Qt::UserRole + 2;
+ QHash<int, QVariant> data = listModel->data(2, roles);
+ QVERIFY(data.count() == 1);
+ QVERIFY(data.value(Qt::UserRole+2).toString().startsWith(QLatin1String("<html>")));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::attributes()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/recipes.qml"));
+ QmlXmlListModel *listModel = qobject_cast<QmlXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 5);
+
+ QList<int> roles;
+ roles << Qt::UserRole;
+ QHash<int, QVariant> data = listModel->data(2, roles);
+ QVERIFY(data.count() == 1);
+ QCOMPARE(data.value(Qt::UserRole).toString(), QLatin1String("Vegetable Soup"));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::roles()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model.qml"));
+ QmlXmlListModel *listModel = qobject_cast<QmlXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles = listModel->roles();
+ QCOMPARE(roles.count(), 4);
+ QCOMPARE(listModel->toString(roles.at(0)), QLatin1String("name"));
+ QCOMPARE(listModel->toString(roles.at(1)), QLatin1String("type"));
+ QCOMPARE(listModel->toString(roles.at(2)), QLatin1String("age"));
+ QCOMPARE(listModel->toString(roles.at(3)), QLatin1String("size"));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::roleErrors()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleErrors.qml"));
+ QTest::ignoreMessage(QtWarningMsg, QString("QML XmlRole (" + QUrl::fromLocalFile(SRCDIR "/data/roleErrors.qml").toString() + ":6:5) An XmlRole query must not start with '/'").toUtf8().constData());
+ //### make sure we receive all expected warning messages.
+ QmlXmlListModel *listModel = qobject_cast<QmlXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles;
+ roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3;
+ QHash<int, QVariant> data = listModel->data(3, roles);
+ QVERIFY(data.count() == 4);
+
+ //### should any of these return valid values?
+ QCOMPARE(data.value(Qt::UserRole), QVariant());
+ QCOMPARE(data.value(Qt::UserRole+1), QVariant());
+ QCOMPARE(data.value(Qt::UserRole+2), QVariant());
+
+ QEXPECT_FAIL("", "QT-2456", Continue);
+ QCOMPARE(data.value(Qt::UserRole+3), QVariant());
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::uniqueRoleNames()
+{
+ QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/unique.qml"));
+ QTest::ignoreMessage(QtWarningMsg, QString("QML XmlRole (" + QUrl::fromLocalFile(SRCDIR "/data/unique.qml").toString() + ":7:5) \"name\" duplicates a previous role name and will be disabled.").toUtf8().constData());
+ QmlXmlListModel *listModel = qobject_cast<QmlXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles = listModel->roles();
+ QCOMPARE(roles.count(), 1);
+
+ delete listModel;
+}
+
+QTEST_MAIN(tst_qmlxmllistmodel)
+
+#include "tst_qmlxmllistmodel.moc"
+
+#else
+QTEST_NOOP_MAIN
+#endif
diff --git a/tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro b/tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro
new file mode 100644
index 0000000..f42cecc
--- /dev/null
+++ b/tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += network declarative
+macx:CONFIG -= app_bundle
+
+HEADERS += ../shared/debugutil_p.h
+SOURCES += tst_qpacketprotocol.cpp \
+ ../shared/debugutil.cpp
diff --git a/tests/auto/declarative/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/declarative/qpacketprotocol/tst_qpacketprotocol.cpp
new file mode 100644
index 0000000..60631d2
--- /dev/null
+++ b/tests/auto/declarative/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QSignalSpy>
+#include <QTimer>
+#include <QTcpSocket>
+#include <QTcpServer>
+#include <QDebug>
+#include <QBuffer>
+
+#include <private/qpacketprotocol_p.h>
+
+#include "../shared/debugutil_p.h"
+
+class tst_QPacketProtocol : public QObject
+{
+ Q_OBJECT
+
+private:
+ QTcpServer *m_server;
+ QTcpSocket *m_client;
+ QTcpSocket *m_serverConn;
+
+private slots:
+ void init();
+ void cleanup();
+
+ void maximumPacketSize();
+ void setMaximumPacketSize();
+ void setMaximumPacketSize_data();
+ void send();
+ void send_data();
+ void packetsAvailable();
+ void packetsAvailable_data();
+ void clear();
+ void read();
+ void device();
+
+ void tst_QPacket_clear();
+};
+
+void tst_QPacketProtocol::init()
+{
+ m_server = new QTcpServer(this);
+ m_serverConn = 0;
+ QVERIFY(m_server->listen(QHostAddress("127.0.0.1")));
+
+ m_client = new QTcpSocket(this);
+ m_client->connectToHost(m_server->serverAddress(), m_server->serverPort());
+
+ QVERIFY(m_client->waitForConnected());
+ QVERIFY(m_server->waitForNewConnection());
+ m_serverConn = m_server->nextPendingConnection();
+}
+
+void tst_QPacketProtocol::cleanup()
+{
+ delete m_client;
+ delete m_serverConn;
+ delete m_server;
+}
+
+void tst_QPacketProtocol::maximumPacketSize()
+{
+ QPacketProtocol p(m_client);
+ QCOMPARE(p.maximumPacketSize(), 0x7FFFFFFF);
+}
+
+void tst_QPacketProtocol::setMaximumPacketSize()
+{
+ QFETCH(qint32, size);
+ QFETCH(qint32, expected);
+
+ QPacketProtocol out(m_serverConn);
+ QCOMPARE(out.setMaximumPacketSize(size), expected);
+
+ if (size == expected) {
+ QPacketProtocol in(m_client);
+ QByteArray b;
+ b.fill('a', size + 1);
+ out.send() << b.constData();
+ QVERIFY(QmlDebugTest::waitForSignal(&in, SIGNAL(invalidPacket())));
+ }
+}
+
+void tst_QPacketProtocol::setMaximumPacketSize_data()
+{
+ QTest::addColumn<int>("size");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("invalid") << qint32(sizeof(qint32) - 1) << qint32(0x7FFFFFFF);
+ QTest::newRow("still invalid") << qint32(sizeof(qint32)) << qint32(0x7FFFFFFF);
+ QTest::newRow("valid") << qint32(sizeof(qint32) + 1) << qint32(sizeof(qint32) + 1);
+}
+
+void tst_QPacketProtocol::send()
+{
+ QFETCH(bool, useAutoSend);
+
+ QPacketProtocol in(m_client);
+ QPacketProtocol out(m_serverConn);
+
+ QByteArray ba;
+ int num;
+
+ if (useAutoSend) {
+ out.send() << "Hello world" << 123;
+ } else {
+ QPacket packet;
+ packet << "Hello world" << 123;
+ out.send(packet);
+ }
+
+ QVERIFY(QmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
+
+ QPacket p = in.read();
+ p >> ba >> num;
+ QCOMPARE(ba, QByteArray("Hello world") + '\0');
+ QCOMPARE(num, 123);
+}
+
+void tst_QPacketProtocol::send_data()
+{
+ QTest::addColumn<bool>("useAutoSend");
+
+ QTest::newRow("auto send") << true;
+ QTest::newRow("no auto send") << false;
+}
+
+void tst_QPacketProtocol::packetsAvailable()
+{
+ QFETCH(int, packetCount);
+
+ QPacketProtocol out(m_client);
+ QPacketProtocol in(m_serverConn);
+
+ QCOMPARE(out.packetsAvailable(), qint64(0));
+ QCOMPARE(in.packetsAvailable(), qint64(0));
+
+ for (int i=0; i<packetCount; i++)
+ out.send() << "Hello";
+
+ QVERIFY(QmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
+ QCOMPARE(in.packetsAvailable(), qint64(packetCount));
+}
+
+void tst_QPacketProtocol::packetsAvailable_data()
+{
+ QTest::addColumn<int>("packetCount");
+
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+ QTest::newRow("10") << 10;
+}
+
+void tst_QPacketProtocol::clear()
+{
+ QPacketProtocol in(m_client);
+ QPacketProtocol out(m_serverConn);
+
+ out.send() << 123;
+ out.send() << 456;
+ QVERIFY(QmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
+
+ in.clear();
+ QVERIFY(in.read().isEmpty());
+}
+
+void tst_QPacketProtocol::read()
+{
+ QPacketProtocol in(m_client);
+ QPacketProtocol out(m_serverConn);
+
+ QVERIFY(in.read().isEmpty());
+
+ out.send() << 123;
+ out.send() << 456;
+ QVERIFY(QmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
+
+ int num;
+
+ QPacket p1 = in.read();
+ QVERIFY(!p1.isEmpty());
+ p1 >> num;
+ QCOMPARE(num, 123);
+
+ QPacket p2 = in.read();
+ QVERIFY(!p2.isEmpty());
+ p2 >> num;
+ QCOMPARE(num, 456);
+
+ QVERIFY(in.read().isEmpty());
+}
+
+void tst_QPacketProtocol::device()
+{
+ QPacketProtocol p(m_client);
+ QCOMPARE(p.device(), m_client);
+}
+
+void tst_QPacketProtocol::tst_QPacket_clear()
+{
+ QPacketProtocol protocol(m_client);
+
+ QPacket packet;
+
+ packet << "Hello world!" << 123;
+ protocol.send(packet);
+
+ packet.clear();
+ QVERIFY(packet.isEmpty());
+ packet << "Goodbyte world!" << 789;
+ protocol.send(packet);
+
+ QByteArray ba;
+ int num;
+ QPacketProtocol in(m_serverConn);
+ QVERIFY(QmlDebugTest::waitForSignal(&in, SIGNAL(readyRead())));
+
+ QPacket p1 = in.read();
+ p1 >> ba >> num;
+ QCOMPARE(ba, QByteArray("Hello world!") + '\0');
+ QCOMPARE(num, 123);
+
+ QPacket p2 = in.read();
+ p2 >> ba >> num;
+ QCOMPARE(ba, QByteArray("Goodbyte world!") + '\0');
+ QCOMPARE(num, 789);
+}
+
+QTEST_MAIN(tst_QPacketProtocol)
+
+#include "tst_qpacketprotocol.moc"
diff --git a/tests/auto/declarative/runall.sh b/tests/auto/declarative/runall.sh
new file mode 100755
index 0000000..33087a1
--- /dev/null
+++ b/tests/auto/declarative/runall.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+Xnest :7 2>/dev/null &
+sleep 1
+trap "kill $!" EXIT
+export DISPLAY=:7
+
+make -k -j1 install 2>&1 |
+ while read line
+ do
+ case "$line" in
+ make*Error) echo "$line";;
+ make*Stop) echo "$line";;
+ make*) ;;
+ */qmake*) ;;
+ */bin/moc*) ;;
+ *targ.debug*) ;;
+ g++*) ;;
+ cd*) ;;
+ PASS*) ;;
+ QDEBUG*) ;;
+ Makefile*) ;;
+ Config*) ;;
+ Totals*) ;;
+ \**) ;;
+ ./*) ;;
+ *) echo "$line"
+ esac
+ done
+
diff --git a/tests/auto/declarative/shared/debugutil.cpp b/tests/auto/declarative/shared/debugutil.cpp
new file mode 100644
index 0000000..aa0cd31
--- /dev/null
+++ b/tests/auto/declarative/shared/debugutil.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QSignalSpy>
+#include <QEventLoop>
+#include <QTimer>
+
+#include <private/qmldebugclient_p.h>
+#include <private/qmldebugservice_p.h>
+
+#include "debugutil_p.h"
+
+bool QmlDebugTest::waitForSignal(QObject *receiver, const char *member, int timeout) {
+ QEventLoop loop;
+ QTimer timer;
+ QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+ QObject::connect(receiver, member, &loop, SLOT(quit()));
+ timer.start(timeout);
+ loop.exec();
+ return timer.isActive();
+}
+
+
+QmlDebugTestData::QmlDebugTestData(QEventLoop *el)
+ : exitCode(-1), loop(el)
+{
+}
+
+QmlDebugTestData::~QmlDebugTestData()
+{
+ qDeleteAll(items);
+}
+
+void QmlDebugTestData::testsFinished(int code)
+{
+ exitCode = code;
+ loop->quit();
+}
+
+
+
+QmlDebugTestService::QmlDebugTestService(const QString &s, QObject *parent)
+ : QmlDebugService(s, parent), enabled(false)
+{
+}
+
+void QmlDebugTestService::messageReceived(const QByteArray &ba)
+{
+ sendMessage(ba);
+}
+
+void QmlDebugTestService::enabledChanged(bool e)
+{
+ enabled = e;
+ emit enabledStateChanged();
+}
+
+
+QmlDebugTestClient::QmlDebugTestClient(const QString &s, QmlDebugConnection *c)
+ : QmlDebugClient(s, c)
+{
+}
+
+QByteArray QmlDebugTestClient::waitForResponse()
+{
+ lastMsg.clear();
+ QmlDebugTest::waitForSignal(this, SIGNAL(serverMessage(QByteArray)));
+ if (lastMsg.isEmpty()) {
+ qWarning() << "tst_QmlDebugClient: no response from server!";
+ return QByteArray();
+ }
+ return lastMsg;
+}
+
+void QmlDebugTestClient::messageReceived(const QByteArray &ba)
+{
+ lastMsg = ba;
+ emit serverMessage(ba);
+}
+
+
+tst_QmlDebug_Thread::tst_QmlDebug_Thread(QmlDebugTestData *data, QmlTestFactory *factory)
+ : m_ready(false), m_data(data), m_factory(factory)
+{
+}
+
+void tst_QmlDebug_Thread::run()
+{
+ QTest::qWait(1000);
+
+ QmlDebugConnection conn;
+ conn.connectToHost("127.0.0.1", 3768);
+ bool ok = conn.waitForConnected(5000);
+ Q_ASSERT(ok);
+
+ while (!m_ready)
+ QTest::qWait(100);
+
+ m_data->conn = &conn;
+
+ Q_ASSERT(m_factory);
+ QObject *test = m_factory->createTest(m_data);
+ Q_ASSERT(test);
+ int code = QTest::qExec(test, QCoreApplication::arguments());
+ emit testsFinished(code);
+}
+
+
+int QmlDebugTest::runTests(QmlTestFactory *factory, const QList<QByteArray> &qml)
+{
+ qputenv("QML_DEBUG_SERVER_PORT", "3768");
+
+ QEventLoop loop;
+ QmlDebugTestData data(&loop);
+
+ tst_QmlDebug_Thread thread(&data, factory);
+ QObject::connect(&thread, SIGNAL(testsFinished(int)), &data, SLOT(testsFinished(int)));
+ thread.start();
+
+ QmlEngine engine; // blocks until client connects
+
+ foreach (const QByteArray &code, qml) {
+ QmlComponent c(&engine);
+ c.setData(code, QUrl::fromLocalFile(""));
+ Q_ASSERT(c.isReady()); // fails if bad syntax
+ data.items << qobject_cast<QmlGraphicsItem*>(c.create());
+ }
+
+ // start the test
+ data.engine = &engine;
+ thread.m_ready = true;
+
+ loop.exec();
+ thread.wait();
+
+ return data.exitCode;
+}
+
+
diff --git a/tests/auto/declarative/shared/debugutil_p.h b/tests/auto/declarative/shared/debugutil_p.h
new file mode 100644
index 0000000..313d16c
--- /dev/null
+++ b/tests/auto/declarative/shared/debugutil_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QSignalSpy>
+#include <QEventLoop>
+#include <QPointer>
+#include <QTimer>
+#include <QThread>
+#include <QTest>
+
+#include <QtDeclarative/qmlengine.h>
+
+#include <private/qmldebugclient_p.h>
+#include <private/qmldebugservice_p.h>
+#include <private/qmlgraphicsitem_p.h>
+
+
+class QmlDebugTestData : public QObject
+{
+ Q_OBJECT
+public:
+ QmlDebugTestData(QEventLoop *el);
+
+ ~QmlDebugTestData();
+
+ QmlDebugConnection *conn;
+ QmlEngine *engine;
+
+ int exitCode;
+ QEventLoop *loop;
+
+ QList<QmlGraphicsItem *> items;
+
+public slots:
+ void testsFinished(int code);
+};
+
+
+class QmlTestFactory
+{
+public:
+ QmlTestFactory() {}
+ virtual ~QmlTestFactory() {}
+
+ virtual QObject *createTest(QmlDebugTestData *data) = 0;
+};
+
+
+namespace QmlDebugTest {
+
+ bool waitForSignal(QObject *receiver, const char *member, int timeout = 5000);
+
+ int runTests(QmlTestFactory *factory, const QList<QByteArray> &qml = QList<QByteArray>());
+}
+
+class QmlDebugTestService : public QmlDebugService
+{
+ Q_OBJECT
+public:
+ QmlDebugTestService(const QString &s, QObject *parent = 0);
+ bool enabled;
+
+signals:
+ void enabledStateChanged();
+
+protected:
+ virtual void messageReceived(const QByteArray &ba);
+
+ virtual void enabledChanged(bool e);
+};
+
+class QmlDebugTestClient : public QmlDebugClient
+{
+ Q_OBJECT
+public:
+ QmlDebugTestClient(const QString &s, QmlDebugConnection *c);
+
+ QByteArray waitForResponse();
+
+signals:
+ void serverMessage(const QByteArray &);
+
+protected:
+ virtual void messageReceived(const QByteArray &ba);
+
+private:
+ QByteArray lastMsg;
+};
+
+class tst_QmlDebug_Thread : public QThread
+{
+ Q_OBJECT
+public:
+ tst_QmlDebug_Thread(QmlDebugTestData *data, QmlTestFactory *factory);
+
+ void run();
+
+ bool m_ready;
+
+signals:
+ void testsFinished(int);
+
+private:
+ QmlDebugTestData *m_data;
+ QmlTestFactory *m_factory;
+};
+
+
diff --git a/tests/auto/declarative/shared/testhttpserver.cpp b/tests/auto/declarative/shared/testhttpserver.cpp
new file mode 100644
index 0000000..490fc95
--- /dev/null
+++ b/tests/auto/declarative/shared/testhttpserver.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "testhttpserver.h"
+#include <QTcpSocket>
+#include <QDebug>
+#include <QFile>
+#include <QTimer>
+
+/*!
+\internal
+\class TestHTTPServer
+\brief provides a very, very basic HTTP server for testing.
+
+Inside the test case, an instance of TestHTTPServer should be created, with the
+appropriate port to listen on. The server will listen on the localhost interface.
+
+Directories to serve can then be added to server, which will be added as "roots".
+Each root can be added as a Normal, Delay or Disconnect root. Requests for files
+within a Normal root are returned immediately. Request for files within a Delay
+root are delayed for 500ms, and then served. Requests for files within a Disconnect
+directory cause the server to disconnect immediately. A request for a file that isn't
+found in any root will return a 404 error.
+
+If you have the following directory structure:
+
+\code
+disconnect/disconnectTest.qml
+files/main.qml
+files/Button.qml
+files/content/WebView.qml
+slowFiles/slowMain.qml
+\endcode
+it can be added like this:
+\code
+TestHTTPServer server(14445);
+server.serveDirectory("disconnect", TestHTTPServer::Disconnect);
+server.serveDirectory("files");
+server.serveDirectory("slowFiles", TestHTTPServer::Delay);
+\endcode
+
+The following request urls will then result in the appropriate action:
+\table
+\header \o URL \o Action
+\row \o http://localhost:14445/disconnectTest.qml \o Disconnection
+\row \o http://localhost:14445/main.qml \o main.qml returned immediately
+\row \o http://localhost:14445/Button.qml \o Button.qml returned immediately
+\row \o http://localhost:14445/content/WebView.qml \o content/WebView.qml returned immediately
+\row \o http://localhost:14445/slowMain.qml \o slowMain.qml returned after 500ms
+\endtable
+*/
+TestHTTPServer::TestHTTPServer(quint16 port)
+: m_hasFailed(false)
+{
+ QObject::connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+
+ server.listen(QHostAddress::LocalHost, port);
+}
+
+bool TestHTTPServer::isValid() const
+{
+ return server.isListening();
+}
+
+bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode)
+{
+ dirs.append(qMakePair(dir, mode));
+ return true;
+}
+
+/*
+ Add an alias, so that if filename is requested and does not exist,
+ alias may be returned.
+*/
+void TestHTTPServer::addAlias(const QString &filename, const QString &alias)
+{
+ aliases.insert(filename, alias);
+}
+
+void TestHTTPServer::addRedirect(const QString &filename, const QString &redirectName)
+{
+ redirects.insert(filename, redirectName);
+}
+
+bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &body)
+{
+ m_hasFailed = false;
+
+ QFile expectFile(expect.toLocalFile());
+ if (!expectFile.open(QIODevice::ReadOnly)) return false;
+
+ QFile replyFile(reply.toLocalFile());
+ if (!replyFile.open(QIODevice::ReadOnly)) return false;
+
+ bodyData = QByteArray();
+ if (body.isValid()) {
+ QFile bodyFile(body.toLocalFile());
+ if (!bodyFile.open(QIODevice::ReadOnly)) return false;
+ bodyData = bodyFile.readAll();
+ }
+
+ waitData = expectFile.readAll();
+ /*
+ while (waitData.endsWith('\n'))
+ waitData = waitData.left(waitData.count() - 1);
+ */
+
+ replyData = replyFile.readAll();
+
+ if (!replyData.endsWith('\n'))
+ replyData.append("\n");
+ replyData.append("Content-length: " + QByteArray::number(bodyData.length()));
+ replyData .append("\n\n");
+
+ for (int ii = 0; ii < replyData.count(); ++ii) {
+ if (replyData.at(ii) == '\n' && (!ii || replyData.at(ii - 1) != '\r')) {
+ replyData.insert(ii, '\r');
+ ++ii;
+ }
+ }
+ replyData.append(bodyData);
+
+ return true;
+}
+
+bool TestHTTPServer::hasFailed() const
+{
+ return m_hasFailed;
+}
+
+void TestHTTPServer::newConnection()
+{
+ QTcpSocket *socket = server.nextPendingConnection();
+ if (!socket) return;
+
+ if (!dirs.isEmpty())
+ dataCache.insert(socket, QByteArray());
+
+ QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
+ QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void TestHTTPServer::disconnected()
+{
+ QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
+ if (!socket) return;
+
+ dataCache.remove(socket);
+ for (int ii = 0; ii < toSend.count(); ++ii) {
+ if (toSend.at(ii).first == socket) {
+ toSend.removeAt(ii);
+ --ii;
+ }
+ }
+ socket->deleteLater();
+}
+
+void TestHTTPServer::readyRead()
+{
+ QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
+ if (!socket) return;
+
+ QByteArray ba = socket->readAll();
+
+ if (!dirs.isEmpty()) {
+ serveGET(socket, ba);
+ return;
+ }
+
+ if (m_hasFailed || waitData.isEmpty()) {
+ qWarning() << "TestHTTPServer: Unexpected data" << ba;
+ return;
+ }
+
+ for (int ii = 0; ii < ba.count(); ++ii) {
+ const char c = ba.at(ii);
+ if (c == '\r' && waitData.isEmpty())
+ continue;
+ else if (!waitData.isEmpty() && c == waitData.at(0))
+ waitData = waitData.mid(1);
+ else if (c == '\r')
+ continue;
+ else {
+ QByteArray data = ba.mid(ii);
+ qWarning() << "TestHTTPServer: Unexpected data" << data << "\nExpected: " << waitData;
+ m_hasFailed = true;
+ socket->disconnect();
+ return;
+ }
+ }
+
+ if (waitData.isEmpty()) {
+ socket->write(replyData);
+ socket->disconnect();
+ }
+}
+
+bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName)
+{
+ if (redirects.contains(fileName)) {
+ QByteArray response = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: " + redirects[fileName].toUtf8() + "\r\n\r\n";
+ socket->write(response);
+ return true;
+ }
+
+ for (int ii = 0; ii < dirs.count(); ++ii) {
+ QString dir = dirs.at(ii).first;
+ Mode mode = dirs.at(ii).second;
+
+ QString dirFile = dir + QLatin1String("/") + QLatin1String(fileName);
+
+ if (!QFile::exists(dirFile)) {
+ if (aliases.contains(fileName))
+ dirFile = dir + QLatin1String("/") + aliases.value(fileName);
+ }
+
+ QFile file(dirFile);
+ if (file.open(QIODevice::ReadOnly)) {
+
+ if (mode == Disconnect)
+ return true;
+
+ QByteArray data = file.readAll();
+
+ QByteArray response = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: ";
+ response += QByteArray::number(data.count());
+ response += "\r\n\r\n";
+ response += data;
+
+ if (mode == Delay) {
+ toSend.append(qMakePair(socket, response));
+ QTimer::singleShot(500, this, SLOT(sendOne()));
+ return false;
+ } else {
+ socket->write(response);
+ return true;
+ }
+ }
+ }
+
+
+ QByteArray response = "HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n";
+ socket->write(response);
+
+ return true;
+}
+
+void TestHTTPServer::sendOne()
+{
+ if (!toSend.isEmpty()) {
+ toSend.first().first->write(toSend.first().second);
+ toSend.first().first->close();
+ toSend.removeFirst();
+ }
+}
+
+void TestHTTPServer::serveGET(QTcpSocket *socket, const QByteArray &data)
+{
+ if (!dataCache.contains(socket))
+ return;
+
+ QByteArray total = dataCache[socket] + data;
+ dataCache[socket] = total;
+
+ if (total.contains("\n\r\n")) {
+
+ bool close = true;
+
+ if (total.startsWith("GET /")) {
+
+ int space = total.indexOf(' ', 4);
+ if (space != -1) {
+
+ QByteArray req = total.mid(5, space - 5);
+ close = reply(socket, req);
+
+ }
+ }
+ dataCache.remove(socket);
+
+ if (close)
+ socket->close();
+ }
+}
+
diff --git a/tests/auto/declarative/shared/testhttpserver.h b/tests/auto/declarative/shared/testhttpserver.h
new file mode 100644
index 0000000..178122d
--- /dev/null
+++ b/tests/auto/declarative/shared/testhttpserver.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTHTTPSERVER_H
+#define TESTHTTPSERVER_H
+
+#include <QObject>
+#include <QTcpServer>
+#include <QUrl>
+#include <QPair>
+
+class TestHTTPServer : public QObject
+{
+ Q_OBJECT
+public:
+ TestHTTPServer(quint16 port);
+
+ bool isValid() const;
+
+ enum Mode { Normal, Delay, Disconnect };
+ bool serveDirectory(const QString &, Mode = Normal);
+
+ bool wait(const QUrl &expect, const QUrl &reply, const QUrl &body);
+ bool hasFailed() const;
+
+ void addAlias(const QString &filename, const QString &aliasName);
+ void addRedirect(const QString &filename, const QString &redirectName);
+
+private slots:
+ void newConnection();
+ void disconnected();
+ void readyRead();
+ void sendOne();
+
+private:
+ void serveGET(QTcpSocket *, const QByteArray &);
+ bool reply(QTcpSocket *, const QByteArray &);
+
+ QList<QPair<QString, Mode> > dirs;
+ QHash<QTcpSocket *, QByteArray> dataCache;
+ QList<QPair<QTcpSocket *, QByteArray> > toSend;
+
+ QByteArray waitData;
+ QByteArray replyData;
+ QByteArray bodyData;
+ bool m_hasFailed;
+
+ QHash<QString,QString> aliases;
+ QHash<QString,QString> redirects;
+
+ QTcpServer server;
+};
+
+#endif // TESTHTTPSERVER_H
+
diff --git a/tests/auto/declarative/sql/data/README b/tests/auto/declarative/sql/data/README
new file mode 100644
index 0000000..7efca3a
--- /dev/null
+++ b/tests/auto/declarative/sql/data/README
@@ -0,0 +1,3 @@
+These tests are executed in sequence - the database persist until the end of the
+testing. This is done to better exercise the persistence of the database, since
+that is how it is used.
diff --git a/tests/auto/declarative/sql/data/changeversion.js b/tests/auto/declarative/sql/data/changeversion.js
new file mode 100644
index 0000000..680d7a6
--- /dev/null
+++ b/tests/auto/declarative/sql/data/changeversion.js
@@ -0,0 +1,53 @@
+function test() {
+ var r="transaction_not_finished";
+
+ var db = openDatabaseSync("QmlTestDB-changeversion", "", "Test database from Qt autotests", 1000000,
+ function(db) {
+ db.changeVersion("","1.0")
+ db.transaction(function(tx){
+ tx.executeSql('CREATE TABLE Greeting(salutation TEXT, salutee TEXT)');
+ })
+ });
+
+ db.transaction(function(tx){
+ tx.executeSql('INSERT INTO Greeting VALUES ("Hello", "world")');
+ tx.executeSql('INSERT INTO Greeting VALUES ("Goodbye", "cruel world")');
+ });
+
+
+ db = openDatabaseSync("QmlTestDB-changeversion", "", "Test database from Qt autotests", 1000000);
+
+ if (db.version == "1.0")
+ db.changeVersion("1.0","2.0",function(tx)
+ {
+ tx.executeSql('CREATE TABLE Utterance(type TEXT, phrase TEXT)')
+ var rs = tx.executeSql('SELECT * FROM Greeting');
+ for (var i=0; i<rs.rows.length; ++i) {
+ var type = "Greeting";
+ var phrase = rs.rows.item(i).salutation + ", " + rs.rows.item(i).salutee;
+ if (rs.rows.item(i).salutation == "Goodbye"
+ || rs.rows.item(i).salutation == "Farewell"
+ || rs.rows.item(i).salutation == "Good-bye") type = "Valediction";
+ var ins = tx.executeSql('INSERT INTO Utterance VALUES(?,?)',[type,phrase]);
+ }
+ tx.executeSql('DROP TABLE Greeting');
+ });
+ else
+ return "db.version should be 1.0, but is " + db.version;
+
+ var db = openDatabaseSync("QmlTestDB-changeversion", "2.0", "Test database from Qt autotests", 1000000);
+
+ db.transaction(function(tx){
+ var rs = tx.executeSql('SELECT * FROM Utterance');
+ r = ""
+ for (var i=0; i<rs.rows.length; ++i) {
+ r += "(" + rs.rows.item(i).type + ": " + rs.rows.item(i).phrase + ")";
+ }
+ if (r == "(Greeting: Hello, world)(Valediction: Goodbye, cruel world)")
+ r = "passed"
+ else
+ r = "WRONG DATA: " + r;
+ })
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/creation-a.js b/tests/auto/declarative/sql/data/creation-a.js
new file mode 100644
index 0000000..bd7d5c5
--- /dev/null
+++ b/tests/auto/declarative/sql/data/creation-a.js
@@ -0,0 +1,18 @@
+function test() {
+ var r="transaction_not_finished";
+
+ var db = openDatabaseSync("QmlTestDB-creation-a", "1.0", "Test database from Qt autotests", 1000000,
+ function(db) {
+ db.transaction(function(tx){
+ tx.executeSql('CREATE TABLE Greeting(salutation TEXT, salutee TEXT)');
+ r = "passed";
+ })
+ });
+
+ var db = openDatabaseSync("QmlTestDB-creation-a", "1.0", "Test database from Qt autotests", 1000000,
+ function(db) {
+ r = "FAILED: should have already been created";
+ });
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/creation.js b/tests/auto/declarative/sql/data/creation.js
new file mode 100644
index 0000000..317b4c1
--- /dev/null
+++ b/tests/auto/declarative/sql/data/creation.js
@@ -0,0 +1,14 @@
+function test() {
+ var r="transaction_not_finished";
+ var db = openDatabaseSync("QmlTestDB-creation", "1.0", "Test database from Qt autotests", 1000000);
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ r = "passed";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/error-a.js b/tests/auto/declarative/sql/data/error-a.js
new file mode 100644
index 0000000..10a23f6
--- /dev/null
+++ b/tests/auto/declarative/sql/data/error-a.js
@@ -0,0 +1,20 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-error-a", "1.0", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+
+ try {
+ db.transaction(
+ function(tx) {
+ var rs = tx.executeSql('SELECT * FROM NotExists');
+ r = "SHOULD NOT SUCCEED";
+ }
+ );
+ } catch (err) {
+ if (err.message == "no such table: NotExists Unable to execute statement")
+ r = "passed";
+ else
+ r = "WRONG ERROR="+err.message;
+ }
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/error-b.js b/tests/auto/declarative/sql/data/error-b.js
new file mode 100644
index 0000000..4dd0ecf
--- /dev/null
+++ b/tests/auto/declarative/sql/data/error-b.js
@@ -0,0 +1,13 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-error-b", "1.0", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('INSERT INTO Greeting VALUES("junk","junk")');
+ notexist[123] = "oops"
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/error-creation.js b/tests/auto/declarative/sql/data/error-creation.js
new file mode 100644
index 0000000..92245fd
--- /dev/null
+++ b/tests/auto/declarative/sql/data/error-creation.js
@@ -0,0 +1,12 @@
+function test() {
+ var r="transaction_not_finished";
+ try {
+ var db = openDatabaseSync("QmlTestDB-creation", "2.0", "Test database from Qt autotests", 1000000);
+ } catch (err) {
+ if (err.message == "SQL: database version mismatch")
+ r = "passed";
+ else
+ r = "WRONG ERROR="+err.message;
+ }
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/error-notransaction.js b/tests/auto/declarative/sql/data/error-notransaction.js
new file mode 100644
index 0000000..b9cc647
--- /dev/null
+++ b/tests/auto/declarative/sql/data/error-notransaction.js
@@ -0,0 +1,15 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-data/error-notransaction", "1.0", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+
+ try {
+ db.transaction();
+ } catch (err) {
+ if (err.message == "transaction: missing callback")
+ r = "passed";
+ else
+ r = "WRONG ERROR="+err.message;
+ }
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/error-outsidetransaction.js b/tests/auto/declarative/sql/data/error-outsidetransaction.js
new file mode 100644
index 0000000..a7af3bd
--- /dev/null
+++ b/tests/auto/declarative/sql/data/error-outsidetransaction.js
@@ -0,0 +1,17 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-data/error-notransaction", "1.0", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+ var v;
+
+ try {
+ db.transaction(function(tx) { v = tx });
+ v.executeSql("SELECT 'bad'")
+ } catch (err) {
+ if (err.message == "executeSql called outside transaction()")
+ r = "passed";
+ else
+ r = "WRONG ERROR="+err.message;
+ }
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/iteration-forwardonly.js b/tests/auto/declarative/sql/data/iteration-forwardonly.js
new file mode 100644
index 0000000..45947c0
--- /dev/null
+++ b/tests/auto/declarative/sql/data/iteration-forwardonly.js
@@ -0,0 +1,29 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-iteration-forwardonly", "", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES ("Hello", "world")');
+ tx.executeSql('INSERT INTO Greeting VALUES ("Goodbye", "cruel world")');
+ }
+ )
+
+ db.transaction(
+ function(tx) {
+ var rs = tx.executeSql('SELECT * FROM Greeting');
+ rs.forwardOnly = !rs.forwardOnly
+ var r1=""
+ for(var i = 0; i < rs.rows.length; i++)
+ r1 += rs.rows.item(i).salutation + ", " + rs.rows.item(i).salutee + ";"
+ if (r1 != "hello, world;hello, world;hello, world;hello, world;")
+ if (r1 != "Hello, world;Goodbye, cruel world;")
+ r = "SELECTED DATA WRONG: "+r1;
+ else
+ r = "passed";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/iteration.js b/tests/auto/declarative/sql/data/iteration.js
new file mode 100644
index 0000000..c34cbbb
--- /dev/null
+++ b/tests/auto/declarative/sql/data/iteration.js
@@ -0,0 +1,28 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-iteration", "", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES ("Hello", "world")');
+ tx.executeSql('INSERT INTO Greeting VALUES ("Goodbye", "cruel world")');
+ }
+ )
+
+ db.transaction(
+ function(tx) {
+ var rs = tx.executeSql('SELECT * FROM Greeting');
+ var r1=""
+ for(var i = 0; i < rs.rows.length; i++)
+ r1 += rs.rows.item(i).salutation + ", " + rs.rows.item(i).salutee + ";"
+ if (r1 != "hello, world;hello, world;hello, world;hello, world;")
+ if (r1 != "Hello, world;Goodbye, cruel world;")
+ r = "SELECTED DATA WRONG: "+r1;
+ else
+ r = "passed";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/readonly-error.js b/tests/auto/declarative/sql/data/readonly-error.js
new file mode 100644
index 0000000..69ec67f
--- /dev/null
+++ b/tests/auto/declarative/sql/data/readonly-error.js
@@ -0,0 +1,27 @@
+function test() {
+ var r="transaction_not_finished";
+ var db = openDatabaseSync("QmlTestDB-readonly-error", "1.0", "Test database from Qt autotests", 1000000);
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ }
+ );
+
+ try {
+ db.readTransaction(
+ function(tx) {
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ r = "FAILED";
+ }
+ );
+ } catch (err) {
+ if (err.message == "Read-only Transaction")
+ r = "passed";
+ else
+ r = "WRONG ERROR="+err.message;
+ }
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/readonly.js b/tests/auto/declarative/sql/data/readonly.js
new file mode 100644
index 0000000..5ee862c
--- /dev/null
+++ b/tests/auto/declarative/sql/data/readonly.js
@@ -0,0 +1,24 @@
+function test() {
+ var r="transaction_not_finished";
+ var db = openDatabaseSync("QmlTestDB-readonly", "1.0", "Test database from Qt autotests", 1000000);
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ r = "passed";
+ }
+ );
+
+ db.readTransaction(
+ function(tx) {
+ var rs = tx.executeSql('SELECT * FROM Greeting');
+ if (rs.rows.item(0).salutation == 'hello')
+ r = "passed";
+ else
+ r = "FAILED";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/reopen1.js b/tests/auto/declarative/sql/data/reopen1.js
new file mode 100644
index 0000000..c1a8157
--- /dev/null
+++ b/tests/auto/declarative/sql/data/reopen1.js
@@ -0,0 +1,14 @@
+function test() {
+ var r="transaction_not_finished";
+ var db = openDatabaseSync("QmlTestDB-reopen", "1.0", "Test database from Qt autotests", 1000000);
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ r = "passed";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/reopen2.js b/tests/auto/declarative/sql/data/reopen2.js
new file mode 100644
index 0000000..4f7248f
--- /dev/null
+++ b/tests/auto/declarative/sql/data/reopen2.js
@@ -0,0 +1,16 @@
+function test() {
+ var r="transaction_not_finished";
+ var db = openDatabaseSync("QmlTestDB-reopen", "1.0", "Test database from Qt autotests", 1000000);
+
+ db.transaction(
+ function(tx) {
+ var rs = tx.executeSql('SELECT * FROM Greeting');
+ if (rs.rows.item(0).salutation == 'hello')
+ r = "passed";
+ else
+ r = "FAILED";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/selection-bindnames.js b/tests/auto/declarative/sql/data/selection-bindnames.js
new file mode 100644
index 0000000..9786821
--- /dev/null
+++ b/tests/auto/declarative/sql/data/selection-bindnames.js
@@ -0,0 +1,26 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-bindnames", "", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'goodbye', 'world' ]);
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'there' ]);
+ }
+ );
+
+ db.transaction(
+ function(tx) {
+ var rs = tx.executeSql('SELECT * FROM Greeting WHERE salutation=:p2 AND salutee=:p1', {':p1':'world', ':p2':'hello'});
+ if ( rs.rows.length != 2 )
+ r = "SELECT RETURNED WRONG VALUE "+rs.rows.length+rs.rows.item(0)+rs.rows.item(1)
+ else
+ r = "passed";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/data/selection.js b/tests/auto/declarative/sql/data/selection.js
new file mode 100644
index 0000000..f116eff
--- /dev/null
+++ b/tests/auto/declarative/sql/data/selection.js
@@ -0,0 +1,26 @@
+function test() {
+ var db = openDatabaseSync("QmlTestDB-selection", "", "Test database from Qt autotests", 1000000);
+ var r="transaction_not_finished";
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ }
+ );
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ var rs = tx.executeSql('SELECT * FROM Greeting');
+ if ( rs.rows.length != 4 )
+ r = "SELECT RETURNED WRONG VALUE "+rs.rows.length+rs.rows[0]+rs.rows[1]
+ else
+ r = "passed";
+ }
+ );
+
+ return r;
+}
diff --git a/tests/auto/declarative/sql/sql.pro b/tests/auto/declarative/sql/sql.pro
new file mode 100644
index 0000000..4217eac
--- /dev/null
+++ b/tests/auto/declarative/sql/sql.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+QT += sql script
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_sql.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/sql/tst_sql.cpp b/tests/auto/declarative/sql/tst_sql.cpp
new file mode 100644
index 0000000..9bc667d
--- /dev/null
+++ b/tests/auto/declarative/sql/tst_sql.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include "../../../shared/util.h"
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlgraphicstext_p.h>
+#include <private/qmlengine_p.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtWebKit/qwebpage.h>
+#include <QtWebKit/qwebframe.h>
+#include <QtWebKit/qwebdatabase.h>
+#include <QtWebKit/qwebsecurityorigin.h>
+#include <QtSql/qsqldatabase.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+
+class tst_sql : public QObject
+{
+ Q_OBJECT
+public:
+ tst_sql()
+ {
+ qApp->setApplicationName("tst_sql");
+ qApp->setOrganizationName("Nokia");
+ qApp->setOrganizationDomain("nokia.com");
+ engine = new QmlEngine;
+ }
+
+ ~tst_sql()
+ {
+ delete engine;
+ }
+
+private slots:
+ void initTestCase();
+
+ void checkDatabasePath();
+
+ void testQml_data();
+ void testQml();
+ void testQml_cleanopen_data();
+ void testQml_cleanopen();
+ void totalDatabases();
+
+ void cleanupTestCase();
+
+private:
+ QString dbDir() const;
+ QmlEngine *engine;
+};
+
+class QWebPageWithJavaScriptConsoleMessages : public QWebPage {
+public:
+ void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
+ {
+ qWarning() << sourceID << ":" << lineNumber << ":" << message;
+ }
+};
+
+void removeRecursive(const QString& dirname)
+{
+ QDir dir(dirname);
+ QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot));
+ for (int i = 0; i < entries.count(); ++i)
+ if (entries[i].isDir())
+ removeRecursive(entries[i].filePath());
+ else
+ dir.remove(entries[i].fileName());
+ QDir().rmdir(dirname);
+}
+
+void tst_sql::initTestCase()
+{
+ removeRecursive(dbDir());
+ QDir().mkpath(dbDir());
+}
+
+void tst_sql::cleanupTestCase()
+{
+ removeRecursive(dbDir());
+}
+
+QString tst_sql::dbDir() const
+{
+ static QString tmpd = QDir::tempPath()+"/tst_sql_output-"
+ + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss"));
+ return tmpd;
+}
+
+void tst_sql::checkDatabasePath()
+{
+ // Check default storage path (we can't use it since we don't want to mess with user's data)
+ QVERIFY(engine->offlineStoragePath().contains("tst_sql"));
+ QVERIFY(engine->offlineStoragePath().contains("OfflineStorage"));
+}
+
+static const int total_databases_created_by_tests = 12;
+void tst_sql::testQml_data()
+{
+ QTest::addColumn<QString>("jsfile"); // The input file
+
+ // Each test should use a newly named DB to avoid inter-test dependencies
+ QTest::newRow("creation") << "data/creation.js";
+ QTest::newRow("creation-a") << "data/creation-a.js";
+ QTest::newRow("creation") << "data/creation.js";
+ QTest::newRow("error-creation") << "data/error-creation.js"; // re-uses above DB
+ QTest::newRow("changeversion") << "data/changeversion.js";
+ QTest::newRow("readonly") << "data/readonly.js";
+ QTest::newRow("readonly-error") << "data/readonly-error.js";
+ QTest::newRow("selection") << "data/selection.js";
+ QTest::newRow("selection-bindnames") << "data/selection-bindnames.js";
+ QTest::newRow("iteration") << "data/iteration.js";
+ QTest::newRow("iteration-forwardonly") << "data/iteration-forwardonly.js";
+ QTest::newRow("error-a") << "data/error-a.js";
+ QTest::newRow("error-notransaction") << "data/error-notransaction.js";
+ QTest::newRow("error-outsidetransaction") << "data/error-outsidetransaction.js"; // reuse above
+ QTest::newRow("reopen1") << "data/reopen1.js";
+ QTest::newRow("reopen2") << "data/reopen2.js"; // re-uses above DB
+
+ // If you add a test, you should usually use a new database in the
+ // test - in which case increment total_databases_created_by_tests above.
+}
+
+/*
+void tst_sql::validateAgainstWebkit()
+{
+ // Validates tests against WebKit (HTML5) support.
+ //
+ QFETCH(QString, jsfile);
+ QFETCH(QString, result);
+ QFETCH(int, databases);
+
+ QFile f(jsfile);
+ QVERIFY(f.open(QIODevice::ReadOnly));
+ QString js=f.readAll();
+
+ QWebPageWithJavaScriptConsoleMessages webpage;
+ webpage.settings()->setOfflineStoragePath(dbDir());
+ webpage.settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
+
+ QEXPECT_FAIL("","WebKit doesn't support openDatabaseSync yet", Continue);
+ QCOMPARE(webpage.mainFrame()->evaluateJavaScript(js).toString(),result);
+
+ QTest::qWait(100); // WebKit crashes if you quit it too fast
+
+ QWebSecurityOrigin origin = webpage.mainFrame()->securityOrigin();
+ QList<QWebDatabase> dbs = origin.databases();
+ QCOMPARE(dbs.count(), databases);
+}
+*/
+
+void tst_sql::testQml()
+{
+ // Tests QML SQL Database support with tests
+ // that have been validated against Webkit.
+ //
+ QFETCH(QString, jsfile);
+
+ QString qml=
+ "import Qt 4.6\n"
+ "Text { Script { source: \""+jsfile+"\" } text: test() }";
+
+ engine->setOfflineStoragePath(dbDir());
+ QmlComponent component(engine);
+ component.setData(qml.toUtf8(), QUrl::fromLocalFile(SRCDIR "/empty.qml")); // just a file for relative local imports
+ QmlGraphicsText *text = qobject_cast<QmlGraphicsText*>(component.create());
+ QVERIFY(text != 0);
+ QCOMPARE(text->text(),QString("passed"));
+}
+
+void tst_sql::testQml_cleanopen_data()
+{
+ QTest::addColumn<QString>("jsfile"); // The input file
+ QTest::newRow("reopen1") << "data/reopen1.js";
+ QTest::newRow("reopen2") << "data/reopen2.js";
+ QTest::newRow("error-creation") << "data/error-creation.js"; // re-uses creation DB
+}
+
+void tst_sql::testQml_cleanopen()
+{
+ // Same as testQml, but clean connections between tests,
+ // making it more like the tests are running in new processes.
+ testQml();
+
+ QmlEnginePrivate::getScriptEngine(engine)->collectGarbage(); // close databases
+ foreach (QString dbname, QSqlDatabase::connectionNames()) {
+ QSqlDatabase::removeDatabase(dbname);
+ }
+}
+
+void tst_sql::totalDatabases()
+{
+ QCOMPARE(QDir(dbDir()+"/Databases").entryInfoList(QDir::Files|QDir::NoDotAndDotDot).count(), total_databases_created_by_tests*2);
+}
+
+QTEST_MAIN(tst_sql)
+
+#include "tst_sql.moc"
diff --git a/tests/auto/declarative/visual/ListView/basic1.qml b/tests/auto/declarative/visual/ListView/basic1.qml
new file mode 100644
index 0000000..3c371a6
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+Rectangle {
+ color: "blue"
+ width: 200
+ height: 300
+ id: page
+ ListView {
+ anchors.fill: parent
+ delegate: Rectangle {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ model: ListModel {
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic2.qml b/tests/auto/declarative/visual/ListView/basic2.qml
new file mode 100644
index 0000000..bdba65e
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Rectangle {
+ color: "blue"
+ width: 200
+ height: 300
+ id: page
+ Component {
+ id: delegate
+ Rectangle {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+ ListView {
+ anchors.fill: parent
+ delegate: delegate
+ model: ListModel {
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic3.qml b/tests/auto/declarative/visual/ListView/basic3.qml
new file mode 100644
index 0000000..05ac358
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ color: "blue"
+ width: 200
+ height: 300
+ id: page
+ Listmodel {
+ id: model
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ ListView {
+ anchors.fill: parent
+ model: model
+ delegate: Rectangle {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/basic4.qml b/tests/auto/declarative/visual/ListView/basic4.qml
new file mode 100644
index 0000000..3628bd3
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4.qml
@@ -0,0 +1,33 @@
+import Qt 4.6
+
+Rectangle {
+ color: "blue"
+ width: 200
+ height: 300
+ id: page
+ Listmodel {
+ id: model
+ ListElement {
+ name: "January"
+ }
+ ListElement {
+ name: "February"
+ }
+ }
+ Component {
+ id: delegate
+ Rectangle {
+ color: "red"
+ width: 100
+ height: 100
+ Text {
+ text: name
+ }
+ }
+ }
+ ListView {
+ anchors.fill: parent
+ model: model
+ delegate: delegate
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/basic1.qml b/tests/auto/declarative/visual/ListView/data-MAC/basic1.qml
new file mode 100644
index 0000000..83b700d
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/basic1.qml
@@ -0,0 +1,159 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 32
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 48
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 64
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 80
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 96
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 112
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 128
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 144
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 160
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 176
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 192
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 208
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 224
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 240
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 256
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 272
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 288
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 304
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 320
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 336
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 352
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 368
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 384
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 400
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 416
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 432
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 448
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 464
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 480
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 496
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 512
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 528
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 544
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 560
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 576
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/basic2.qml b/tests/auto/declarative/visual/ListView/data-MAC/basic2.qml
new file mode 100644
index 0000000..1483512
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/basic2.qml
@@ -0,0 +1,187 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 32
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 48
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 64
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 80
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 96
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 112
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 128
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 144
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 160
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 176
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 192
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 208
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 224
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 240
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 256
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 272
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 288
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 304
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 320
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 336
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 352
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 368
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 384
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 400
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 416
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 432
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 448
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 464
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 480
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 496
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 512
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 528
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 544
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 560
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 576
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 592
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 608
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 624
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 640
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 656
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 672
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 688
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/basic3.qml b/tests/auto/declarative/visual/ListView/data-MAC/basic3.qml
new file mode 100644
index 0000000..bf68998
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/basic3.qml
@@ -0,0 +1,147 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 32
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 48
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 64
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 80
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 96
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 112
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 128
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 144
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 160
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 176
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 192
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 208
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 224
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 240
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 256
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 272
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 288
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 304
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 320
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 336
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 352
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 368
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 384
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 400
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 416
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 432
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 448
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 464
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 480
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 496
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 512
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 528
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/basic4.qml b/tests/auto/declarative/visual/ListView/data-MAC/basic4.qml
new file mode 100644
index 0000000..4aa9ab6
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/basic4.qml
@@ -0,0 +1,171 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 32
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 48
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 64
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 80
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 96
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 112
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 128
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 144
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 160
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 176
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 192
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 208
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 224
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 240
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 256
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 272
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 288
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 304
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 320
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 336
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 352
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 368
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 384
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 400
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 416
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 432
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 448
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 464
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 480
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 496
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 512
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 528
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 544
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 560
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 576
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 592
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 608
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+ Frame {
+ msec: 624
+ hash: "895c70434a24da42144e60e6d8dcf323"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.0.png b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.0.png
new file mode 100644
index 0000000..13b280c
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.1.png b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.1.png
new file mode 100644
index 0000000..402872b
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.2.png b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.2.png
new file mode 100644
index 0000000..afd0830
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.3.png b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.3.png
new file mode 100644
index 0000000..7c15f61
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.4.png b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.4.png
new file mode 100644
index 0000000..afd0830
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.5.png b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.5.png
new file mode 100644
index 0000000..fddf1cb
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.6.png b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.6.png
new file mode 100644
index 0000000..13b280c
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/itemlist.qml b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.qml
new file mode 100644
index 0000000..073749f
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/itemlist.qml
@@ -0,0 +1,2203 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 32
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 48
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 64
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 80
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 96
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 112
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 128
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 144
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 160
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 176
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 192
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 208
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 224
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 240
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 256
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 272
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 288
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 304
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 320
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 336
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 352
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 368
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 384
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 400
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 416
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 432
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 448
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 464
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 480
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 496
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 512
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 528
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 544
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 560
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 576
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 592
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 608
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 624
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 640
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 656
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 672
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 688
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 704
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 720
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 736
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 752
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 768
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 784
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 800
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 816
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 832
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 848
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 864
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 880
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 896
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 912
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 928
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 944
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 960
+ image: "itemlist.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 992
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1008
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1024
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1040
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1056
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1072
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1088
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1104
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1120
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1136
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1152
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1168
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1184
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1200
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1216
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1232
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1248
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1264
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1280
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1296
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1312
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1328
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1344
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1360
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1376
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1392
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1408
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1424
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1440
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1456
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1472
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1488
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1504
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1520
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1536
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1552
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1568
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1584
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1600
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1616
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1632
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1648
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 192; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1664
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 191; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1680
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 190; y: 112
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 187; y: 113
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1696
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 184; y: 113
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 180; y: 113
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1712
+ hash: "a68b1bc6c2963ee92c3a45f500667b3b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 174; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 167; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1728
+ hash: "7cda93e59466b3348e7ffe3895f89e86"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 160; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1744
+ hash: "06e0008c78e919f7270402938d9d764b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 140; y: 121
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 132; y: 122
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1760
+ hash: "9d8da9199efebb95f56e5d4ebc9a585e"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 114; y: 126
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 98; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1776
+ hash: "54a60a4279911ba4a8a5741bcadfa783"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 91; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 91; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1792
+ hash: "a1a19370a1a8ed78e475f0d0eb12311c"
+ }
+ Frame {
+ msec: 1808
+ hash: "196a3b127cf7065614c34856bf8d8bca"
+ }
+ Frame {
+ msec: 1824
+ hash: "5fbefbd7c7be4374382cc4c8b86ac78a"
+ }
+ Frame {
+ msec: 1840
+ hash: "d6a544c622e504c1b931e1a8a1310a6e"
+ }
+ Frame {
+ msec: 1856
+ hash: "20e76f0eb4ec5f691999faf8ad313370"
+ }
+ Frame {
+ msec: 1872
+ hash: "7f84a3545907c754ae8a6a30ef61c98d"
+ }
+ Frame {
+ msec: 1888
+ hash: "b544901eae32903ad054e8cdfed715eb"
+ }
+ Frame {
+ msec: 1904
+ hash: "a010ed1e3312f4ca9f429b7e32cdcef9"
+ }
+ Frame {
+ msec: 1920
+ image: "itemlist.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "93a731dc6f71b6ff5400bf74c87e6c46"
+ }
+ Frame {
+ msec: 1952
+ hash: "c73f63d1a024ba956e693487b3ccc761"
+ }
+ Frame {
+ msec: 1968
+ hash: "539d3d00fce2d0128cd697d86d237fe7"
+ }
+ Frame {
+ msec: 1984
+ hash: "52752d7d6f2d0e085f7132313907b72b"
+ }
+ Frame {
+ msec: 2000
+ hash: "f46dd5803a6075e979e0fc733d503bfb"
+ }
+ Frame {
+ msec: 2016
+ hash: "b8734698a6bad00ecf019f85328c2c21"
+ }
+ Frame {
+ msec: 2032
+ hash: "1cfc499ca756023430cc5b2fa95a599d"
+ }
+ Frame {
+ msec: 2048
+ hash: "63a816548837c19f8f0494c137fc0174"
+ }
+ Frame {
+ msec: 2064
+ hash: "1bce9b85235e9a1a472c079dfec70ec5"
+ }
+ Frame {
+ msec: 2080
+ hash: "6677863e7f74c12648409883f73adbe2"
+ }
+ Frame {
+ msec: 2096
+ hash: "98e707a3e39a5f7bd4a101c2ed83535c"
+ }
+ Frame {
+ msec: 2112
+ hash: "c1f6d8842d14a9394d4b7797314f50e8"
+ }
+ Frame {
+ msec: 2128
+ hash: "579758b477bcd2112b305a5aac7df338"
+ }
+ Frame {
+ msec: 2144
+ hash: "4a7bb81090db246db53e2dbc56f710ea"
+ }
+ Frame {
+ msec: 2160
+ hash: "074995cdd8a70817d1c8a7bb0ad4c542"
+ }
+ Frame {
+ msec: 2176
+ hash: "bd8d7bda4d2e9ad1fba2895d568f36cc"
+ }
+ Frame {
+ msec: 2192
+ hash: "40cce3d2d80ac470af44fc334cec1d5b"
+ }
+ Frame {
+ msec: 2208
+ hash: "15cbc226b032d5a97199735ea7a1408b"
+ }
+ Frame {
+ msec: 2224
+ hash: "12b296aea9b058a5402d0d0a620f8edc"
+ }
+ Frame {
+ msec: 2240
+ hash: "6ffd2b79cf0e941a59e74bc6f9025bcb"
+ }
+ Frame {
+ msec: 2256
+ hash: "589a58ef76ea709dc8d80390c9044f99"
+ }
+ Frame {
+ msec: 2272
+ hash: "c009924bfa30153f22ab168b539494e9"
+ }
+ Frame {
+ msec: 2288
+ hash: "4b83674a7c2daa68d735901ad40be2bd"
+ }
+ Frame {
+ msec: 2304
+ hash: "0525908c0302ada989e28990bac3f2ca"
+ }
+ Frame {
+ msec: 2320
+ hash: "89eb13976ba3ba4413cafeb0cc91c01b"
+ }
+ Frame {
+ msec: 2336
+ hash: "75c1295ef99680784b2e11fb88fa1423"
+ }
+ Frame {
+ msec: 2352
+ hash: "93d89165cf6a97c76ae6e7f75678a3cd"
+ }
+ Frame {
+ msec: 2368
+ hash: "53064c1938f08a55603a99b0db225174"
+ }
+ Frame {
+ msec: 2384
+ hash: "31db5684466c0c32128a9a8c7b1835e1"
+ }
+ Frame {
+ msec: 2400
+ hash: "99d9e58697736198e0a00443d237e85b"
+ }
+ Frame {
+ msec: 2416
+ hash: "6c1e860aef983367365d53f5849ad441"
+ }
+ Frame {
+ msec: 2432
+ hash: "6c1e860aef983367365d53f5849ad441"
+ }
+ Frame {
+ msec: 2448
+ hash: "6c1e860aef983367365d53f5849ad441"
+ }
+ Frame {
+ msec: 2464
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2480
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2496
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2512
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2528
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2544
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2560
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2576
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2592
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2608
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2624
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2640
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2656
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2672
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2688
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2704
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2720
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2736
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2752
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2768
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2784
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2800
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2816
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2832
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2848
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2864
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 181; y: 104
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2880
+ image: "itemlist.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 179; y: 105
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 177; y: 106
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2912
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 174; y: 108
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 170; y: 110
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2928
+ hash: "5bb06b4e74532ba5bc8c7bc38bf77d7f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 166; y: 112
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 160; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2944
+ hash: "b10a6206830a876017799ef2fcf61b1a"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 154; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 140; y: 123
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2960
+ hash: "b2e24759ba10afd6cff90f4b1e04b496"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 124; y: 127
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 124; y: 127
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2976
+ hash: "ccbcd6f45cb529c2db71504c0f69d73e"
+ }
+ Frame {
+ msec: 2992
+ hash: "7b31c6d5931677f1aa1e8c7d48a4ff22"
+ }
+ Frame {
+ msec: 3008
+ hash: "c52f691a0a6cf155118bdfea2dfea623"
+ }
+ Frame {
+ msec: 3024
+ hash: "dd639d1df3d4a9b8f06718def63d588f"
+ }
+ Frame {
+ msec: 3040
+ hash: "39d767b09a648ef6295cec2848f9226f"
+ }
+ Frame {
+ msec: 3056
+ hash: "5dd46d5f386431e7b13348ac9a9630ed"
+ }
+ Frame {
+ msec: 3072
+ hash: "0354e5183b0e66e7ba146d292c559df4"
+ }
+ Frame {
+ msec: 3088
+ hash: "984aa6d7075e24de429e05b1b0eda94a"
+ }
+ Frame {
+ msec: 3104
+ hash: "1af58a2f44f1f613712d4df85e38356d"
+ }
+ Frame {
+ msec: 3120
+ hash: "6e4085e7f1fee724d78808753f04b471"
+ }
+ Frame {
+ msec: 3136
+ hash: "73a019ef9057639d631cd99a431b3f3b"
+ }
+ Frame {
+ msec: 3152
+ hash: "c9414a2e655a90dfdcb6fb288b4ba0ca"
+ }
+ Frame {
+ msec: 3168
+ hash: "3f4c24f7ac89da982af22032309637fb"
+ }
+ Frame {
+ msec: 3184
+ hash: "a50e6ada8f73a257657f4348ceaffcfd"
+ }
+ Frame {
+ msec: 3200
+ hash: "a67bf40d09259bbd079c12ae4f49150f"
+ }
+ Frame {
+ msec: 3216
+ hash: "a2fc512b7c234a9d0b2c1a83387a8a46"
+ }
+ Frame {
+ msec: 3232
+ hash: "85090683ce9a3c9833b1cb0b3df076ee"
+ }
+ Frame {
+ msec: 3248
+ hash: "275f3594a0e2cc4b6717f9f336e7e1b6"
+ }
+ Frame {
+ msec: 3264
+ hash: "2473eb11f7b65a784a2b166114026488"
+ }
+ Frame {
+ msec: 3280
+ hash: "4865c30dc45fbf5ca82047b77eca0912"
+ }
+ Frame {
+ msec: 3296
+ hash: "54de88bca395449fbaea2c090c7a5d91"
+ }
+ Frame {
+ msec: 3312
+ hash: "833f9295cf9a34934f001eac48551b59"
+ }
+ Frame {
+ msec: 3328
+ hash: "5bf565f57ababa7380faeee94add91ca"
+ }
+ Frame {
+ msec: 3344
+ hash: "6325578867f1eb3b2d47ed40b017b571"
+ }
+ Frame {
+ msec: 3360
+ hash: "046a6114176b3a3206b7a2acd6e30b41"
+ }
+ Frame {
+ msec: 3376
+ hash: "f8d4120a17f28c2d1d9c4be959098058"
+ }
+ Frame {
+ msec: 3392
+ hash: "71356d2e48aad2900784ea6bc1a3d908"
+ }
+ Frame {
+ msec: 3408
+ hash: "b84ad460fb81fdc4049abe8f3ff180bb"
+ }
+ Frame {
+ msec: 3424
+ hash: "0354239f5eaea23474d9f81385392a8a"
+ }
+ Frame {
+ msec: 3440
+ hash: "8ef0eef3393e07ae7605c865a95edc30"
+ }
+ Frame {
+ msec: 3456
+ hash: "5b8b384cc8e3faf4310015e19b3eb487"
+ }
+ Frame {
+ msec: 3472
+ hash: "77c18ac7dfff2a4e516915e3e3df0717"
+ }
+ Frame {
+ msec: 3488
+ hash: "c1d3264384c26345eb8100de829309ca"
+ }
+ Frame {
+ msec: 3504
+ hash: "6b21f71d0bedef4bbcb445a13f61e7a3"
+ }
+ Frame {
+ msec: 3520
+ hash: "f619097356671f6eb54d3b1c481e709d"
+ }
+ Frame {
+ msec: 3536
+ hash: "e56e3a90da446e0c482cb93717f6aacc"
+ }
+ Frame {
+ msec: 3552
+ hash: "aa94ebdbb4b8423aff28c95daff0baf5"
+ }
+ Frame {
+ msec: 3568
+ hash: "e1744d9cacd1a2c96af4cfdd5c486995"
+ }
+ Frame {
+ msec: 3584
+ hash: "7f19ea52e9e41a3b1bd90bb2a144d305"
+ }
+ Frame {
+ msec: 3600
+ hash: "7f19ea52e9e41a3b1bd90bb2a144d305"
+ }
+ Frame {
+ msec: 3616
+ hash: "7f19ea52e9e41a3b1bd90bb2a144d305"
+ }
+ Frame {
+ msec: 3632
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3648
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3664
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3680
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3696
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3712
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3728
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3744
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3760
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3776
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3792
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3808
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3824
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3840
+ image: "itemlist.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3872
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3888
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3904
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3920
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3936
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3952
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3968
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3984
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4000
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4016
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4032
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4048
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4064
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4080
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4096
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 31; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4112
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 32; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4128
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 33; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 36; y: 135
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4144
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 40; y: 134
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4160
+ hash: "c2c9c284b185a89faf4ddb5a7867f449"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 64; y: 130
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4176
+ hash: "de1c18aeda5d2fbd6dad4554c78617bd"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 86; y: 126
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 110; y: 118
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 110; y: 118
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4192
+ hash: "a67bf40d09259bbd079c12ae4f49150f"
+ }
+ Frame {
+ msec: 4208
+ hash: "94514668dafbe41c5890a578efd6dea4"
+ }
+ Frame {
+ msec: 4224
+ hash: "2e97a74eb9ddb1c9613c89e2d78db018"
+ }
+ Frame {
+ msec: 4240
+ hash: "4b5368f0d86bffeb6bd31b58aec88650"
+ }
+ Frame {
+ msec: 4256
+ hash: "b459bde7bb4ce51e6ecdab58f64fcbb9"
+ }
+ Frame {
+ msec: 4272
+ hash: "7bac8cc3ec64c9ad1c0da282e38c953e"
+ }
+ Frame {
+ msec: 4288
+ hash: "a73a58c3d7a757547740a2a161f4c756"
+ }
+ Frame {
+ msec: 4304
+ hash: "b35edcb1fa3568a3e770ab2364b82e75"
+ }
+ Frame {
+ msec: 4320
+ hash: "d6c863ef57c5e5cb04cdac72f920db0b"
+ }
+ Frame {
+ msec: 4336
+ hash: "0db5e4588ff851918b07796f0cf07382"
+ }
+ Frame {
+ msec: 4352
+ hash: "71ec8c363ca6a6f7556afb70faccffe6"
+ }
+ Frame {
+ msec: 4368
+ hash: "18d026e9c965ada1db67c643576d2a80"
+ }
+ Frame {
+ msec: 4384
+ hash: "69f71c22dff981a4da8ec1edcf90e79f"
+ }
+ Frame {
+ msec: 4400
+ hash: "680460f5e4d9e649931601041af046b2"
+ }
+ Frame {
+ msec: 4416
+ hash: "3028763fd15de2607b20b1331b904a4a"
+ }
+ Frame {
+ msec: 4432
+ hash: "333eb60e217fe1ea7469eab52ac461f1"
+ }
+ Frame {
+ msec: 4448
+ hash: "ccbcd6f45cb529c2db71504c0f69d73e"
+ }
+ Frame {
+ msec: 4464
+ hash: "3445df9b41a0a3e74738cbf328ab7d5c"
+ }
+ Frame {
+ msec: 4480
+ hash: "bd2c072558479e9de7a97207e58cc57f"
+ }
+ Frame {
+ msec: 4496
+ hash: "3d34b0b24a30eda93377dcb4585afed8"
+ }
+ Frame {
+ msec: 4512
+ hash: "d3045703863b0c5a327b9355c23d69f2"
+ }
+ Frame {
+ msec: 4528
+ hash: "2f2eb55f693415b840a317211b250e9f"
+ }
+ Frame {
+ msec: 4544
+ hash: "791b9ca7d47a3343474c30a35e336d4b"
+ }
+ Frame {
+ msec: 4560
+ hash: "73a0c02ebad6d3d5f939d9a00dd898bf"
+ }
+ Frame {
+ msec: 4576
+ hash: "d5c11135d586711b12f236430a2c2795"
+ }
+ Frame {
+ msec: 4592
+ hash: "34f9ea214fe714ff4e994f715ea6ea39"
+ }
+ Frame {
+ msec: 4608
+ hash: "8e49afa00983b156b818533923fb6edd"
+ }
+ Frame {
+ msec: 4624
+ hash: "e7e7bef17cee92eca9191fd734d7a577"
+ }
+ Frame {
+ msec: 4640
+ hash: "e407f6ed7cb3c130365ab5515d6308c0"
+ }
+ Frame {
+ msec: 4656
+ hash: "5bb06b4e74532ba5bc8c7bc38bf77d7f"
+ }
+ Frame {
+ msec: 4672
+ hash: "0ad7411316031e22034c14e81ca3a806"
+ }
+ Frame {
+ msec: 4688
+ hash: "dd81d7a9b48c922b4c42cba1b5f2b9d7"
+ }
+ Frame {
+ msec: 4704
+ hash: "32bef6f5005ad94e29ff59165958fbdc"
+ }
+ Frame {
+ msec: 4720
+ hash: "87758dd311f91193bf1e3536c2f58525"
+ }
+ Frame {
+ msec: 4736
+ hash: "015be92a4ff4e735fcc3cbc7a8b9d763"
+ }
+ Frame {
+ msec: 4752
+ hash: "d4c34ed49317c6692d71681fcd9842b6"
+ }
+ Frame {
+ msec: 4768
+ hash: "abaa235bb946a8abaddd52981d632c2d"
+ }
+ Frame {
+ msec: 4784
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4800
+ image: "itemlist.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4832
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4848
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4864
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4880
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4896
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4912
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4928
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4944
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4960
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4976
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4992
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5008
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5024
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5040
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5056
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5072
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5088
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5104
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5120
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5136
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5152
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5168
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5184
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5200
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5216
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5232
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 17; y: 120
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5248
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 19; y: 120
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 21; y: 120
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5264
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 24; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 28; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5280
+ hash: "95b380c9ab6f8db7b822faf023d94546"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 35; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 44; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5296
+ hash: "bb79e53556698c62ec30c75be9f6b7d7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 70; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 96; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 96; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5312
+ hash: "285cc2f0df1f59f25a0135560ab6edf2"
+ }
+ Frame {
+ msec: 5328
+ hash: "93a731dc6f71b6ff5400bf74c87e6c46"
+ }
+ Frame {
+ msec: 5344
+ hash: "eb555741ab128a50de5a18a454f2e639"
+ }
+ Frame {
+ msec: 5360
+ hash: "5dbe6cf898c1e37fcaacecfcf57b2194"
+ }
+ Frame {
+ msec: 5376
+ hash: "e7795610115593e78bb32f7bcc0ae2eb"
+ }
+ Frame {
+ msec: 5392
+ hash: "20e76f0eb4ec5f691999faf8ad313370"
+ }
+ Frame {
+ msec: 5408
+ hash: "d6a544c622e504c1b931e1a8a1310a6e"
+ }
+ Frame {
+ msec: 5424
+ hash: "e7a3a21feed244c5b1c710a9254c15f0"
+ }
+ Frame {
+ msec: 5440
+ hash: "5a4b1aca24f121d1373646e9d80b86fd"
+ }
+ Frame {
+ msec: 5456
+ hash: "331d2ec7021655c86aa64e47718a1088"
+ }
+ Frame {
+ msec: 5472
+ hash: "92096bc872e7395aa5b75c44646a0b60"
+ }
+ Frame {
+ msec: 5488
+ hash: "0d9aa6cee4d21488cbb5153f8f3ed593"
+ }
+ Frame {
+ msec: 5504
+ hash: "c1b943d43701605563fffffcb75f9fa7"
+ }
+ Frame {
+ msec: 5520
+ hash: "1b680025d5ad1ddd8f8d5f570ba73e71"
+ }
+ Frame {
+ msec: 5536
+ hash: "5539a3b9f60ea747c10ed8328b467cbf"
+ }
+ Frame {
+ msec: 5552
+ hash: "0a1317bcb606cd3488c5b14ee5d96585"
+ }
+ Frame {
+ msec: 5568
+ hash: "8844af68b11db7d92c69804c7371a746"
+ }
+ Frame {
+ msec: 5584
+ hash: "28d7fd127739c6e3b8488651b725c802"
+ }
+ Frame {
+ msec: 5600
+ hash: "0cf1a7d958a96aa2768995dddc5ccc09"
+ }
+ Frame {
+ msec: 5616
+ hash: "64b902fe7ab4d89ef0c7b760974e3488"
+ }
+ Frame {
+ msec: 5632
+ hash: "aba11c597eba550fc1eaddbf554057f6"
+ }
+ Frame {
+ msec: 5648
+ hash: "1bacaa3bb9dc3cac9ffc7491cb4dc1a5"
+ }
+ Frame {
+ msec: 5664
+ hash: "0ba8b582234d9f0c198c0c9e18e1cb02"
+ }
+ Frame {
+ msec: 5680
+ hash: "f66eaf2b5c3529987c0d9d005351ed73"
+ }
+ Frame {
+ msec: 5696
+ hash: "75b0bb720fa4c77da3783b3ff31c2fae"
+ }
+ Frame {
+ msec: 5712
+ hash: "345b235bb7f13409378e5c0c370f2a41"
+ }
+ Frame {
+ msec: 5728
+ hash: "83b7e902dce4e0fdc4ef5d629188c23c"
+ }
+ Frame {
+ msec: 5744
+ hash: "04b9041c6f10969889d92e94785c7e88"
+ }
+ Frame {
+ msec: 5760
+ image: "itemlist.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "4f3a902addc34ecdaf390e2427cc52e7"
+ }
+ Frame {
+ msec: 5792
+ hash: "68d443f16c16821ffc9ca68b17c76034"
+ }
+ Frame {
+ msec: 5808
+ hash: "9d25adc77befa761ee376a9b43595b5e"
+ }
+ Frame {
+ msec: 5824
+ hash: "a68b1bc6c2963ee92c3a45f500667b3b"
+ }
+ Frame {
+ msec: 5840
+ hash: "d5268cd58c222451d48038e715e83802"
+ }
+ Frame {
+ msec: 5856
+ hash: "f37d461541a8ec7a4161b18748de6aea"
+ }
+ Frame {
+ msec: 5872
+ hash: "805319ac7ca842feb3649e92f8b5b72f"
+ }
+ Frame {
+ msec: 5888
+ hash: "73124472a05080891d4948d8ca273f8c"
+ }
+ Frame {
+ msec: 5904
+ hash: "b6e433a23282a50db2e165a2447ba3f6"
+ }
+ Frame {
+ msec: 5920
+ hash: "fd8d3f5688b1806998c6087e18c6c730"
+ }
+ Frame {
+ msec: 5936
+ hash: "f132dd459950ef2d18aa93ca950d0692"
+ }
+ Frame {
+ msec: 5952
+ hash: "ade5beb259b5277c333ca806fc9bdbec"
+ }
+ Frame {
+ msec: 5968
+ hash: "ade5beb259b5277c333ca806fc9bdbec"
+ }
+ Frame {
+ msec: 5984
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6000
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6016
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6032
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6048
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6064
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6080
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6096
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6112
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6128
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6144
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6160
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6176
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6192
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6208
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6224
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6240
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6256
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6272
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6288
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6304
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6320
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6336
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6352
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6368
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6384
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6400
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6416
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6432
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6448
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6464
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6480
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6496
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6512
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6528
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6544
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6560
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6576
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6592
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6608
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6624
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6640
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6656
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6672
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6688
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6704
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6720
+ image: "itemlist.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6752
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6768
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6784
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6800
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6816
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6832
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6848
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6864
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6880
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6896
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6912
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6928
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6944
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6960
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6976
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6992
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7008
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7024
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7040
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7056
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7072
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7088
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7104
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7120
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7136
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7152
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7168
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7184
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7200
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7216
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7232
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7248
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7264
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7280
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7296
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7312
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.0.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.0.png
new file mode 100644
index 0000000..a1ab987
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.1.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.1.png
new file mode 100644
index 0000000..a1ab987
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.10.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.10.png
new file mode 100644
index 0000000..dcfca3f
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.10.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.11.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.11.png
new file mode 100644
index 0000000..7cc4047
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.11.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.12.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.12.png
new file mode 100644
index 0000000..a97f4ad
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.12.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.13.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.13.png
new file mode 100644
index 0000000..7a8c6bd
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.13.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.14.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.14.png
new file mode 100644
index 0000000..ae47356
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.14.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.15.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.15.png
new file mode 100644
index 0000000..b3a7260
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.15.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.16.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.16.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.16.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.17.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.17.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.17.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.18.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.18.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.18.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.19.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.19.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.19.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.2.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.2.png
new file mode 100644
index 0000000..9877b92
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.3.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.3.png
new file mode 100644
index 0000000..603bd24
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.4.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.4.png
new file mode 100644
index 0000000..5fdfbb8
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.5.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.5.png
new file mode 100644
index 0000000..a1ab987
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.6.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.6.png
new file mode 100644
index 0000000..9ccf9b0
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.7.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.7.png
new file mode 100644
index 0000000..6b40e1b
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.8.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.8.png
new file mode 100644
index 0000000..2fda36d
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.9.png b/tests/auto/declarative/visual/ListView/data-MAC/listview.9.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.9.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data-MAC/listview.qml b/tests/auto/declarative/visual/ListView/data-MAC/listview.qml
new file mode 100644
index 0000000..3765668
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-MAC/listview.qml
@@ -0,0 +1,3079 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 32
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 48
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 64
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 80
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 96
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 112
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 128
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 144
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 160
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 176
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 192
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 208
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 224
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 240
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 256
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 272
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 288
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 304
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 320
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 336
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 352
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 368
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 384
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 400
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 416
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 432
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 448
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 464
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 480
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 496
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 512
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 528
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 544
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 560
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 576
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 592
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 608
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 624
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 640
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 656
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 672
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 688
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 704
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 720
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 736
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 752
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 768
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 784
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 800
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 816
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 832
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 848
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 864
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 880
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 896
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 912
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 928
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 944
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 960
+ image: "listview.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 992
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1008
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1024
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1040
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1056
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1072
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1088
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1104
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1120
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1136
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1152
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1168
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1184
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1200
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1216
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1232
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1248
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1264
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1280
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1296
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1312
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1328
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1344
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1360
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1376
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1392
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1408
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1424
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1440
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1456
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1472
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1488
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1504
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1520
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1536
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1552
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1568
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1584
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1600
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1616
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1632
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1648
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1664
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1680
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1696
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1712
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1728
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1744
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1760
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1776
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1792
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1808
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1824
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1840
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1856
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1872
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1888
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1904
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1920
+ image: "listview.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1952
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1968
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1984
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2000
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2016
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2032
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2048
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2064
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2080
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2096
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2112
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2128
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2144
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2160
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2176
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2192
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2208
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2224
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2240
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2256
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2272
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2288
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2304
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2320
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2336
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2352
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2368
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2384
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2400
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2416
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2432
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2448
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2464
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2480
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2496
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2512
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2528
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2544
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2560
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2576
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2592
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 553; y: 267
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2608
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2624
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 554; y: 267
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 555; y: 266
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2640
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 556; y: 265
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 558; y: 260
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2656
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 560; y: 256
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2672
+ hash: "c315e184c4dcb11d7e9fd4509a8b6a1f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 562; y: 250
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 566; y: 234
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2688
+ hash: "aeef1cacca9518408519b670443e396f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 568; y: 216
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2704
+ hash: "621626927f83bf7b36b78f5ca7ed4ed0"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 572; y: 192
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 572; y: 192
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2720
+ hash: "b2aca965b745e98365195c52b9dd9a2c"
+ }
+ Frame {
+ msec: 2736
+ hash: "4cc8c162afcc45c79afd8230893d4ddd"
+ }
+ Frame {
+ msec: 2752
+ hash: "b9c0815086393878ad00566db7a3c577"
+ }
+ Frame {
+ msec: 2768
+ hash: "23cbc15fce97f966c24e3ec626e01960"
+ }
+ Frame {
+ msec: 2784
+ hash: "3a7ce897b47ba39e63be31a020de6f3d"
+ }
+ Frame {
+ msec: 2800
+ hash: "2a8a32cd27fad2c57c9eb518c7b3b3ca"
+ }
+ Frame {
+ msec: 2816
+ hash: "96d676ad58119430b440a5f0a2215f26"
+ }
+ Frame {
+ msec: 2832
+ hash: "5f9cd251615ee6a98470a7b6098f7890"
+ }
+ Frame {
+ msec: 2848
+ hash: "c9b1c073cbfbf1c353685b3f38baa675"
+ }
+ Frame {
+ msec: 2864
+ hash: "cf5bfbfe8904ea40b796d2b33d5cc363"
+ }
+ Frame {
+ msec: 2880
+ image: "listview.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "c75c3342b476f75fc0c5f56a374da13e"
+ }
+ Frame {
+ msec: 2912
+ hash: "0dfcd15d21b7e949b56bc69d881c52f5"
+ }
+ Frame {
+ msec: 2928
+ hash: "73b7352bb11d29cbf64b6b594e761e42"
+ }
+ Frame {
+ msec: 2944
+ hash: "876361c2fc18c2236c1dffd36f517f44"
+ }
+ Frame {
+ msec: 2960
+ hash: "0dfaf61e3a86ee056a5d76cf6f7994b2"
+ }
+ Frame {
+ msec: 2976
+ hash: "391995cfc5d8d3808b30d74ba5ea3188"
+ }
+ Frame {
+ msec: 2992
+ hash: "6fd4f14c16a8870355fa190c94e4be2d"
+ }
+ Frame {
+ msec: 3008
+ hash: "0aac04c8092505d934220e61c7959512"
+ }
+ Frame {
+ msec: 3024
+ hash: "6cb0fbe22fcd60b5ed6385e49522b32e"
+ }
+ Frame {
+ msec: 3040
+ hash: "2eb7fd1a773e32ae94284cf57efaaff2"
+ }
+ Frame {
+ msec: 3056
+ hash: "e143ed5eeb94b35ef97e965f34d45e4d"
+ }
+ Frame {
+ msec: 3072
+ hash: "529e85f2cd48c1f0d056682b8350445b"
+ }
+ Frame {
+ msec: 3088
+ hash: "d74bded985c00ecd192ff8fdce708450"
+ }
+ Frame {
+ msec: 3104
+ hash: "f71568b2173f72c4433a019775923c02"
+ }
+ Frame {
+ msec: 3120
+ hash: "1185a1c936ac08633c14d39ca9c4f5e9"
+ }
+ Frame {
+ msec: 3136
+ hash: "e641720bf75f1e4f0a8471f3a8b35094"
+ }
+ Frame {
+ msec: 3152
+ hash: "cecc41fb42abb95505c094829fd415bf"
+ }
+ Frame {
+ msec: 3168
+ hash: "7ad89090beb9de3cd7c5a5a03fca900d"
+ }
+ Frame {
+ msec: 3184
+ hash: "2a98fe4406367d4e286d8932d6a21318"
+ }
+ Frame {
+ msec: 3200
+ hash: "9aad024b2fc25ce886ccaa4ac106b1d8"
+ }
+ Frame {
+ msec: 3216
+ hash: "3c4a787a4d590efd2e72706e40df7b6d"
+ }
+ Frame {
+ msec: 3232
+ hash: "1135e06c2981bdaed13c13400e178dc3"
+ }
+ Frame {
+ msec: 3248
+ hash: "1fbceedf1c20f2aa3f05be36126280e2"
+ }
+ Frame {
+ msec: 3264
+ hash: "5d1ec83f43b649c732cc3f7815100428"
+ }
+ Frame {
+ msec: 3280
+ hash: "27501f6b6adccfdb77a5228611e2a95a"
+ }
+ Frame {
+ msec: 3296
+ hash: "218dc244352c14467f2b2a39d78a1bc7"
+ }
+ Frame {
+ msec: 3312
+ hash: "33a998563d2c053e375f619b7a75a224"
+ }
+ Frame {
+ msec: 3328
+ hash: "02d34b79e25367e6d0dc1765cab12353"
+ }
+ Frame {
+ msec: 3344
+ hash: "2698cf68138aa7d292167bcc85f60b74"
+ }
+ Frame {
+ msec: 3360
+ hash: "0b33e929b420596ff1dce2eeef8480db"
+ }
+ Frame {
+ msec: 3376
+ hash: "d8ec307a85cecaacaa908ceb34d5db5b"
+ }
+ Frame {
+ msec: 3392
+ hash: "4afe1df3e802b41d1b89b5fab4e35190"
+ }
+ Frame {
+ msec: 3408
+ hash: "e8f484ed8d2a6745ee87ac9544281d55"
+ }
+ Frame {
+ msec: 3424
+ hash: "6df053920e87d7e6e3ec0368b4b14c25"
+ }
+ Frame {
+ msec: 3440
+ hash: "6e94791acce321417a37132821c0260d"
+ }
+ Frame {
+ msec: 3456
+ hash: "fea3e31cbf3078615f57c934197dac35"
+ }
+ Frame {
+ msec: 3472
+ hash: "e8d15890a8bd95db39889d19f046901b"
+ }
+ Frame {
+ msec: 3488
+ hash: "038b422b154dfef2d955b833892c581e"
+ }
+ Frame {
+ msec: 3504
+ hash: "01180b3d9b504ca2814382eadaf3a4e0"
+ }
+ Frame {
+ msec: 3520
+ hash: "869a0aa0d67043822c65383e0f3264d4"
+ }
+ Frame {
+ msec: 3536
+ hash: "43785b1214510c10b65018a9d68a93b1"
+ }
+ Frame {
+ msec: 3552
+ hash: "95e6ebc35c2fb128b6e6ac0743268523"
+ }
+ Frame {
+ msec: 3568
+ hash: "f8c22a6ca3169de4d29b3b0e2908f581"
+ }
+ Frame {
+ msec: 3584
+ hash: "6baf16c321847d269718bcb3468aeeb2"
+ }
+ Frame {
+ msec: 3600
+ hash: "30804b5eb2a6d99116475cbdc1a9c043"
+ }
+ Frame {
+ msec: 3616
+ hash: "c892c17ec947a910b74f5b8704405e9f"
+ }
+ Frame {
+ msec: 3632
+ hash: "696029b77512943001c9eba64191e633"
+ }
+ Frame {
+ msec: 3648
+ hash: "4c26bb0ca28d74a2bb79d0bfc8127361"
+ }
+ Frame {
+ msec: 3664
+ hash: "6e8c50cc14c9afe73b4baf09a6a8f1a4"
+ }
+ Frame {
+ msec: 3680
+ hash: "fd20e4259b44357c93f22f35c698fe1b"
+ }
+ Frame {
+ msec: 3696
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3712
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3728
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3744
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3760
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3776
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3792
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3808
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3824
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3840
+ image: "listview.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3872
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3888
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3904
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3920
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3936
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3952
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3968
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3984
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4000
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4016
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4032
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4048
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4064
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4080
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4096
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4112
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4128
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4144
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 521; y: 24
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4160
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 25
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4176
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 32
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 37
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4192
+ hash: "a5df688148c264de1d376c9b87ddfa6b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 46
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4208
+ hash: "a4e2c1878b0afce0ee1eebd63e9c951a"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 66
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 88
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4224
+ hash: "2f9a79278d492790ef86a09c77e95ff4"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 531; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 531; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4240
+ hash: "5b5ce7206b26528157c426f4e1e3e0a8"
+ }
+ Frame {
+ msec: 4256
+ hash: "65a1e5f81ab89b163aed46b984cca45e"
+ }
+ Frame {
+ msec: 4272
+ hash: "e28253ad5a2415251b68bcda1d7d4bd0"
+ }
+ Frame {
+ msec: 4288
+ hash: "71aae5abb4a9e9077053ea21dd3ec315"
+ }
+ Frame {
+ msec: 4304
+ hash: "33fcea38fc3b328b3294f9ac2a26aa1a"
+ }
+ Frame {
+ msec: 4320
+ hash: "6299eb1d87f371966307668b92de6a0b"
+ }
+ Frame {
+ msec: 4336
+ hash: "4f66d8c7cb6971d0fc24089d123c547b"
+ }
+ Frame {
+ msec: 4352
+ hash: "d9906d61b31fabf968290ebcd6688f34"
+ }
+ Frame {
+ msec: 4368
+ hash: "5a1945993ff8096ba6b933d45586044a"
+ }
+ Frame {
+ msec: 4384
+ hash: "331535e54da9bbdbc2fbf2b244ad0199"
+ }
+ Frame {
+ msec: 4400
+ hash: "4dc39de0c54f6e0b77f94f6ae6c345ec"
+ }
+ Frame {
+ msec: 4416
+ hash: "ec309a298ce246c13eb666488eb75016"
+ }
+ Frame {
+ msec: 4432
+ hash: "a133819f8adc6265eb0e438261c869e3"
+ }
+ Frame {
+ msec: 4448
+ hash: "da4d64fd6b3ae7d49ee5c5c8d0117a37"
+ }
+ Frame {
+ msec: 4464
+ hash: "620dd1c3fc41ce657eac9d1a5b765fd4"
+ }
+ Frame {
+ msec: 4480
+ hash: "ff1c370bd1bf75a98ae7125e7dd5a9db"
+ }
+ Frame {
+ msec: 4496
+ hash: "59c6e4297109b5cc7c197749867dddae"
+ }
+ Frame {
+ msec: 4512
+ hash: "91b1719e86529d0c35a53a2d0a095dd6"
+ }
+ Frame {
+ msec: 4528
+ hash: "2994663d35c9eb453a27c1a1fa9aeeb8"
+ }
+ Frame {
+ msec: 4544
+ hash: "ae4ec37b9f6a00b3c9139e5cfe13d32e"
+ }
+ Frame {
+ msec: 4560
+ hash: "a98340236d1b65f47e88684168c1429d"
+ }
+ Frame {
+ msec: 4576
+ hash: "34848b483ea6a2bd412e29d26beb3ab0"
+ }
+ Frame {
+ msec: 4592
+ hash: "dd9bae0e2fca84b265d8cb59686ff88d"
+ }
+ Frame {
+ msec: 4608
+ hash: "18b6ef6f5913b0612b76e7b2e25073dd"
+ }
+ Frame {
+ msec: 4624
+ hash: "9398aab9478279aed1bc40c9378f8da4"
+ }
+ Frame {
+ msec: 4640
+ hash: "a297a304c12102f23bd1e0f0207e0df9"
+ }
+ Frame {
+ msec: 4656
+ hash: "091db9138cd6ae801ad857105a83c8f9"
+ }
+ Frame {
+ msec: 4672
+ hash: "253938ca4a4f13433ddd502eb94cb7cd"
+ }
+ Frame {
+ msec: 4688
+ hash: "6002df1793d290e4e31ee0c91c37bbe6"
+ }
+ Frame {
+ msec: 4704
+ hash: "212476fa1c3a52fb8eba03ec3aecdcd8"
+ }
+ Frame {
+ msec: 4720
+ hash: "80d4d8434d4e96a2bc23f5ed060d6ddc"
+ }
+ Frame {
+ msec: 4736
+ hash: "2d4add725f31a04558635ce4b73a758a"
+ }
+ Frame {
+ msec: 4752
+ hash: "57c06022ec1e502c4f49f43063c433e7"
+ }
+ Frame {
+ msec: 4768
+ hash: "8393e97990993f9d5f68ea65f8e4a2db"
+ }
+ Frame {
+ msec: 4784
+ hash: "9a1fcd96dffaf5c79ecc7f9427e02499"
+ }
+ Frame {
+ msec: 4800
+ image: "listview.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "5ae722cf541e3453e73bbee57dc379e9"
+ }
+ Frame {
+ msec: 4832
+ hash: "fc7326c2e2e56d9c3036e8dfc2ea77a8"
+ }
+ Frame {
+ msec: 4848
+ hash: "f22a2a68cea158f333b0457025d75490"
+ }
+ Frame {
+ msec: 4864
+ hash: "d684c8aa9b835779080f170cafead40f"
+ }
+ Frame {
+ msec: 4880
+ hash: "dd451e5e421f929d015981bc7aeb8c66"
+ }
+ Frame {
+ msec: 4896
+ hash: "d066f228295db7f46520495167d3e946"
+ }
+ Frame {
+ msec: 4912
+ hash: "ebf640a457e3498bade3220aafa70331"
+ }
+ Frame {
+ msec: 4928
+ hash: "190f5b1f3ce9d200790c34c50bcc62c5"
+ }
+ Frame {
+ msec: 4944
+ hash: "9d4ad865246eb008afa40740b5c9a208"
+ }
+ Frame {
+ msec: 4960
+ hash: "81c8b2c0b4f9e74f24d328a1d9b40a9f"
+ }
+ Frame {
+ msec: 4976
+ hash: "24acc300307e71bee79bce8de76f56cb"
+ }
+ Frame {
+ msec: 4992
+ hash: "1f9d31f94cfce6f868bfcc8a104d2465"
+ }
+ Frame {
+ msec: 5008
+ hash: "7a3cab008dcb7a893ae30797b33df6f2"
+ }
+ Frame {
+ msec: 5024
+ hash: "38d561a2950434e59513439c7f1120ea"
+ }
+ Frame {
+ msec: 5040
+ hash: "8d34131faa15bc126bd4d9ef3be39ef5"
+ }
+ Frame {
+ msec: 5056
+ hash: "85d57ef15791b56deb537795dd87911e"
+ }
+ Frame {
+ msec: 5072
+ hash: "71e932169915a6c8c2cef0b22febf316"
+ }
+ Frame {
+ msec: 5088
+ hash: "8b3452981963aeebadc9ac2013150263"
+ }
+ Frame {
+ msec: 5104
+ hash: "a3fb8abecfeb48ba1cd1fd8f40896fa0"
+ }
+ Frame {
+ msec: 5120
+ hash: "f53ab533f6a58ae45139f3da4bf8ab4e"
+ }
+ Frame {
+ msec: 5136
+ hash: "9ec7012404f3c1c7795810dcee5acc3b"
+ }
+ Frame {
+ msec: 5152
+ hash: "99ca43bab532dd5d7566e596c65053ce"
+ }
+ Frame {
+ msec: 5168
+ hash: "0af83ad2416821cc230cd2856d1a3e39"
+ }
+ Frame {
+ msec: 5184
+ hash: "86fa23ddf2005bbf35238ae04ae554ac"
+ }
+ Frame {
+ msec: 5200
+ hash: "bb52a748f1d85dde410cfa4f24e3ed20"
+ }
+ Frame {
+ msec: 5216
+ hash: "898b96bc5ee9a3ac61764e5cd9af8cfb"
+ }
+ Frame {
+ msec: 5232
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5248
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5264
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5280
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5296
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5312
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5328
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5344
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5360
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5376
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5392
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5408
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5424
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5440
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5456
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5472
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5488
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5504
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5520
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5536
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5552
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5568
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5584
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5600
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5616
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5632
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5648
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5664
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5680
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5696
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5712
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5728
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5744
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5760
+ image: "listview.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5792
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5808
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5824
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5840
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5856
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5872
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5888
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5904
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5920
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5936
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5952
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5968
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 111; y: 230
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 227
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5984
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 223
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6000
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 216
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 210
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6016
+ hash: "0076b55d3da4ca365688b6a2c984103f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 112; y: 205
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6032
+ hash: "db846ad8e3200ca1fce36a38dc7beab8"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 112; y: 192
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6048
+ hash: "3cb6b25725b4285f9c096d595224c5ca"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 180
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6064
+ hash: "1832e12fdf3b464b02b296e727b33694"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 110; y: 173
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6080
+ hash: "6d18d2b5f65cbba4915d0725d24b40f3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 109; y: 158
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 107; y: 140
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6096
+ hash: "79bc7afc6b1aa5f8904b3e6d5d4a9389"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 103; y: 124
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6112
+ hash: "4436f2d15304c839aacec486c1fd6d96"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6128
+ hash: "c3bffc7c95893cf9bbd8596208b7f657"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 105
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 100
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6144
+ hash: "04231c2fdc02729aa34ed4e403dd373b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 96
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6160
+ hash: "392d75c4b372825e78366eb63a618170"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 87
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 102; y: 83
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6176
+ hash: "7f91f7bdb0cb62d600ac4aa573681fe3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 102; y: 79
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6192
+ hash: "69207181a382650c5e33145555f0d9ba"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 103; y: 76
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 103; y: 72
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6208
+ hash: "65a184b5c49b02e08114e437483f928d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 104; y: 68
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 105; y: 64
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6224
+ hash: "c22da9ce54d04f51fb55da755753a509"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 105; y: 61
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6240
+ hash: "59dbd5216847a62f60a1d0701a15bb62"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 106; y: 57
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 106; y: 53
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6256
+ hash: "bbfc902db6e6ca253afb1c90306b2a63"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 106; y: 47
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 106; y: 47
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6272
+ hash: "5c41f194afec5f7e3db9d98673d03d5c"
+ }
+ Frame {
+ msec: 6288
+ hash: "deb06d0f915d5f6ec39b1820d57b6af6"
+ }
+ Frame {
+ msec: 6304
+ hash: "deb06d0f915d5f6ec39b1820d57b6af6"
+ }
+ Frame {
+ msec: 6320
+ hash: "2a1a1f9239a6ccb308e51796f9b0bb89"
+ }
+ Frame {
+ msec: 6336
+ hash: "3c1b44201616b8271023bf05a3f3f0f7"
+ }
+ Frame {
+ msec: 6352
+ hash: "87afcef49db8b2b547e85e834f8ec304"
+ }
+ Frame {
+ msec: 6368
+ hash: "290081b4b1272ef09ec9964c128e61b5"
+ }
+ Frame {
+ msec: 6384
+ hash: "19bb3b23ee4b14a5f0a313106ef7c8c1"
+ }
+ Frame {
+ msec: 6400
+ hash: "65a184b5c49b02e08114e437483f928d"
+ }
+ Frame {
+ msec: 6416
+ hash: "832d2aefbcaf776f35039be527d367c5"
+ }
+ Frame {
+ msec: 6432
+ hash: "69207181a382650c5e33145555f0d9ba"
+ }
+ Frame {
+ msec: 6448
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6464
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6480
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6496
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6512
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6528
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6544
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6560
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6576
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6592
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6608
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6624
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6640
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6656
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6672
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6688
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6704
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6720
+ image: "listview.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6752
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6768
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6784
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6800
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6816
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6832
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6848
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6864
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6880
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6896
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6912
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6928
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6944
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6960
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6976
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6992
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7008
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7024
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7040
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7056
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7072
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7088
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7104
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7120
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7136
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7152
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7168
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7184
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7200
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7216
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7232
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7248
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7264
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7280
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7296
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 519; y: 276
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7312
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 519; y: 275
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7328
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 519; y: 274
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7344
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 273
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 272
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7360
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 271
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7376
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 268
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7392
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 266
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 265
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7408
+ hash: "9047f597b9e59ca652c172338bed6ef9"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 262
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7424
+ hash: "87476f78daecd6bb49e8d6e673d28100"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 260
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7440
+ hash: "6bfd895c6b7d97e4102eb26608cdfeca"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 254
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7456
+ hash: "e4c2b75beaee54a5781a5acbeb37ea64"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 249
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7472
+ hash: "d5e816768e9c3db0631416bd86b1b461"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 243
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7488
+ hash: "df6c7252ebb51e7447396b640e1c6ead"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 237
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7504
+ hash: "5f4db5386dc76b9f2dac47618c733dee"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 231
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7520
+ hash: "534d1d16d8321996969b54875ec5f1e0"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 225
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7536
+ hash: "5263016e53327df1972498b55a60c0ed"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 219
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7552
+ hash: "6787a5a16d2a61643bb1435f6488ada6"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 215
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7568
+ hash: "1feabcd683590c3d28d899167e6278b3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 519; y: 208
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7584
+ hash: "c0495d6083b2e4ddd2b1dca2f231529c"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 520; y: 202
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7600
+ hash: "cb302493a17c1806dfcdf002c44e7acd"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 196
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7616
+ hash: "f3822b79b678532ce7f826952636be90"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 189
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7632
+ hash: "6e30eed182c38be110ba9c7e95b223be"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 185
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7648
+ hash: "9e3ad0331c0c041b9a5747a1d44a43fe"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 177
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7664
+ hash: "791e6abf9dae670770c2429ee9f1ad71"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 169
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7680
+ image: "listview.7.png"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 160
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7696
+ hash: "d3ae366fb8212cb987e23150802c88e3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 156
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7712
+ hash: "b87708e19d7e8b64fe1ab50ec1723975"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 147
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7728
+ hash: "512678e45cdd8d48e10b08ee020afe8e"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 144
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7744
+ hash: "211aa70e813819d476996b3396e9e5a0"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7760
+ hash: "f16eaa360604be84ce61364ad9733b52"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 130
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7776
+ hash: "d3af36dfb187d08abe1458f186a935a2"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 124
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7792
+ hash: "9d0a0ba1deb7c4a4a8838e5e6a27f2f6"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 122
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7808
+ hash: "69aac14f4c137e66724ca33f00a86676"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 116
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7824
+ hash: "893d56e2a2ca257fae9f0c6c0629903d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7840
+ hash: "b9f734e57a72e33973740a59776948d9"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 106
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7856
+ hash: "e4b0f3f6a6785d7a183e4a36c5803301"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 104
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7872
+ hash: "99ee1e8803c05e546a721b0c9ee39499"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 101
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7888
+ hash: "96e7da2f895500a786ed36cb295e9003"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 99
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7904
+ hash: "cd369fc5dc31814208e56cf7cd0decea"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 97
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7920
+ hash: "5fee72994b65a45b4900a3073f86a3e1"
+ }
+ Frame {
+ msec: 7936
+ hash: "9a2f8a65d842b8f92998e6411f7cd53c"
+ }
+ Frame {
+ msec: 7952
+ hash: "2848d69017ce71ae101ccdfa7c67f933"
+ }
+ Frame {
+ msec: 7968
+ hash: "6568aa88e81f988f65da435df7166167"
+ }
+ Frame {
+ msec: 7984
+ hash: "d5f15ee08a2d7667786757a378a7a7f4"
+ }
+ Frame {
+ msec: 8000
+ hash: "9b566bd02a561b32d1a4c1ec99c2e2c3"
+ }
+ Frame {
+ msec: 8016
+ hash: "580419e1c9e91046547d913f6b8790a4"
+ }
+ Frame {
+ msec: 8032
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8048
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8064
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 521; y: 97
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8080
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8096
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8112
+ hash: "83b91a371d682a501bc3a3fceabe4f8c"
+ }
+ Frame {
+ msec: 8128
+ hash: "798b1dbfa0cce362213f426e2c60ac0e"
+ }
+ Frame {
+ msec: 8144
+ hash: "d71b6a693c430a618c23413cb65bb320"
+ }
+ Frame {
+ msec: 8160
+ hash: "2baae394390da39447a67151bc503d65"
+ }
+ Frame {
+ msec: 8176
+ hash: "06688b05c61a7b862d39534207a8adab"
+ }
+ Frame {
+ msec: 8192
+ hash: "a1d3042e16709817906dcdc673ee52c7"
+ }
+ Frame {
+ msec: 8208
+ hash: "236dd41feac1b1a8a4bd7911bb184da2"
+ }
+ Frame {
+ msec: 8224
+ hash: "f3ec821bba1d32e90bdab0e85c07d7d8"
+ }
+ Frame {
+ msec: 8240
+ hash: "e328c35adf7ffc3d7e3af97e798ec8a5"
+ }
+ Frame {
+ msec: 8256
+ hash: "651101db68fd3ed1dc5f441c126dc31b"
+ }
+ Frame {
+ msec: 8272
+ hash: "651101db68fd3ed1dc5f441c126dc31b"
+ }
+ Frame {
+ msec: 8288
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8304
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8320
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8336
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8352
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8368
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8384
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8400
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8416
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8432
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8448
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8464
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8480
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8496
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8512
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8528
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8544
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8560
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8576
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8592
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8608
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8624
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8640
+ image: "listview.8.png"
+ }
+ Frame {
+ msec: 8656
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8672
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8688
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8704
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8720
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8736
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8752
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8768
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8784
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8800
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8816
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8832
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8848
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8864
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8880
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8896
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8912
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8928
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8944
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8960
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8976
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8992
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9008
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9024
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9040
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9056
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9072
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9088
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9104
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9120
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9136
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9152
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9168
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9184
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9200
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9216
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9232
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9248
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9264
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9280
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9296
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9312
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9328
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9344
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9360
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9376
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9392
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9408
+ hash: "1171be123a361d72859c25434573482c"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-X11/basic1.qml b/tests/auto/declarative/visual/ListView/data-X11/basic1.qml
new file mode 100644
index 0000000..ae59b14
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-X11/basic1.qml
@@ -0,0 +1,159 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 32
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 48
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 64
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 80
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 96
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 112
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 128
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 144
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 160
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 176
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 192
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 208
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 224
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 240
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 256
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 272
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 288
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 304
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 320
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 336
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 352
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 368
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 384
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 400
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 416
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 432
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 448
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 464
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 480
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 496
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 512
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 528
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 544
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 560
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 576
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-X11/basic2.qml b/tests/auto/declarative/visual/ListView/data-X11/basic2.qml
new file mode 100644
index 0000000..ff19d22
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-X11/basic2.qml
@@ -0,0 +1,187 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 32
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 48
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 64
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 80
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 96
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 112
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 128
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 144
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 160
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 176
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 192
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 208
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 224
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 240
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 256
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 272
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 288
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 304
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 320
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 336
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 352
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 368
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 384
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 400
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 416
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 432
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 448
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 464
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 480
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 496
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 512
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 528
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 544
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 560
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 576
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 592
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 608
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 624
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 640
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 656
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 672
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 688
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-X11/basic3.qml b/tests/auto/declarative/visual/ListView/data-X11/basic3.qml
new file mode 100644
index 0000000..2f33cae
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-X11/basic3.qml
@@ -0,0 +1,147 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 32
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 48
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 64
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 80
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 96
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 112
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 128
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 144
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 160
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 176
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 192
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 208
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 224
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 240
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 256
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 272
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 288
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 304
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 320
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 336
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 352
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 368
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 384
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 400
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 416
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 432
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 448
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 464
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 480
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 496
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 512
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 528
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data-X11/basic4.qml b/tests/auto/declarative/visual/ListView/data-X11/basic4.qml
new file mode 100644
index 0000000..4b1c5cf
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data-X11/basic4.qml
@@ -0,0 +1,171 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 32
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 48
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 64
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 80
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 96
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 112
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 128
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 144
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 160
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 176
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 192
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 208
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 224
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 240
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 256
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 272
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 288
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 304
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 320
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 336
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 352
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 368
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 384
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 400
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 416
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 432
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 448
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 464
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 480
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 496
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 512
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 528
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 544
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 560
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 576
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 592
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 608
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+ Frame {
+ msec: 624
+ hash: "c0dc2737283d8dfa62631e0cbb948b99"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data/basic1.qml b/tests/auto/declarative/visual/ListView/data/basic1.qml
new file mode 100644
index 0000000..4cd44fc
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/basic1.qml
@@ -0,0 +1,159 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 32
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 48
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 64
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 80
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 96
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 112
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 128
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 144
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 160
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 176
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 192
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 208
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 224
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 240
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 256
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 272
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 288
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 304
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 320
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 336
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 352
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 368
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 384
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 400
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 416
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 432
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 448
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 464
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 480
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 496
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 512
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 528
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 544
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 560
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 576
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data/basic2.qml b/tests/auto/declarative/visual/ListView/data/basic2.qml
new file mode 100644
index 0000000..34ad5ed
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/basic2.qml
@@ -0,0 +1,187 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 32
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 48
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 64
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 80
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 96
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 112
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 128
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 144
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 160
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 176
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 192
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 208
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 224
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 240
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 256
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 272
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 288
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 304
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 320
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 336
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 352
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 368
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 384
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 400
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 416
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 432
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 448
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 464
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 480
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 496
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 512
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 528
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 544
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 560
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 576
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 592
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 608
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 624
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 640
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 656
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 672
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 688
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data/basic3.qml b/tests/auto/declarative/visual/ListView/data/basic3.qml
new file mode 100644
index 0000000..1c5ddb0
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/basic3.qml
@@ -0,0 +1,147 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 32
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 48
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 64
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 80
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 96
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 112
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 128
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 144
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 160
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 176
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 192
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 208
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 224
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 240
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 256
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 272
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 288
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 304
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 320
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 336
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 352
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 368
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 384
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 400
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 416
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 432
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 448
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 464
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 480
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 496
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 512
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 528
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data/basic4.qml b/tests/auto/declarative/visual/ListView/data/basic4.qml
new file mode 100644
index 0000000..d121d91
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/basic4.qml
@@ -0,0 +1,171 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 32
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 48
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 64
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 80
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 96
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 112
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 128
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 144
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 160
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 176
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 192
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 208
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 224
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 240
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 256
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 272
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 288
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 304
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 320
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 336
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 352
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 368
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 384
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 400
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 416
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 432
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 448
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 464
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 480
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 496
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 512
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 528
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 544
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 560
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 576
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 592
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 608
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+ Frame {
+ msec: 624
+ hash: "c0ec1bac5550efaa1f8ce7b46c2fed94"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.0.png b/tests/auto/declarative/visual/ListView/data/itemlist.0.png
new file mode 100644
index 0000000..a1947ca
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.1.png b/tests/auto/declarative/visual/ListView/data/itemlist.1.png
new file mode 100644
index 0000000..d27b7fa
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.2.png b/tests/auto/declarative/visual/ListView/data/itemlist.2.png
new file mode 100644
index 0000000..fdab8c6
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.3.png b/tests/auto/declarative/visual/ListView/data/itemlist.3.png
new file mode 100644
index 0000000..dc321a8
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.4.png b/tests/auto/declarative/visual/ListView/data/itemlist.4.png
new file mode 100644
index 0000000..fdab8c6
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.5.png b/tests/auto/declarative/visual/ListView/data/itemlist.5.png
new file mode 100644
index 0000000..15b51cb
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.6.png b/tests/auto/declarative/visual/ListView/data/itemlist.6.png
new file mode 100644
index 0000000..a1947ca
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/itemlist.qml b/tests/auto/declarative/visual/ListView/data/itemlist.qml
new file mode 100644
index 0000000..073749f
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/itemlist.qml
@@ -0,0 +1,2203 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 32
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 48
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 64
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 80
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 96
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 112
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 128
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 144
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 160
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 176
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 192
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 208
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 224
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 240
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 256
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 272
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 288
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 304
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 320
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 336
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 352
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 368
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 384
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 400
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 416
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 432
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 448
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 464
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 480
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 496
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 512
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 528
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 544
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 560
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 576
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 592
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 608
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 624
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 640
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 656
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 672
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 688
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 704
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 720
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 736
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 752
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 768
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 784
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 800
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 816
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 832
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 848
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 864
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 880
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 896
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 912
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 928
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 944
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 960
+ image: "itemlist.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 992
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1008
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1024
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1040
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1056
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1072
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1088
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1104
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1120
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1136
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1152
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1168
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1184
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1200
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1216
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1232
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1248
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1264
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1280
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1296
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1312
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1328
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1344
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1360
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1376
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1392
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1408
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1424
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1440
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1456
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1472
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1488
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1504
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1520
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1536
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1552
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1568
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1584
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1600
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1616
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1632
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 1648
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 192; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1664
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 191; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1680
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 190; y: 112
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 187; y: 113
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1696
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 184; y: 113
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 180; y: 113
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1712
+ hash: "a68b1bc6c2963ee92c3a45f500667b3b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 174; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 167; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1728
+ hash: "7cda93e59466b3348e7ffe3895f89e86"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 160; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1744
+ hash: "06e0008c78e919f7270402938d9d764b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 140; y: 121
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 132; y: 122
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1760
+ hash: "9d8da9199efebb95f56e5d4ebc9a585e"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 114; y: 126
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 98; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1776
+ hash: "54a60a4279911ba4a8a5741bcadfa783"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 91; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 91; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1792
+ hash: "a1a19370a1a8ed78e475f0d0eb12311c"
+ }
+ Frame {
+ msec: 1808
+ hash: "196a3b127cf7065614c34856bf8d8bca"
+ }
+ Frame {
+ msec: 1824
+ hash: "5fbefbd7c7be4374382cc4c8b86ac78a"
+ }
+ Frame {
+ msec: 1840
+ hash: "d6a544c622e504c1b931e1a8a1310a6e"
+ }
+ Frame {
+ msec: 1856
+ hash: "20e76f0eb4ec5f691999faf8ad313370"
+ }
+ Frame {
+ msec: 1872
+ hash: "7f84a3545907c754ae8a6a30ef61c98d"
+ }
+ Frame {
+ msec: 1888
+ hash: "b544901eae32903ad054e8cdfed715eb"
+ }
+ Frame {
+ msec: 1904
+ hash: "a010ed1e3312f4ca9f429b7e32cdcef9"
+ }
+ Frame {
+ msec: 1920
+ image: "itemlist.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "93a731dc6f71b6ff5400bf74c87e6c46"
+ }
+ Frame {
+ msec: 1952
+ hash: "c73f63d1a024ba956e693487b3ccc761"
+ }
+ Frame {
+ msec: 1968
+ hash: "539d3d00fce2d0128cd697d86d237fe7"
+ }
+ Frame {
+ msec: 1984
+ hash: "52752d7d6f2d0e085f7132313907b72b"
+ }
+ Frame {
+ msec: 2000
+ hash: "f46dd5803a6075e979e0fc733d503bfb"
+ }
+ Frame {
+ msec: 2016
+ hash: "b8734698a6bad00ecf019f85328c2c21"
+ }
+ Frame {
+ msec: 2032
+ hash: "1cfc499ca756023430cc5b2fa95a599d"
+ }
+ Frame {
+ msec: 2048
+ hash: "63a816548837c19f8f0494c137fc0174"
+ }
+ Frame {
+ msec: 2064
+ hash: "1bce9b85235e9a1a472c079dfec70ec5"
+ }
+ Frame {
+ msec: 2080
+ hash: "6677863e7f74c12648409883f73adbe2"
+ }
+ Frame {
+ msec: 2096
+ hash: "98e707a3e39a5f7bd4a101c2ed83535c"
+ }
+ Frame {
+ msec: 2112
+ hash: "c1f6d8842d14a9394d4b7797314f50e8"
+ }
+ Frame {
+ msec: 2128
+ hash: "579758b477bcd2112b305a5aac7df338"
+ }
+ Frame {
+ msec: 2144
+ hash: "4a7bb81090db246db53e2dbc56f710ea"
+ }
+ Frame {
+ msec: 2160
+ hash: "074995cdd8a70817d1c8a7bb0ad4c542"
+ }
+ Frame {
+ msec: 2176
+ hash: "bd8d7bda4d2e9ad1fba2895d568f36cc"
+ }
+ Frame {
+ msec: 2192
+ hash: "40cce3d2d80ac470af44fc334cec1d5b"
+ }
+ Frame {
+ msec: 2208
+ hash: "15cbc226b032d5a97199735ea7a1408b"
+ }
+ Frame {
+ msec: 2224
+ hash: "12b296aea9b058a5402d0d0a620f8edc"
+ }
+ Frame {
+ msec: 2240
+ hash: "6ffd2b79cf0e941a59e74bc6f9025bcb"
+ }
+ Frame {
+ msec: 2256
+ hash: "589a58ef76ea709dc8d80390c9044f99"
+ }
+ Frame {
+ msec: 2272
+ hash: "c009924bfa30153f22ab168b539494e9"
+ }
+ Frame {
+ msec: 2288
+ hash: "4b83674a7c2daa68d735901ad40be2bd"
+ }
+ Frame {
+ msec: 2304
+ hash: "0525908c0302ada989e28990bac3f2ca"
+ }
+ Frame {
+ msec: 2320
+ hash: "89eb13976ba3ba4413cafeb0cc91c01b"
+ }
+ Frame {
+ msec: 2336
+ hash: "75c1295ef99680784b2e11fb88fa1423"
+ }
+ Frame {
+ msec: 2352
+ hash: "93d89165cf6a97c76ae6e7f75678a3cd"
+ }
+ Frame {
+ msec: 2368
+ hash: "53064c1938f08a55603a99b0db225174"
+ }
+ Frame {
+ msec: 2384
+ hash: "31db5684466c0c32128a9a8c7b1835e1"
+ }
+ Frame {
+ msec: 2400
+ hash: "99d9e58697736198e0a00443d237e85b"
+ }
+ Frame {
+ msec: 2416
+ hash: "6c1e860aef983367365d53f5849ad441"
+ }
+ Frame {
+ msec: 2432
+ hash: "6c1e860aef983367365d53f5849ad441"
+ }
+ Frame {
+ msec: 2448
+ hash: "6c1e860aef983367365d53f5849ad441"
+ }
+ Frame {
+ msec: 2464
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2480
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2496
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2512
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2528
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2544
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2560
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2576
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2592
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2608
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2624
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2640
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2656
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2672
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2688
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2704
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2720
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2736
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2752
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2768
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2784
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2800
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2816
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2832
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2848
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 2864
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 181; y: 104
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2880
+ image: "itemlist.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 179; y: 105
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 177; y: 106
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2912
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 174; y: 108
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 170; y: 110
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2928
+ hash: "5bb06b4e74532ba5bc8c7bc38bf77d7f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 166; y: 112
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 160; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2944
+ hash: "b10a6206830a876017799ef2fcf61b1a"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 154; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 140; y: 123
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2960
+ hash: "b2e24759ba10afd6cff90f4b1e04b496"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 124; y: 127
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 124; y: 127
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2976
+ hash: "ccbcd6f45cb529c2db71504c0f69d73e"
+ }
+ Frame {
+ msec: 2992
+ hash: "7b31c6d5931677f1aa1e8c7d48a4ff22"
+ }
+ Frame {
+ msec: 3008
+ hash: "c52f691a0a6cf155118bdfea2dfea623"
+ }
+ Frame {
+ msec: 3024
+ hash: "dd639d1df3d4a9b8f06718def63d588f"
+ }
+ Frame {
+ msec: 3040
+ hash: "39d767b09a648ef6295cec2848f9226f"
+ }
+ Frame {
+ msec: 3056
+ hash: "5dd46d5f386431e7b13348ac9a9630ed"
+ }
+ Frame {
+ msec: 3072
+ hash: "0354e5183b0e66e7ba146d292c559df4"
+ }
+ Frame {
+ msec: 3088
+ hash: "984aa6d7075e24de429e05b1b0eda94a"
+ }
+ Frame {
+ msec: 3104
+ hash: "1af58a2f44f1f613712d4df85e38356d"
+ }
+ Frame {
+ msec: 3120
+ hash: "6e4085e7f1fee724d78808753f04b471"
+ }
+ Frame {
+ msec: 3136
+ hash: "73a019ef9057639d631cd99a431b3f3b"
+ }
+ Frame {
+ msec: 3152
+ hash: "c9414a2e655a90dfdcb6fb288b4ba0ca"
+ }
+ Frame {
+ msec: 3168
+ hash: "3f4c24f7ac89da982af22032309637fb"
+ }
+ Frame {
+ msec: 3184
+ hash: "a50e6ada8f73a257657f4348ceaffcfd"
+ }
+ Frame {
+ msec: 3200
+ hash: "a67bf40d09259bbd079c12ae4f49150f"
+ }
+ Frame {
+ msec: 3216
+ hash: "a2fc512b7c234a9d0b2c1a83387a8a46"
+ }
+ Frame {
+ msec: 3232
+ hash: "85090683ce9a3c9833b1cb0b3df076ee"
+ }
+ Frame {
+ msec: 3248
+ hash: "275f3594a0e2cc4b6717f9f336e7e1b6"
+ }
+ Frame {
+ msec: 3264
+ hash: "2473eb11f7b65a784a2b166114026488"
+ }
+ Frame {
+ msec: 3280
+ hash: "4865c30dc45fbf5ca82047b77eca0912"
+ }
+ Frame {
+ msec: 3296
+ hash: "54de88bca395449fbaea2c090c7a5d91"
+ }
+ Frame {
+ msec: 3312
+ hash: "833f9295cf9a34934f001eac48551b59"
+ }
+ Frame {
+ msec: 3328
+ hash: "5bf565f57ababa7380faeee94add91ca"
+ }
+ Frame {
+ msec: 3344
+ hash: "6325578867f1eb3b2d47ed40b017b571"
+ }
+ Frame {
+ msec: 3360
+ hash: "046a6114176b3a3206b7a2acd6e30b41"
+ }
+ Frame {
+ msec: 3376
+ hash: "f8d4120a17f28c2d1d9c4be959098058"
+ }
+ Frame {
+ msec: 3392
+ hash: "71356d2e48aad2900784ea6bc1a3d908"
+ }
+ Frame {
+ msec: 3408
+ hash: "b84ad460fb81fdc4049abe8f3ff180bb"
+ }
+ Frame {
+ msec: 3424
+ hash: "0354239f5eaea23474d9f81385392a8a"
+ }
+ Frame {
+ msec: 3440
+ hash: "8ef0eef3393e07ae7605c865a95edc30"
+ }
+ Frame {
+ msec: 3456
+ hash: "5b8b384cc8e3faf4310015e19b3eb487"
+ }
+ Frame {
+ msec: 3472
+ hash: "77c18ac7dfff2a4e516915e3e3df0717"
+ }
+ Frame {
+ msec: 3488
+ hash: "c1d3264384c26345eb8100de829309ca"
+ }
+ Frame {
+ msec: 3504
+ hash: "6b21f71d0bedef4bbcb445a13f61e7a3"
+ }
+ Frame {
+ msec: 3520
+ hash: "f619097356671f6eb54d3b1c481e709d"
+ }
+ Frame {
+ msec: 3536
+ hash: "e56e3a90da446e0c482cb93717f6aacc"
+ }
+ Frame {
+ msec: 3552
+ hash: "aa94ebdbb4b8423aff28c95daff0baf5"
+ }
+ Frame {
+ msec: 3568
+ hash: "e1744d9cacd1a2c96af4cfdd5c486995"
+ }
+ Frame {
+ msec: 3584
+ hash: "7f19ea52e9e41a3b1bd90bb2a144d305"
+ }
+ Frame {
+ msec: 3600
+ hash: "7f19ea52e9e41a3b1bd90bb2a144d305"
+ }
+ Frame {
+ msec: 3616
+ hash: "7f19ea52e9e41a3b1bd90bb2a144d305"
+ }
+ Frame {
+ msec: 3632
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3648
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3664
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3680
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3696
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3712
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3728
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3744
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3760
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3776
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3792
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3808
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3824
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3840
+ image: "itemlist.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3872
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3888
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3904
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3920
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3936
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3952
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3968
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 3984
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4000
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4016
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4032
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4048
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4064
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4080
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Frame {
+ msec: 4096
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 31; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4112
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 32; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4128
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 33; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 36; y: 135
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4144
+ hash: "88143ff6c278a5433b314b551b7b8b1d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 40; y: 134
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 132
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4160
+ hash: "c2c9c284b185a89faf4ddb5a7867f449"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 64; y: 130
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4176
+ hash: "de1c18aeda5d2fbd6dad4554c78617bd"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 86; y: 126
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 110; y: 118
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 110; y: 118
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4192
+ hash: "a67bf40d09259bbd079c12ae4f49150f"
+ }
+ Frame {
+ msec: 4208
+ hash: "94514668dafbe41c5890a578efd6dea4"
+ }
+ Frame {
+ msec: 4224
+ hash: "2e97a74eb9ddb1c9613c89e2d78db018"
+ }
+ Frame {
+ msec: 4240
+ hash: "4b5368f0d86bffeb6bd31b58aec88650"
+ }
+ Frame {
+ msec: 4256
+ hash: "b459bde7bb4ce51e6ecdab58f64fcbb9"
+ }
+ Frame {
+ msec: 4272
+ hash: "7bac8cc3ec64c9ad1c0da282e38c953e"
+ }
+ Frame {
+ msec: 4288
+ hash: "a73a58c3d7a757547740a2a161f4c756"
+ }
+ Frame {
+ msec: 4304
+ hash: "b35edcb1fa3568a3e770ab2364b82e75"
+ }
+ Frame {
+ msec: 4320
+ hash: "d6c863ef57c5e5cb04cdac72f920db0b"
+ }
+ Frame {
+ msec: 4336
+ hash: "0db5e4588ff851918b07796f0cf07382"
+ }
+ Frame {
+ msec: 4352
+ hash: "71ec8c363ca6a6f7556afb70faccffe6"
+ }
+ Frame {
+ msec: 4368
+ hash: "18d026e9c965ada1db67c643576d2a80"
+ }
+ Frame {
+ msec: 4384
+ hash: "69f71c22dff981a4da8ec1edcf90e79f"
+ }
+ Frame {
+ msec: 4400
+ hash: "680460f5e4d9e649931601041af046b2"
+ }
+ Frame {
+ msec: 4416
+ hash: "3028763fd15de2607b20b1331b904a4a"
+ }
+ Frame {
+ msec: 4432
+ hash: "333eb60e217fe1ea7469eab52ac461f1"
+ }
+ Frame {
+ msec: 4448
+ hash: "ccbcd6f45cb529c2db71504c0f69d73e"
+ }
+ Frame {
+ msec: 4464
+ hash: "3445df9b41a0a3e74738cbf328ab7d5c"
+ }
+ Frame {
+ msec: 4480
+ hash: "bd2c072558479e9de7a97207e58cc57f"
+ }
+ Frame {
+ msec: 4496
+ hash: "3d34b0b24a30eda93377dcb4585afed8"
+ }
+ Frame {
+ msec: 4512
+ hash: "d3045703863b0c5a327b9355c23d69f2"
+ }
+ Frame {
+ msec: 4528
+ hash: "2f2eb55f693415b840a317211b250e9f"
+ }
+ Frame {
+ msec: 4544
+ hash: "791b9ca7d47a3343474c30a35e336d4b"
+ }
+ Frame {
+ msec: 4560
+ hash: "73a0c02ebad6d3d5f939d9a00dd898bf"
+ }
+ Frame {
+ msec: 4576
+ hash: "d5c11135d586711b12f236430a2c2795"
+ }
+ Frame {
+ msec: 4592
+ hash: "34f9ea214fe714ff4e994f715ea6ea39"
+ }
+ Frame {
+ msec: 4608
+ hash: "8e49afa00983b156b818533923fb6edd"
+ }
+ Frame {
+ msec: 4624
+ hash: "e7e7bef17cee92eca9191fd734d7a577"
+ }
+ Frame {
+ msec: 4640
+ hash: "e407f6ed7cb3c130365ab5515d6308c0"
+ }
+ Frame {
+ msec: 4656
+ hash: "5bb06b4e74532ba5bc8c7bc38bf77d7f"
+ }
+ Frame {
+ msec: 4672
+ hash: "0ad7411316031e22034c14e81ca3a806"
+ }
+ Frame {
+ msec: 4688
+ hash: "dd81d7a9b48c922b4c42cba1b5f2b9d7"
+ }
+ Frame {
+ msec: 4704
+ hash: "32bef6f5005ad94e29ff59165958fbdc"
+ }
+ Frame {
+ msec: 4720
+ hash: "87758dd311f91193bf1e3536c2f58525"
+ }
+ Frame {
+ msec: 4736
+ hash: "015be92a4ff4e735fcc3cbc7a8b9d763"
+ }
+ Frame {
+ msec: 4752
+ hash: "d4c34ed49317c6692d71681fcd9842b6"
+ }
+ Frame {
+ msec: 4768
+ hash: "abaa235bb946a8abaddd52981d632c2d"
+ }
+ Frame {
+ msec: 4784
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4800
+ image: "itemlist.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4832
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4848
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4864
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4880
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4896
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4912
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4928
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4944
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4960
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4976
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 4992
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5008
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5024
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5040
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5056
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5072
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5088
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5104
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5120
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5136
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5152
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5168
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5184
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5200
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5216
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Frame {
+ msec: 5232
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 17; y: 120
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5248
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 19; y: 120
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 21; y: 120
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5264
+ hash: "99f9988040a389576cb6420b5391f768"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 24; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 28; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5280
+ hash: "95b380c9ab6f8db7b822faf023d94546"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 35; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 44; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5296
+ hash: "bb79e53556698c62ec30c75be9f6b7d7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 70; y: 119
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 96; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 96; y: 117
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5312
+ hash: "285cc2f0df1f59f25a0135560ab6edf2"
+ }
+ Frame {
+ msec: 5328
+ hash: "93a731dc6f71b6ff5400bf74c87e6c46"
+ }
+ Frame {
+ msec: 5344
+ hash: "eb555741ab128a50de5a18a454f2e639"
+ }
+ Frame {
+ msec: 5360
+ hash: "5dbe6cf898c1e37fcaacecfcf57b2194"
+ }
+ Frame {
+ msec: 5376
+ hash: "e7795610115593e78bb32f7bcc0ae2eb"
+ }
+ Frame {
+ msec: 5392
+ hash: "20e76f0eb4ec5f691999faf8ad313370"
+ }
+ Frame {
+ msec: 5408
+ hash: "d6a544c622e504c1b931e1a8a1310a6e"
+ }
+ Frame {
+ msec: 5424
+ hash: "e7a3a21feed244c5b1c710a9254c15f0"
+ }
+ Frame {
+ msec: 5440
+ hash: "5a4b1aca24f121d1373646e9d80b86fd"
+ }
+ Frame {
+ msec: 5456
+ hash: "331d2ec7021655c86aa64e47718a1088"
+ }
+ Frame {
+ msec: 5472
+ hash: "92096bc872e7395aa5b75c44646a0b60"
+ }
+ Frame {
+ msec: 5488
+ hash: "0d9aa6cee4d21488cbb5153f8f3ed593"
+ }
+ Frame {
+ msec: 5504
+ hash: "c1b943d43701605563fffffcb75f9fa7"
+ }
+ Frame {
+ msec: 5520
+ hash: "1b680025d5ad1ddd8f8d5f570ba73e71"
+ }
+ Frame {
+ msec: 5536
+ hash: "5539a3b9f60ea747c10ed8328b467cbf"
+ }
+ Frame {
+ msec: 5552
+ hash: "0a1317bcb606cd3488c5b14ee5d96585"
+ }
+ Frame {
+ msec: 5568
+ hash: "8844af68b11db7d92c69804c7371a746"
+ }
+ Frame {
+ msec: 5584
+ hash: "28d7fd127739c6e3b8488651b725c802"
+ }
+ Frame {
+ msec: 5600
+ hash: "0cf1a7d958a96aa2768995dddc5ccc09"
+ }
+ Frame {
+ msec: 5616
+ hash: "64b902fe7ab4d89ef0c7b760974e3488"
+ }
+ Frame {
+ msec: 5632
+ hash: "aba11c597eba550fc1eaddbf554057f6"
+ }
+ Frame {
+ msec: 5648
+ hash: "1bacaa3bb9dc3cac9ffc7491cb4dc1a5"
+ }
+ Frame {
+ msec: 5664
+ hash: "0ba8b582234d9f0c198c0c9e18e1cb02"
+ }
+ Frame {
+ msec: 5680
+ hash: "f66eaf2b5c3529987c0d9d005351ed73"
+ }
+ Frame {
+ msec: 5696
+ hash: "75b0bb720fa4c77da3783b3ff31c2fae"
+ }
+ Frame {
+ msec: 5712
+ hash: "345b235bb7f13409378e5c0c370f2a41"
+ }
+ Frame {
+ msec: 5728
+ hash: "83b7e902dce4e0fdc4ef5d629188c23c"
+ }
+ Frame {
+ msec: 5744
+ hash: "04b9041c6f10969889d92e94785c7e88"
+ }
+ Frame {
+ msec: 5760
+ image: "itemlist.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "4f3a902addc34ecdaf390e2427cc52e7"
+ }
+ Frame {
+ msec: 5792
+ hash: "68d443f16c16821ffc9ca68b17c76034"
+ }
+ Frame {
+ msec: 5808
+ hash: "9d25adc77befa761ee376a9b43595b5e"
+ }
+ Frame {
+ msec: 5824
+ hash: "a68b1bc6c2963ee92c3a45f500667b3b"
+ }
+ Frame {
+ msec: 5840
+ hash: "d5268cd58c222451d48038e715e83802"
+ }
+ Frame {
+ msec: 5856
+ hash: "f37d461541a8ec7a4161b18748de6aea"
+ }
+ Frame {
+ msec: 5872
+ hash: "805319ac7ca842feb3649e92f8b5b72f"
+ }
+ Frame {
+ msec: 5888
+ hash: "73124472a05080891d4948d8ca273f8c"
+ }
+ Frame {
+ msec: 5904
+ hash: "b6e433a23282a50db2e165a2447ba3f6"
+ }
+ Frame {
+ msec: 5920
+ hash: "fd8d3f5688b1806998c6087e18c6c730"
+ }
+ Frame {
+ msec: 5936
+ hash: "f132dd459950ef2d18aa93ca950d0692"
+ }
+ Frame {
+ msec: 5952
+ hash: "ade5beb259b5277c333ca806fc9bdbec"
+ }
+ Frame {
+ msec: 5968
+ hash: "ade5beb259b5277c333ca806fc9bdbec"
+ }
+ Frame {
+ msec: 5984
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6000
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6016
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6032
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6048
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6064
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6080
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6096
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6112
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6128
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6144
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6160
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6176
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6192
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6208
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6224
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6240
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6256
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6272
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6288
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6304
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6320
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6336
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6352
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6368
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6384
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6400
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6416
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6432
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6448
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6464
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6480
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6496
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6512
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6528
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6544
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6560
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6576
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6592
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6608
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6624
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6640
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6656
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6672
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6688
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6704
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6720
+ image: "itemlist.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6752
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6768
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6784
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6800
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6816
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6832
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6848
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6864
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6880
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6896
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6912
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6928
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6944
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6960
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6976
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 6992
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7008
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7024
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7040
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7056
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7072
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7088
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7104
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7120
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7136
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7152
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7168
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7184
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7200
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7216
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7232
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7248
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7264
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7280
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7296
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+ Frame {
+ msec: 7312
+ hash: "bf47cc398a702dd17c8efebb3d2f8073"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/data/listview.0.png b/tests/auto/declarative/visual/ListView/data/listview.0.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.1.png b/tests/auto/declarative/visual/ListView/data/listview.1.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.10.png b/tests/auto/declarative/visual/ListView/data/listview.10.png
new file mode 100644
index 0000000..dcfca3f
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.10.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.11.png b/tests/auto/declarative/visual/ListView/data/listview.11.png
new file mode 100644
index 0000000..7cc4047
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.11.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.12.png b/tests/auto/declarative/visual/ListView/data/listview.12.png
new file mode 100644
index 0000000..a97f4ad
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.12.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.13.png b/tests/auto/declarative/visual/ListView/data/listview.13.png
new file mode 100644
index 0000000..7a8c6bd
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.13.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.14.png b/tests/auto/declarative/visual/ListView/data/listview.14.png
new file mode 100644
index 0000000..ae47356
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.14.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.15.png b/tests/auto/declarative/visual/ListView/data/listview.15.png
new file mode 100644
index 0000000..b3a7260
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.15.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.16.png b/tests/auto/declarative/visual/ListView/data/listview.16.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.16.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.17.png b/tests/auto/declarative/visual/ListView/data/listview.17.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.17.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.18.png b/tests/auto/declarative/visual/ListView/data/listview.18.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.18.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.19.png b/tests/auto/declarative/visual/ListView/data/listview.19.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.19.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.2.png b/tests/auto/declarative/visual/ListView/data/listview.2.png
new file mode 100644
index 0000000..579c68c
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.3.png b/tests/auto/declarative/visual/ListView/data/listview.3.png
new file mode 100644
index 0000000..b3a7260
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.4.png b/tests/auto/declarative/visual/ListView/data/listview.4.png
new file mode 100644
index 0000000..19758b0
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.5.png b/tests/auto/declarative/visual/ListView/data/listview.5.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.6.png b/tests/auto/declarative/visual/ListView/data/listview.6.png
new file mode 100644
index 0000000..82cac48
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.7.png b/tests/auto/declarative/visual/ListView/data/listview.7.png
new file mode 100644
index 0000000..9277a82
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.8.png b/tests/auto/declarative/visual/ListView/data/listview.8.png
new file mode 100644
index 0000000..8c36da7
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.9.png b/tests/auto/declarative/visual/ListView/data/listview.9.png
new file mode 100644
index 0000000..581e824
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.9.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/data/listview.qml b/tests/auto/declarative/visual/ListView/data/listview.qml
new file mode 100644
index 0000000..cd5d7b4
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/data/listview.qml
@@ -0,0 +1,3079 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 32
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 48
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 64
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 80
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 96
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 112
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 128
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 144
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 160
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 176
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 192
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 208
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 224
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 240
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 256
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 272
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 288
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 304
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 320
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 336
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 352
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 368
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 384
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 400
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 416
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 432
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 448
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 464
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 480
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 496
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 512
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 528
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 544
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 560
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 576
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 592
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 608
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 624
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 640
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 656
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 672
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 688
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 704
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 720
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 736
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 752
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 768
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 784
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 800
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 816
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 832
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 848
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 864
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 880
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 896
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 912
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 928
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 944
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 960
+ image: "listview.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 992
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1008
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1024
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1040
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1056
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1072
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1088
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1104
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1120
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1136
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1152
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1168
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1184
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1200
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1216
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1232
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1248
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1264
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1280
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1296
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1312
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1328
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1344
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1360
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1376
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1392
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1408
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1424
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1440
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1456
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1472
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1488
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1504
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1520
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1536
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1552
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1568
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1584
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1600
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1616
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1632
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1648
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1664
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1680
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1696
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1712
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1728
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1744
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1760
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1776
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1792
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1808
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1824
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1840
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1856
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1872
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1888
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1904
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1920
+ image: "listview.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1952
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1968
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 1984
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2000
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2016
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2032
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2048
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2064
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2080
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2096
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2112
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2128
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2144
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2160
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2176
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2192
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2208
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2224
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2240
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2256
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2272
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2288
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2304
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2320
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2336
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2352
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2368
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2384
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2400
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2416
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2432
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2448
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2464
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2480
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2496
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2512
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2528
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2544
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2560
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2576
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2592
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 553; y: 267
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2608
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 2624
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 554; y: 267
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 555; y: 266
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2640
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 556; y: 265
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 558; y: 260
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2656
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 560; y: 256
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2672
+ hash: "c315e184c4dcb11d7e9fd4509a8b6a1f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 562; y: 250
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 566; y: 234
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2688
+ hash: "aeef1cacca9518408519b670443e396f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 568; y: 216
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2704
+ hash: "621626927f83bf7b36b78f5ca7ed4ed0"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 572; y: 192
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 572; y: 192
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2720
+ hash: "b2aca965b745e98365195c52b9dd9a2c"
+ }
+ Frame {
+ msec: 2736
+ hash: "b80cc493e604c42aca2367e26bc9e844"
+ }
+ Frame {
+ msec: 2752
+ hash: "39165ad87fc687e0f165f8a2675173b5"
+ }
+ Frame {
+ msec: 2768
+ hash: "edd1da7c34c3eb7f1f16b782dfa41a13"
+ }
+ Frame {
+ msec: 2784
+ hash: "d31a7915cdb2a7f392e6edc3047a6606"
+ }
+ Frame {
+ msec: 2800
+ hash: "3038dbb3fe3c255adcbecfc106bacb99"
+ }
+ Frame {
+ msec: 2816
+ hash: "454137c508d76f2c38b8007247420b81"
+ }
+ Frame {
+ msec: 2832
+ hash: "16eb385d3ce3b186745974500f855a97"
+ }
+ Frame {
+ msec: 2848
+ hash: "8871fded1fbbdcb0fdfdaa2e6eecc3d1"
+ }
+ Frame {
+ msec: 2864
+ hash: "f49955dab8341e7ca472c3f547cbeaab"
+ }
+ Frame {
+ msec: 2880
+ image: "listview.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "c0ef41c682fa9802c9eb74fd249cfd40"
+ }
+ Frame {
+ msec: 2912
+ hash: "6174fea6ef04fbcefd32d6a0b35a3514"
+ }
+ Frame {
+ msec: 2928
+ hash: "7b2288a8be7b3c465e725aeb5788e91f"
+ }
+ Frame {
+ msec: 2944
+ hash: "b39d8cb650ee00c245b556235843490b"
+ }
+ Frame {
+ msec: 2960
+ hash: "9478ea0bf640924931d627cd8b607eba"
+ }
+ Frame {
+ msec: 2976
+ hash: "39743788f56c6f5c29fa9549e586d1ae"
+ }
+ Frame {
+ msec: 2992
+ hash: "ec8ab3547e10d18e9493b8fae5125591"
+ }
+ Frame {
+ msec: 3008
+ hash: "169b115d03db8c901db4f4c2909a18d3"
+ }
+ Frame {
+ msec: 3024
+ hash: "bf438b17a1e8df6d6bb05474cacd12a7"
+ }
+ Frame {
+ msec: 3040
+ hash: "2aad06334128659e143c4c6c8415a30b"
+ }
+ Frame {
+ msec: 3056
+ hash: "ea0e8d7387b9b54a47bb99c058093462"
+ }
+ Frame {
+ msec: 3072
+ hash: "e483e585399a47490599ca265cf73000"
+ }
+ Frame {
+ msec: 3088
+ hash: "43bed4aac1a2a9b66eafefc117424500"
+ }
+ Frame {
+ msec: 3104
+ hash: "ba5c36add368938f8134a0a88e599c00"
+ }
+ Frame {
+ msec: 3120
+ hash: "c905be5276a871bd1ac392580231c9e4"
+ }
+ Frame {
+ msec: 3136
+ hash: "0c96d9b0119513c1f327f9e6651e89cd"
+ }
+ Frame {
+ msec: 3152
+ hash: "c4ba0836dbb900600f8f4aed42eb1ea1"
+ }
+ Frame {
+ msec: 3168
+ hash: "253d014f89a616032664f29f268cfd85"
+ }
+ Frame {
+ msec: 3184
+ hash: "a5185192d7db7c4a4c8bec6cb5a2a73a"
+ }
+ Frame {
+ msec: 3200
+ hash: "d453cc5b89d3fa00586cc41d5a9a8092"
+ }
+ Frame {
+ msec: 3216
+ hash: "b3c39c0c06643612681b098101458d32"
+ }
+ Frame {
+ msec: 3232
+ hash: "09beec410a0ca7c47fe08991341aea0c"
+ }
+ Frame {
+ msec: 3248
+ hash: "c13c269b384029d04a05fd0170e5909e"
+ }
+ Frame {
+ msec: 3264
+ hash: "cafe360c512ab92804dc1fddae9b8fb6"
+ }
+ Frame {
+ msec: 3280
+ hash: "26dfe538a7edc8f43af1d78e678f3dfa"
+ }
+ Frame {
+ msec: 3296
+ hash: "11e03f6901a4bdbc1eabe72b1ddbee4b"
+ }
+ Frame {
+ msec: 3312
+ hash: "0ea8886b1256649665a1597f62cc633b"
+ }
+ Frame {
+ msec: 3328
+ hash: "013c34be077fb689333df9b04a931b3a"
+ }
+ Frame {
+ msec: 3344
+ hash: "d0e9f1d147e0767c12a89f33b5f2b5b3"
+ }
+ Frame {
+ msec: 3360
+ hash: "9888bf29cd868bad6b2593842413b283"
+ }
+ Frame {
+ msec: 3376
+ hash: "d8ec307a85cecaacaa908ceb34d5db5b"
+ }
+ Frame {
+ msec: 3392
+ hash: "4afe1df3e802b41d1b89b5fab4e35190"
+ }
+ Frame {
+ msec: 3408
+ hash: "e8f484ed8d2a6745ee87ac9544281d55"
+ }
+ Frame {
+ msec: 3424
+ hash: "48eaa0644a27cb3e53c75bd0ce08bf47"
+ }
+ Frame {
+ msec: 3440
+ hash: "f1523d82dfc5c136fbe8746449bb5013"
+ }
+ Frame {
+ msec: 3456
+ hash: "d664786f1a79f851e72aa48ee6736374"
+ }
+ Frame {
+ msec: 3472
+ hash: "e43bb6d0374c8bab67b5fafcaeb2a205"
+ }
+ Frame {
+ msec: 3488
+ hash: "77ef61827c993b16691a023e99cc7f7e"
+ }
+ Frame {
+ msec: 3504
+ hash: "6198e0d242db79e81fb81f621c78a3c9"
+ }
+ Frame {
+ msec: 3520
+ hash: "a66b4773ef05ca78aa12e2c8a151c53a"
+ }
+ Frame {
+ msec: 3536
+ hash: "52fa0b693c3de208e5943521eef5587c"
+ }
+ Frame {
+ msec: 3552
+ hash: "0e237f706f9c2c4c616271f9b9d014e5"
+ }
+ Frame {
+ msec: 3568
+ hash: "14edd1dc2371a9aadaa3c079d325fab6"
+ }
+ Frame {
+ msec: 3584
+ hash: "1fe873b07ee24edaea224939e10830f1"
+ }
+ Frame {
+ msec: 3600
+ hash: "30804b5eb2a6d99116475cbdc1a9c043"
+ }
+ Frame {
+ msec: 3616
+ hash: "c892c17ec947a910b74f5b8704405e9f"
+ }
+ Frame {
+ msec: 3632
+ hash: "696029b77512943001c9eba64191e633"
+ }
+ Frame {
+ msec: 3648
+ hash: "4c26bb0ca28d74a2bb79d0bfc8127361"
+ }
+ Frame {
+ msec: 3664
+ hash: "2d1539db88647d73b9c53cde7c424dd7"
+ }
+ Frame {
+ msec: 3680
+ hash: "fd20e4259b44357c93f22f35c698fe1b"
+ }
+ Frame {
+ msec: 3696
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3712
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3728
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3744
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3760
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3776
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3792
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3808
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3824
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3840
+ image: "listview.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3872
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3888
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3904
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3920
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3936
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3952
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3968
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 3984
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4000
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4016
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4032
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4048
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4064
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4080
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4096
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4112
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4128
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Frame {
+ msec: 4144
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 521; y: 24
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4160
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 25
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4176
+ hash: "5d49efe1383065f0b88f1bfdbbe5e165"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 32
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 37
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4192
+ hash: "a5df688148c264de1d376c9b87ddfa6b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 46
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4208
+ hash: "a4e2c1878b0afce0ee1eebd63e9c951a"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 66
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 88
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4224
+ hash: "2f9a79278d492790ef86a09c77e95ff4"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 531; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 531; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4240
+ hash: "5b5ce7206b26528157c426f4e1e3e0a8"
+ }
+ Frame {
+ msec: 4256
+ hash: "65a1e5f81ab89b163aed46b984cca45e"
+ }
+ Frame {
+ msec: 4272
+ hash: "e28253ad5a2415251b68bcda1d7d4bd0"
+ }
+ Frame {
+ msec: 4288
+ hash: "71aae5abb4a9e9077053ea21dd3ec315"
+ }
+ Frame {
+ msec: 4304
+ hash: "33fcea38fc3b328b3294f9ac2a26aa1a"
+ }
+ Frame {
+ msec: 4320
+ hash: "6299eb1d87f371966307668b92de6a0b"
+ }
+ Frame {
+ msec: 4336
+ hash: "4f66d8c7cb6971d0fc24089d123c547b"
+ }
+ Frame {
+ msec: 4352
+ hash: "d9906d61b31fabf968290ebcd6688f34"
+ }
+ Frame {
+ msec: 4368
+ hash: "5a1945993ff8096ba6b933d45586044a"
+ }
+ Frame {
+ msec: 4384
+ hash: "331535e54da9bbdbc2fbf2b244ad0199"
+ }
+ Frame {
+ msec: 4400
+ hash: "4dc39de0c54f6e0b77f94f6ae6c345ec"
+ }
+ Frame {
+ msec: 4416
+ hash: "ec309a298ce246c13eb666488eb75016"
+ }
+ Frame {
+ msec: 4432
+ hash: "a133819f8adc6265eb0e438261c869e3"
+ }
+ Frame {
+ msec: 4448
+ hash: "da4d64fd6b3ae7d49ee5c5c8d0117a37"
+ }
+ Frame {
+ msec: 4464
+ hash: "620dd1c3fc41ce657eac9d1a5b765fd4"
+ }
+ Frame {
+ msec: 4480
+ hash: "ff1c370bd1bf75a98ae7125e7dd5a9db"
+ }
+ Frame {
+ msec: 4496
+ hash: "59c6e4297109b5cc7c197749867dddae"
+ }
+ Frame {
+ msec: 4512
+ hash: "91b1719e86529d0c35a53a2d0a095dd6"
+ }
+ Frame {
+ msec: 4528
+ hash: "2994663d35c9eb453a27c1a1fa9aeeb8"
+ }
+ Frame {
+ msec: 4544
+ hash: "ae4ec37b9f6a00b3c9139e5cfe13d32e"
+ }
+ Frame {
+ msec: 4560
+ hash: "a98340236d1b65f47e88684168c1429d"
+ }
+ Frame {
+ msec: 4576
+ hash: "34848b483ea6a2bd412e29d26beb3ab0"
+ }
+ Frame {
+ msec: 4592
+ hash: "dd9bae0e2fca84b265d8cb59686ff88d"
+ }
+ Frame {
+ msec: 4608
+ hash: "18b6ef6f5913b0612b76e7b2e25073dd"
+ }
+ Frame {
+ msec: 4624
+ hash: "9398aab9478279aed1bc40c9378f8da4"
+ }
+ Frame {
+ msec: 4640
+ hash: "a297a304c12102f23bd1e0f0207e0df9"
+ }
+ Frame {
+ msec: 4656
+ hash: "091db9138cd6ae801ad857105a83c8f9"
+ }
+ Frame {
+ msec: 4672
+ hash: "253938ca4a4f13433ddd502eb94cb7cd"
+ }
+ Frame {
+ msec: 4688
+ hash: "6002df1793d290e4e31ee0c91c37bbe6"
+ }
+ Frame {
+ msec: 4704
+ hash: "212476fa1c3a52fb8eba03ec3aecdcd8"
+ }
+ Frame {
+ msec: 4720
+ hash: "80d4d8434d4e96a2bc23f5ed060d6ddc"
+ }
+ Frame {
+ msec: 4736
+ hash: "2d4add725f31a04558635ce4b73a758a"
+ }
+ Frame {
+ msec: 4752
+ hash: "57c06022ec1e502c4f49f43063c433e7"
+ }
+ Frame {
+ msec: 4768
+ hash: "8393e97990993f9d5f68ea65f8e4a2db"
+ }
+ Frame {
+ msec: 4784
+ hash: "9a1fcd96dffaf5c79ecc7f9427e02499"
+ }
+ Frame {
+ msec: 4800
+ image: "listview.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "5ae722cf541e3453e73bbee57dc379e9"
+ }
+ Frame {
+ msec: 4832
+ hash: "fc7326c2e2e56d9c3036e8dfc2ea77a8"
+ }
+ Frame {
+ msec: 4848
+ hash: "f22a2a68cea158f333b0457025d75490"
+ }
+ Frame {
+ msec: 4864
+ hash: "d684c8aa9b835779080f170cafead40f"
+ }
+ Frame {
+ msec: 4880
+ hash: "dd451e5e421f929d015981bc7aeb8c66"
+ }
+ Frame {
+ msec: 4896
+ hash: "d066f228295db7f46520495167d3e946"
+ }
+ Frame {
+ msec: 4912
+ hash: "ebf640a457e3498bade3220aafa70331"
+ }
+ Frame {
+ msec: 4928
+ hash: "190f5b1f3ce9d200790c34c50bcc62c5"
+ }
+ Frame {
+ msec: 4944
+ hash: "9d4ad865246eb008afa40740b5c9a208"
+ }
+ Frame {
+ msec: 4960
+ hash: "81c8b2c0b4f9e74f24d328a1d9b40a9f"
+ }
+ Frame {
+ msec: 4976
+ hash: "24acc300307e71bee79bce8de76f56cb"
+ }
+ Frame {
+ msec: 4992
+ hash: "1f9d31f94cfce6f868bfcc8a104d2465"
+ }
+ Frame {
+ msec: 5008
+ hash: "7a3cab008dcb7a893ae30797b33df6f2"
+ }
+ Frame {
+ msec: 5024
+ hash: "38d561a2950434e59513439c7f1120ea"
+ }
+ Frame {
+ msec: 5040
+ hash: "8d34131faa15bc126bd4d9ef3be39ef5"
+ }
+ Frame {
+ msec: 5056
+ hash: "85d57ef15791b56deb537795dd87911e"
+ }
+ Frame {
+ msec: 5072
+ hash: "71e932169915a6c8c2cef0b22febf316"
+ }
+ Frame {
+ msec: 5088
+ hash: "8b3452981963aeebadc9ac2013150263"
+ }
+ Frame {
+ msec: 5104
+ hash: "a3fb8abecfeb48ba1cd1fd8f40896fa0"
+ }
+ Frame {
+ msec: 5120
+ hash: "f53ab533f6a58ae45139f3da4bf8ab4e"
+ }
+ Frame {
+ msec: 5136
+ hash: "9ec7012404f3c1c7795810dcee5acc3b"
+ }
+ Frame {
+ msec: 5152
+ hash: "99ca43bab532dd5d7566e596c65053ce"
+ }
+ Frame {
+ msec: 5168
+ hash: "0af83ad2416821cc230cd2856d1a3e39"
+ }
+ Frame {
+ msec: 5184
+ hash: "86fa23ddf2005bbf35238ae04ae554ac"
+ }
+ Frame {
+ msec: 5200
+ hash: "bb52a748f1d85dde410cfa4f24e3ed20"
+ }
+ Frame {
+ msec: 5216
+ hash: "898b96bc5ee9a3ac61764e5cd9af8cfb"
+ }
+ Frame {
+ msec: 5232
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5248
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5264
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5280
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5296
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5312
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5328
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5344
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5360
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5376
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5392
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5408
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5424
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5440
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5456
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5472
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5488
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5504
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5520
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5536
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5552
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5568
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5584
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5600
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5616
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5632
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5648
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5664
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5680
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5696
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5712
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5728
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5744
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5760
+ image: "listview.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5792
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5808
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5824
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5840
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5856
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5872
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5888
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5904
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5920
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5936
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5952
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Frame {
+ msec: 5968
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 111; y: 230
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 227
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5984
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 223
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6000
+ hash: "3b88645092be28037fca4a6034f5b2f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 216
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 210
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6016
+ hash: "0076b55d3da4ca365688b6a2c984103f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 112; y: 205
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6032
+ hash: "db846ad8e3200ca1fce36a38dc7beab8"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 112; y: 192
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6048
+ hash: "3cb6b25725b4285f9c096d595224c5ca"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 111; y: 180
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6064
+ hash: "1832e12fdf3b464b02b296e727b33694"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 110; y: 173
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6080
+ hash: "6d18d2b5f65cbba4915d0725d24b40f3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 109; y: 158
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 107; y: 140
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6096
+ hash: "79bc7afc6b1aa5f8904b3e6d5d4a9389"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 103; y: 124
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6112
+ hash: "4436f2d15304c839aacec486c1fd6d96"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6128
+ hash: "c3bffc7c95893cf9bbd8596208b7f657"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 105
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 100
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6144
+ hash: "04231c2fdc02729aa34ed4e403dd373b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 96
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6160
+ hash: "392d75c4b372825e78366eb63a618170"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 101; y: 87
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 102; y: 83
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6176
+ hash: "7f91f7bdb0cb62d600ac4aa573681fe3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 102; y: 79
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6192
+ hash: "69207181a382650c5e33145555f0d9ba"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 103; y: 76
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 103; y: 72
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6208
+ hash: "65a184b5c49b02e08114e437483f928d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 104; y: 68
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 105; y: 64
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6224
+ hash: "c22da9ce54d04f51fb55da755753a509"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 105; y: 61
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6240
+ hash: "59dbd5216847a62f60a1d0701a15bb62"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 106; y: 57
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 106; y: 53
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6256
+ hash: "bbfc902db6e6ca253afb1c90306b2a63"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 106; y: 47
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 106; y: 47
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6272
+ hash: "5c41f194afec5f7e3db9d98673d03d5c"
+ }
+ Frame {
+ msec: 6288
+ hash: "5c41f194afec5f7e3db9d98673d03d5c"
+ }
+ Frame {
+ msec: 6304
+ hash: "deb06d0f915d5f6ec39b1820d57b6af6"
+ }
+ Frame {
+ msec: 6320
+ hash: "deb06d0f915d5f6ec39b1820d57b6af6"
+ }
+ Frame {
+ msec: 6336
+ hash: "2a1a1f9239a6ccb308e51796f9b0bb89"
+ }
+ Frame {
+ msec: 6352
+ hash: "3c1b44201616b8271023bf05a3f3f0f7"
+ }
+ Frame {
+ msec: 6368
+ hash: "87afcef49db8b2b547e85e834f8ec304"
+ }
+ Frame {
+ msec: 6384
+ hash: "290081b4b1272ef09ec9964c128e61b5"
+ }
+ Frame {
+ msec: 6400
+ hash: "19bb3b23ee4b14a5f0a313106ef7c8c1"
+ }
+ Frame {
+ msec: 6416
+ hash: "65a184b5c49b02e08114e437483f928d"
+ }
+ Frame {
+ msec: 6432
+ hash: "832d2aefbcaf776f35039be527d367c5"
+ }
+ Frame {
+ msec: 6448
+ hash: "69207181a382650c5e33145555f0d9ba"
+ }
+ Frame {
+ msec: 6464
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6480
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6496
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6512
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6528
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6544
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6560
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6576
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6592
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6608
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6624
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6640
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6656
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6672
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6688
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6704
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6720
+ image: "listview.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6752
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6768
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6784
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6800
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6816
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6832
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6848
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6864
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6880
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6896
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6912
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6928
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6944
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6960
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6976
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 6992
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7008
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7024
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7040
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7056
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7072
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7088
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7104
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7120
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7136
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7152
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7168
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7184
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7200
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7216
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7232
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7248
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7264
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7280
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Frame {
+ msec: 7296
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 519; y: 276
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7312
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 519; y: 275
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7328
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 519; y: 274
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7344
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 273
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 272
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7360
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 271
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7376
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 268
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7392
+ hash: "89fe95733476bd000457e36ee4ecfc73"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 266
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 265
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7408
+ hash: "9047f597b9e59ca652c172338bed6ef9"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 262
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7424
+ hash: "87476f78daecd6bb49e8d6e673d28100"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 260
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7440
+ hash: "6bfd895c6b7d97e4102eb26608cdfeca"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 254
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7456
+ hash: "e4c2b75beaee54a5781a5acbeb37ea64"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 249
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7472
+ hash: "d5e816768e9c3db0631416bd86b1b461"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 243
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7488
+ hash: "22cb512b302afc6c3c9dec1d47b3bf03"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 237
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7504
+ hash: "a7e458e007954bd908cf27a1841d36ea"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 231
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7520
+ hash: "0f9fa53b247f72e9a8ff6201b188b410"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 225
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7536
+ hash: "c986ea3853dd33f7f2b5629f67429423"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 517; y: 219
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7552
+ hash: "114ffaa5cf38e4884a1d477884541b44"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 518; y: 215
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7568
+ hash: "7cdf1bb327484618909ded5411aca4ec"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 519; y: 208
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7584
+ hash: "d4c005194ed510f5d54a811176943dc2"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 520; y: 202
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7600
+ hash: "3103351bc83675c877fb6dcd1a6ddbbc"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 196
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7616
+ hash: "2c13ddda8d89501c9487b83f8b115570"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 189
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7632
+ hash: "476834b6d88077f9983ed358c06bd0c3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 185
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7648
+ hash: "cc2148c6a7ba0bbe6ceea848b7e48621"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 177
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7664
+ hash: "5b8824848dd1de3632b26e04e95b5899"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 169
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7680
+ image: "listview.7.png"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 160
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7696
+ hash: "d0a4a8b631e3494043f261fb8da67938"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 156
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7712
+ hash: "985111215c3959a45b293879af701318"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 147
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7728
+ hash: "ed5917a3fe95777f2efdaa154af0c489"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 144
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7744
+ hash: "6fa9de2983f0e30cb96c035c28757b93"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7760
+ hash: "fd568c7d27618a71b0f0882ca57b685b"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 130
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7776
+ hash: "f5b941f5741a9a78122605576809c395"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 124
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7792
+ hash: "ffc96a85d7dbbed257b69a0c735e21b8"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 122
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7808
+ hash: "cfb6335c5449554e631d6e3106ea8a00"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 116
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7824
+ hash: "ff9786e85ee8af6177ac8e5cc1307462"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 111
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7840
+ hash: "3140b49dfee8e690b5c778044385e107"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 106
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7856
+ hash: "0d899af24685a9998a6b961023286fde"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 104
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7872
+ hash: "99ee1e8803c05e546a721b0c9ee39499"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 101
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7888
+ hash: "96e7da2f895500a786ed36cb295e9003"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 99
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7904
+ hash: "cd369fc5dc31814208e56cf7cd0decea"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 521; y: 97
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7920
+ hash: "5fee72994b65a45b4900a3073f86a3e1"
+ }
+ Frame {
+ msec: 7936
+ hash: "9a2f8a65d842b8f92998e6411f7cd53c"
+ }
+ Frame {
+ msec: 7952
+ hash: "2848d69017ce71ae101ccdfa7c67f933"
+ }
+ Frame {
+ msec: 7968
+ hash: "6568aa88e81f988f65da435df7166167"
+ }
+ Frame {
+ msec: 7984
+ hash: "d5f15ee08a2d7667786757a378a7a7f4"
+ }
+ Frame {
+ msec: 8000
+ hash: "9b566bd02a561b32d1a4c1ec99c2e2c3"
+ }
+ Frame {
+ msec: 8016
+ hash: "580419e1c9e91046547d913f6b8790a4"
+ }
+ Frame {
+ msec: 8032
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8048
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8064
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 521; y: 97
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8080
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8096
+ hash: "a5a3cd610ec0b35af1295ee6c41e09e3"
+ }
+ Frame {
+ msec: 8112
+ hash: "83b91a371d682a501bc3a3fceabe4f8c"
+ }
+ Frame {
+ msec: 8128
+ hash: "798b1dbfa0cce362213f426e2c60ac0e"
+ }
+ Frame {
+ msec: 8144
+ hash: "d71b6a693c430a618c23413cb65bb320"
+ }
+ Frame {
+ msec: 8160
+ hash: "2baae394390da39447a67151bc503d65"
+ }
+ Frame {
+ msec: 8176
+ hash: "06688b05c61a7b862d39534207a8adab"
+ }
+ Frame {
+ msec: 8192
+ hash: "a1d3042e16709817906dcdc673ee52c7"
+ }
+ Frame {
+ msec: 8208
+ hash: "236dd41feac1b1a8a4bd7911bb184da2"
+ }
+ Frame {
+ msec: 8224
+ hash: "f3ec821bba1d32e90bdab0e85c07d7d8"
+ }
+ Frame {
+ msec: 8240
+ hash: "e328c35adf7ffc3d7e3af97e798ec8a5"
+ }
+ Frame {
+ msec: 8256
+ hash: "651101db68fd3ed1dc5f441c126dc31b"
+ }
+ Frame {
+ msec: 8272
+ hash: "651101db68fd3ed1dc5f441c126dc31b"
+ }
+ Frame {
+ msec: 8288
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8304
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8320
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8336
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8352
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8368
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8384
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8400
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8416
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8432
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8448
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8464
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8480
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8496
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8512
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8528
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8544
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8560
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8576
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8592
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8608
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8624
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8640
+ image: "listview.8.png"
+ }
+ Frame {
+ msec: 8656
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8672
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8688
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8704
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8720
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8736
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8752
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8768
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8784
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8800
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8816
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8832
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8848
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8864
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8880
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8896
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8912
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8928
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8944
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8960
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8976
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 8992
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9008
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9024
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9040
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9056
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9072
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9088
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9104
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9120
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9136
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9152
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9168
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9184
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9200
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9216
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9232
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9248
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9264
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9280
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9296
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9312
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9328
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9344
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9360
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9376
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9392
+ hash: "1171be123a361d72859c25434573482c"
+ }
+ Frame {
+ msec: 9408
+ hash: "1171be123a361d72859c25434573482c"
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/itemlist.qml b/tests/auto/declarative/visual/ListView/itemlist.qml
new file mode 100644
index 0000000..8cbbdb0
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/itemlist.qml
@@ -0,0 +1,40 @@
+// This example demonstrates placing items in a view using
+// a VisualItemModel
+
+import Qt 4.6
+
+Rectangle {
+ color: "lightgray"
+ width: 240
+ height: 320
+
+ VisualItemModel {
+ id: itemModel
+ objectName: "itemModel"
+ Rectangle {
+ objectName: "item1"
+ height: view.height; width: view.width; color: "#FFFEF0"
+ }
+ Rectangle {
+ objectName: "item2"
+ height: view.height; width: view.width; color: "#F0FFF7"
+ }
+ Rectangle {
+ objectName: "item3"
+ height: view.height; width: view.width; color: "#F4F0FF"
+ }
+ }
+
+ ListView {
+ id: view
+ objectName: "view"
+ anchors.fill: parent
+ anchors.bottomMargin: 30
+ model: itemModel
+ preferredHighlightBegin: 0
+ preferredHighlightEnd: 0
+ highlightRangeMode: "StrictlyEnforceRange"
+ orientation: ListView.Horizontal
+ flickDeceleration: 2000
+ }
+}
diff --git a/tests/auto/declarative/visual/ListView/listview.qml b/tests/auto/declarative/visual/ListView/listview.qml
new file mode 100644
index 0000000..fb9eecd
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/listview.qml
@@ -0,0 +1,81 @@
+import Qt 4.6
+
+Rectangle {
+ width: 600; height: 300; color: "white"
+
+ ListModel {
+ id: myModel
+ ListElement {
+ itemColor: "red"
+ }
+ ListElement {
+ itemColor: "green"
+ }
+ ListElement {
+ itemColor: "blue"
+ }
+ ListElement {
+ itemColor: "orange"
+ }
+ ListElement {
+ itemColor: "brown"
+ }
+ ListElement {
+ itemColor: "yellow"
+ }
+ ListElement {
+ itemColor: "purple"
+ }
+ ListElement {
+ itemColor: "darkred"
+ }
+ ListElement {
+ itemColor: "darkblue"
+ }
+ }
+
+ Component {
+ id: myDelegate
+ Item {
+ width: 200; height: 50
+ Rectangle {
+ x: 5; y : 5
+ width: 190; height: 40
+ opacity: 0.5
+ color: itemColor
+ }
+ }
+ }
+
+ Component {
+ id: myHighlight
+ Rectangle { color: "black" }
+ }
+
+ ListView {
+ id: list1
+ width: 200; height: parent.height
+ model: myModel; delegate: myDelegate
+ highlight: myHighlight; currentIndex: list3.currentIndex
+ focus: true
+ }
+ ListView {
+ id: list2
+ x: 200; width: 200; height: parent.height
+ model: myModel; delegate: myDelegate; highlight: myHighlight
+ preferredHighlightBegin: 80
+ preferredHighlightEnd: 220
+ highlightRangeMode: "ApplyRange"
+ currentIndex: list1.currentIndex
+ }
+ ListView {
+ id: list3
+ x: 400; width: 200; height: parent.height
+ model: myModel; delegate: myDelegate; highlight: myHighlight
+ currentIndex: list1.currentIndex
+ preferredHighlightBegin: 125
+ preferredHighlightEnd: 125
+ highlightRangeMode: "StrictlyEnforceRange"
+ flickDeceleration: 1000
+ }
+}
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.0.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.0.png
new file mode 100644
index 0000000..c59b816
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.1.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.1.png
new file mode 100644
index 0000000..d4dbc70
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.10.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.10.png
new file mode 100644
index 0000000..ed9d345
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.10.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.11.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.11.png
new file mode 100644
index 0000000..ed9d345
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.11.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.12.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.12.png
new file mode 100644
index 0000000..45ee400
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.12.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.13.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.13.png
new file mode 100644
index 0000000..c73e158
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.13.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.14.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.14.png
new file mode 100644
index 0000000..e2fff6d
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.14.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.15.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.15.png
new file mode 100644
index 0000000..d7a13df
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.15.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.16.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.16.png
new file mode 100644
index 0000000..beb3094
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.16.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.17.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.17.png
new file mode 100644
index 0000000..beb3094
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.17.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.18.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.18.png
new file mode 100644
index 0000000..beb3094
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.18.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.19.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.19.png
new file mode 100644
index 0000000..d3a2650
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.19.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.2.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.2.png
new file mode 100644
index 0000000..a09dd28
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.20.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.20.png
new file mode 100644
index 0000000..600462a
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.20.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.21.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.21.png
new file mode 100644
index 0000000..6defca0
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.21.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.22.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.22.png
new file mode 100644
index 0000000..91967e1
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.22.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.3.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.3.png
new file mode 100644
index 0000000..d099a79
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.4.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.4.png
new file mode 100644
index 0000000..385efc8
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.5.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.5.png
new file mode 100644
index 0000000..25a7c3c
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.6.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.6.png
new file mode 100644
index 0000000..25a7c3c
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.7.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.7.png
new file mode 100644
index 0000000..7a24f51
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.8.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.8.png
new file mode 100644
index 0000000..7a24f51
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.9.png b/tests/auto/declarative/visual/Package_Views/data/packageviews.9.png
new file mode 100644
index 0000000..45ee400
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.9.png
Binary files differ
diff --git a/tests/auto/declarative/visual/Package_Views/data/packageviews.qml b/tests/auto/declarative/visual/Package_Views/data/packageviews.qml
new file mode 100644
index 0000000..d062667
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/data/packageviews.qml
@@ -0,0 +1,3751 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 32
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 48
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 64
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 80
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 96
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 112
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 128
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 144
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 160
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 176
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 192
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 208
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 224
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 240
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 256
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 272
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 288
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 304
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 320
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 336
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 352
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 368
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 384
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 400
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 416
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 432
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 448
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 464
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 480
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 496
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 512
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 528
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 544
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 560
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 576
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 592
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 608
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 624
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 640
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 656
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 672
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 688
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 704
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 720
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 736
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 752
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 768
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 784
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 800
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 816
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 832
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 848
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 864
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 880
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 896
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 912
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 928
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 944
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 960
+ image: "packageviews.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 992
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1008
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1024
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1040
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1056
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1072
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1088
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1104
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1120
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1136
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1152
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1168
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1184
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1200
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1216
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1232
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1248
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1264
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1280
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1296
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1312
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1328
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1344
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1360
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Frame {
+ msec: 1376
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 57; y: 164
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1392
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 57; y: 162
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1408
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 57; y: 159
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 57; y: 156
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1424
+ hash: "a327426c93b523526f993b5271ab4501"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 56; y: 152
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 56; y: 147
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1440
+ hash: "87b7cacfb2d9e8ad916e331b2cf1f13e"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 55; y: 141
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 54; y: 133
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1456
+ hash: "34290c1435c1a96d08152479d2d1334e"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 54; y: 126
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 54; y: 126
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1472
+ hash: "ef5fb09ec8fb4b0d97c864618d6f6231"
+ }
+ Frame {
+ msec: 1488
+ hash: "d5b4c2e1d4b0bc877c99739a67b4a4fb"
+ }
+ Frame {
+ msec: 1504
+ hash: "a3623a3f253590d51ee03b6849e88edb"
+ }
+ Frame {
+ msec: 1520
+ hash: "4c1115f1041629b7c37cf4ae001fd7d3"
+ }
+ Frame {
+ msec: 1536
+ hash: "845bb3d1f52bee4a469fb12d6875a323"
+ }
+ Frame {
+ msec: 1552
+ hash: "eb08b5a671149005dbafc8507bb78b18"
+ }
+ Frame {
+ msec: 1568
+ hash: "16744a5b90b29954faf0710010ac6369"
+ }
+ Frame {
+ msec: 1584
+ hash: "322bbe367fbbf0bf07f9153da652a5fc"
+ }
+ Frame {
+ msec: 1600
+ hash: "257769f7c3e24bb2d0cd674dfbe42913"
+ }
+ Frame {
+ msec: 1616
+ hash: "8e299cbcaeae4d53d0fc05e03d36e0d9"
+ }
+ Frame {
+ msec: 1632
+ hash: "f3fb7f30336045abb4557247aab5bde1"
+ }
+ Frame {
+ msec: 1648
+ hash: "468400fb4e9bfa454ea00f19aa5d77b5"
+ }
+ Frame {
+ msec: 1664
+ hash: "429cc820ada7a515b2cb71f133320949"
+ }
+ Frame {
+ msec: 1680
+ hash: "721ec7594d8f815e5648eb8d570d1179"
+ }
+ Frame {
+ msec: 1696
+ hash: "9bc4105a0456c36738c435323e690db1"
+ }
+ Frame {
+ msec: 1712
+ hash: "e54a84718dbdc45dd814089051772585"
+ }
+ Frame {
+ msec: 1728
+ hash: "2c969450ede6b6ea7e0e68ee54d02aaa"
+ }
+ Frame {
+ msec: 1744
+ hash: "c2015dd1d4bd223a7fe1df03027af2f3"
+ }
+ Frame {
+ msec: 1760
+ hash: "74108fedfb0967adea181893834bcd9b"
+ }
+ Frame {
+ msec: 1776
+ hash: "b04a22f1cfde6ede57117992cd97dc1c"
+ }
+ Frame {
+ msec: 1792
+ hash: "271d71cb03dd38100812466a973b79ef"
+ }
+ Frame {
+ msec: 1808
+ hash: "130709eecd8eca395085020a83e7553a"
+ }
+ Frame {
+ msec: 1824
+ hash: "a0e5e187ed5245fd766803d266195e6b"
+ }
+ Frame {
+ msec: 1840
+ hash: "d29c145f3ba39a7c2c6ac54b27f9cea1"
+ }
+ Frame {
+ msec: 1856
+ hash: "6e41349b4adb6e37a2f9f2482c0aa5b1"
+ }
+ Frame {
+ msec: 1872
+ hash: "c02c52d3c87c6befb65f3bf392981cd5"
+ }
+ Frame {
+ msec: 1888
+ hash: "ec48d113c8468bd1e1b465e248eecaee"
+ }
+ Frame {
+ msec: 1904
+ hash: "a2c9b917d1f0cff0e088d3b624d9eeb8"
+ }
+ Frame {
+ msec: 1920
+ image: "packageviews.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "c4d4f8a351316b4a33f42f5fb030f304"
+ }
+ Frame {
+ msec: 1952
+ hash: "1baee6be1da687309d84a992e430c915"
+ }
+ Frame {
+ msec: 1968
+ hash: "4245f02817f7a674c34c581cbd9e1181"
+ }
+ Frame {
+ msec: 1984
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2000
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2016
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2032
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2048
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2064
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2080
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2096
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2112
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2128
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2144
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2160
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2176
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2192
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2208
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2224
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2240
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2256
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2272
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2288
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 70; y: 89
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2304
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2320
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2336
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2352
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 70; y: 89
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2368
+ hash: "2fa6bb20f29467713c94886c6fffe5e3"
+ }
+ Frame {
+ msec: 2384
+ hash: "3b9a75225adddb01e92286463e15bf98"
+ }
+ Frame {
+ msec: 2400
+ hash: "32f99602756898b4ec607d4124b5120f"
+ }
+ Frame {
+ msec: 2416
+ hash: "60007f14752d2d87ba6e335ad596f1ad"
+ }
+ Frame {
+ msec: 2432
+ hash: "dcfad2407f53f83964fa7be762a137bd"
+ }
+ Frame {
+ msec: 2448
+ hash: "fcc1a30a33bec046868734014132eb70"
+ }
+ Frame {
+ msec: 2464
+ hash: "f60592829a2765b3cd3a0cecb9c45426"
+ }
+ Frame {
+ msec: 2480
+ hash: "a0e26063acd1b53b5eeeb31187f38336"
+ }
+ Frame {
+ msec: 2496
+ hash: "d7f3e776038bd479db292bcba3a65fc7"
+ }
+ Frame {
+ msec: 2512
+ hash: "4af31954235ab8a7cf8462eaa64d7dda"
+ }
+ Frame {
+ msec: 2528
+ hash: "aff3f287c07f546e0d3e9e68731d82fe"
+ }
+ Frame {
+ msec: 2544
+ hash: "75fbc4e26466e8a1f66503addfcbb525"
+ }
+ Frame {
+ msec: 2560
+ hash: "cb4c91f725ec46dd066475efc2bc2d65"
+ }
+ Frame {
+ msec: 2576
+ hash: "106434203ccc2fd8246c56520095a473"
+ }
+ Frame {
+ msec: 2592
+ hash: "129ced0e7fc406e81b1ced72397adc5c"
+ }
+ Frame {
+ msec: 2608
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2624
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2640
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2656
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2672
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2688
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2704
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2720
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2736
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2752
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2768
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2784
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2800
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2816
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2832
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2848
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2864
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2880
+ image: "packageviews.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2912
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2928
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2944
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2960
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2976
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 2992
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3008
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3024
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3040
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3056
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3072
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3088
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3104
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3120
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3136
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3152
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3168
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3184
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3200
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3216
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3232
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3248
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3264
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3280
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3296
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3312
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3328
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3344
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3360
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3376
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3392
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 49; y: 162
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3408
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Frame {
+ msec: 3424
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 49; y: 161
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3440
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 49; y: 159
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 48; y: 157
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3456
+ hash: "49903693b112d5f35c4e877bef6bbdb0"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 48; y: 153
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 48; y: 149
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3472
+ hash: "1c84452b0ce90ae6f136f5bcce408220"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 50; y: 144
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 50; y: 138
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 50; y: 138
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3488
+ hash: "4c77d402b995297dadb5e671f071605f"
+ }
+ Frame {
+ msec: 3504
+ hash: "babd28626a81bd48b39b56f8da69c360"
+ }
+ Frame {
+ msec: 3520
+ hash: "71654a76f9b94fafaf3767003598fb96"
+ }
+ Frame {
+ msec: 3536
+ hash: "87ad69a660e072e71f940db93be3a949"
+ }
+ Frame {
+ msec: 3552
+ hash: "147f7f3f1913bc5ac5889c1a4daa8026"
+ }
+ Frame {
+ msec: 3568
+ hash: "9c26b3ad7a5dacd56028afa7bf4deef6"
+ }
+ Frame {
+ msec: 3584
+ hash: "18611ff90e5af36c9b6396c3df4cd646"
+ }
+ Frame {
+ msec: 3600
+ hash: "84701fd73ed8e1951bd4c806b70654ac"
+ }
+ Frame {
+ msec: 3616
+ hash: "42b40f1683beb23f4fe5ade066c0626f"
+ }
+ Frame {
+ msec: 3632
+ hash: "8c6aeefaa6f36cdffcf7bdb1597c6fbe"
+ }
+ Frame {
+ msec: 3648
+ hash: "731cea2e0d8fb8aac6ae919b23b89b87"
+ }
+ Frame {
+ msec: 3664
+ hash: "d4dc70a8e09e7ec03e7c1f5123b7abef"
+ }
+ Frame {
+ msec: 3680
+ hash: "5246e2f52aa104e8030eef105a5b5a7c"
+ }
+ Frame {
+ msec: 3696
+ hash: "a9c3d0034c09ba81d19d57ff550d7b4f"
+ }
+ Frame {
+ msec: 3712
+ hash: "e9092b1be19273f1f29912cd493dd238"
+ }
+ Frame {
+ msec: 3728
+ hash: "c2b19c7b818c94e932558676a026f049"
+ }
+ Frame {
+ msec: 3744
+ hash: "6627c4d6daab8e6500dbd0d921bc1ebd"
+ }
+ Frame {
+ msec: 3760
+ hash: "45c584ca18e8bfd6aa495c16a977662a"
+ }
+ Frame {
+ msec: 3776
+ hash: "de79039a8bb623f7d48afe1549ae23e0"
+ }
+ Frame {
+ msec: 3792
+ hash: "076d29278466038071095093266553f5"
+ }
+ Frame {
+ msec: 3808
+ hash: "73ed162dc5f9983bf22446f63691f7e4"
+ }
+ Frame {
+ msec: 3824
+ hash: "4cc3648635884a69191f0cfe2051f621"
+ }
+ Frame {
+ msec: 3840
+ image: "packageviews.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3872
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3888
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3904
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3920
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3936
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3952
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3968
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 3984
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4000
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4016
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4032
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4048
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4064
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4080
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4096
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4112
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4128
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4144
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4160
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4176
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4192
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4208
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4224
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4240
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4256
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4272
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4288
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4304
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4320
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4336
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4352
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Frame {
+ msec: 4368
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 151; y: 170
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 151; y: 168
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4384
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 152; y: 166
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 153; y: 163
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4400
+ hash: "d06fbe4c7dd8bd392172aa5b29c6ceee"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 154; y: 160
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 155; y: 154
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4416
+ hash: "ac75b9adaecd10206c4daa07c93adb27"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 155; y: 148
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 156; y: 141
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4432
+ hash: "539ec244fd42801cfcf97adc12f48786"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 160; y: 121
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4448
+ hash: "7d7bc6f7d2ff1da352ddab0d679906e7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 162; y: 101
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 166; y: 83
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 166; y: 83
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4464
+ hash: "4b508eb55971a03c6dc8a50d0244fa21"
+ }
+ Frame {
+ msec: 4480
+ hash: "2ceb497ca10e6448a019b62a225a72e4"
+ }
+ Frame {
+ msec: 4496
+ hash: "1fd9b89ebcb8e707c9b1b13ba64061b4"
+ }
+ Frame {
+ msec: 4512
+ hash: "24a3a48843860f643e55ca6dfec84f98"
+ }
+ Frame {
+ msec: 4528
+ hash: "48ea9398101f44a707c44ee1c5102d0c"
+ }
+ Frame {
+ msec: 4544
+ hash: "d8f2cebcdb542e75bbbaa4391ca881b8"
+ }
+ Frame {
+ msec: 4560
+ hash: "df35827ac111c67588922aadd45b3c85"
+ }
+ Frame {
+ msec: 4576
+ hash: "c1e612548c8d5c2f844e94ad4c0f1db4"
+ }
+ Frame {
+ msec: 4592
+ hash: "c298bccebeb1f4528c935e5fd256479c"
+ }
+ Frame {
+ msec: 4608
+ hash: "4c01d969eba4eca32b8a3b7f6f9c99f0"
+ }
+ Frame {
+ msec: 4624
+ hash: "66c783ae698cb91195088591a9bd67c1"
+ }
+ Frame {
+ msec: 4640
+ hash: "5419f6889162fb0db6b8c9e521f57f4f"
+ }
+ Frame {
+ msec: 4656
+ hash: "d153dbf30acf36145d7fcb8e37dd5c6d"
+ }
+ Frame {
+ msec: 4672
+ hash: "ffbf186683dc979ef29cdd5ff50296fc"
+ }
+ Frame {
+ msec: 4688
+ hash: "ddcedde95d1ebcafe5b73924ecfa047a"
+ }
+ Frame {
+ msec: 4704
+ hash: "d94b9e92f2c1a5e0ea2f8dd21a905517"
+ }
+ Frame {
+ msec: 4720
+ hash: "92c27d497128ccdcbfe8224a0f55a302"
+ }
+ Frame {
+ msec: 4736
+ hash: "7146017581b03e6551822653e54d5001"
+ }
+ Frame {
+ msec: 4752
+ hash: "a39567e01b8963d3b71f5f525d1582d4"
+ }
+ Frame {
+ msec: 4768
+ hash: "842654ef5a24143e41412b2450b6024c"
+ }
+ Frame {
+ msec: 4784
+ hash: "c2a002588b4b3f89806d6d283c39ea54"
+ }
+ Frame {
+ msec: 4800
+ image: "packageviews.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "2bea5cc22ea4989f8f07fbf62d09880b"
+ }
+ Frame {
+ msec: 4832
+ hash: "b8326b959b75b05c050ff91f0c34fa55"
+ }
+ Frame {
+ msec: 4848
+ hash: "d5f2e63bd18b2067221ec80764c7500d"
+ }
+ Frame {
+ msec: 4864
+ hash: "157f93ebaa95664965539237ba121265"
+ }
+ Frame {
+ msec: 4880
+ hash: "5bda47a6295e500f24b6ba7bf04e9282"
+ }
+ Frame {
+ msec: 4896
+ hash: "0134d543cfbf085eb4b5ea4a0f5ae32f"
+ }
+ Frame {
+ msec: 4912
+ hash: "d27f2ad3bd9817c23caf01ba64335776"
+ }
+ Frame {
+ msec: 4928
+ hash: "4dd96288601f4481a24b75afedd34599"
+ }
+ Frame {
+ msec: 4944
+ hash: "d5ebfbd190fe2482af54004ad9434818"
+ }
+ Frame {
+ msec: 4960
+ hash: "6a8c5c64228b3be521407e00c2b6a1de"
+ }
+ Frame {
+ msec: 4976
+ hash: "645219e7aa6761bef1b11ac8f17f1f42"
+ }
+ Frame {
+ msec: 4992
+ hash: "54fff3170fa43d99eca2c87381ecaf1e"
+ }
+ Frame {
+ msec: 5008
+ hash: "54fff3170fa43d99eca2c87381ecaf1e"
+ }
+ Frame {
+ msec: 5024
+ hash: "00c3c11b9b266504b8cdbdf4edcc3a98"
+ }
+ Frame {
+ msec: 5040
+ hash: "00c3c11b9b266504b8cdbdf4edcc3a98"
+ }
+ Frame {
+ msec: 5056
+ hash: "00c3c11b9b266504b8cdbdf4edcc3a98"
+ }
+ Frame {
+ msec: 5072
+ hash: "54fff3170fa43d99eca2c87381ecaf1e"
+ }
+ Frame {
+ msec: 5088
+ hash: "6a8c5c64228b3be521407e00c2b6a1de"
+ }
+ Frame {
+ msec: 5104
+ hash: "f91cea801322d1bc6ac1b9eeae96c704"
+ }
+ Frame {
+ msec: 5120
+ hash: "d27f2ad3bd9817c23caf01ba64335776"
+ }
+ Frame {
+ msec: 5136
+ hash: "5bda47a6295e500f24b6ba7bf04e9282"
+ }
+ Frame {
+ msec: 5152
+ hash: "d5f2e63bd18b2067221ec80764c7500d"
+ }
+ Frame {
+ msec: 5168
+ hash: "b10145c10c2bc9d01ec6a49a399f728e"
+ }
+ Frame {
+ msec: 5184
+ hash: "f0b759a49bf21b0c9b311a1dd02d7807"
+ }
+ Frame {
+ msec: 5200
+ hash: "1c5546c3ddbde95d10921c8c32fd2d67"
+ }
+ Frame {
+ msec: 5216
+ hash: "c2a002588b4b3f89806d6d283c39ea54"
+ }
+ Frame {
+ msec: 5232
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5248
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5264
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5280
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5296
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5312
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5328
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5344
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5360
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5376
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5392
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5408
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5424
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5440
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5456
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5472
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5488
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5504
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5520
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5536
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5552
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5568
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5584
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5600
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5616
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5632
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5648
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5664
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5680
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5696
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5712
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5728
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5744
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5760
+ image: "packageviews.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5792
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5808
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5824
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5840
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5856
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5872
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5888
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5904
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5920
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5936
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5952
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5968
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 5984
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6000
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6016
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6032
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6048
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6064
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6080
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6096
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6112
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6128
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6144
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6160
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6176
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6192
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6208
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6224
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6240
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6256
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6272
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6288
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6304
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6320
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6336
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6352
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6368
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6384
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6400
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6416
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6432
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6448
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6464
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6480
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6496
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6512
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 177; y: 168
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6528
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6544
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6560
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6576
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 178; y: 168
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6592
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 178; y: 168
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 6608
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6624
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6640
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6656
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6672
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6688
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6704
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6720
+ image: "packageviews.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6752
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6768
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6784
+ hash: "1eb5d2140ff3c71d55a6e5338dd2853e"
+ }
+ Frame {
+ msec: 6800
+ hash: "f6de07972a225d276b4b5c424dc490ef"
+ }
+ Frame {
+ msec: 6816
+ hash: "d8c400ca33d590a9b4d9b179b5634d94"
+ }
+ Frame {
+ msec: 6832
+ hash: "21ec87c22e52b3daa78bd94b771a105c"
+ }
+ Frame {
+ msec: 6848
+ hash: "19a3667f4051e40e944ec58abb16846a"
+ }
+ Frame {
+ msec: 6864
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6880
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6896
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6912
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6928
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6944
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6960
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6976
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 6992
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7008
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7024
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7040
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7056
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7072
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7088
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7104
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7120
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7136
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7152
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7168
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7184
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7200
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7216
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7232
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7248
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7264
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7280
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7296
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7312
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7328
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7344
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7360
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7376
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7392
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7408
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 157; y: 37
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7424
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Frame {
+ msec: 7440
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 157; y: 39
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7456
+ hash: "08369a783b1f1f4e64da7dab40df6ef3"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 157; y: 44
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 157; y: 51
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7472
+ hash: "e8ad02d4c2429a03ff0686888e4038bf"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 157; y: 59
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 158; y: 67
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7488
+ hash: "43dcc86aeff3b8b74ae1b87e735e8963"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 158; y: 87
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 158; y: 96
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7504
+ hash: "96e10ce9e5a80caf626213e5c696d84d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 160; y: 116
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7520
+ hash: "3b34cb99481d5418136840afd649807d"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 164; y: 134
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 164; y: 134
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7536
+ hash: "494cf05eb3d8eb221d0e3c233c936e87"
+ }
+ Frame {
+ msec: 7552
+ hash: "e0d5f3aab9fbfac1de47f42202dbeb79"
+ }
+ Frame {
+ msec: 7568
+ hash: "8cd6919e15ea4320e00e79d43596ea80"
+ }
+ Frame {
+ msec: 7584
+ hash: "395a63aa12928a6b597eabd74f019a03"
+ }
+ Frame {
+ msec: 7600
+ hash: "16d4ccbda396a9afcaeac4ddca733012"
+ }
+ Frame {
+ msec: 7616
+ hash: "71955518b68a9817a41d5d0f63adcc57"
+ }
+ Frame {
+ msec: 7632
+ hash: "152f2569fe8849d5c4289699dba2ee32"
+ }
+ Frame {
+ msec: 7648
+ hash: "a1de2cb5acc31a9d73e005c3a44cee4f"
+ }
+ Frame {
+ msec: 7664
+ hash: "96ceaad68263b5165a65f557ae19d9cd"
+ }
+ Frame {
+ msec: 7680
+ image: "packageviews.7.png"
+ }
+ Frame {
+ msec: 7696
+ hash: "9ff5d2774820dac56655a44d965c7742"
+ }
+ Frame {
+ msec: 7712
+ hash: "79cdbfb2f93a35680eab38f0df2eaf66"
+ }
+ Frame {
+ msec: 7728
+ hash: "19896d510a27871fc589579e27adc0dc"
+ }
+ Frame {
+ msec: 7744
+ hash: "71b62e488897345eebf8d9640d50585f"
+ }
+ Frame {
+ msec: 7760
+ hash: "4853b95a3f1ae0ebbd468dff3605d595"
+ }
+ Frame {
+ msec: 7776
+ hash: "a8030aa0aede17d91758af08256cf39d"
+ }
+ Frame {
+ msec: 7792
+ hash: "a2a5e71349060ae262d337d9aa33b549"
+ }
+ Frame {
+ msec: 7808
+ hash: "7b5f32f0e53ab102ef6f1eca7da016dd"
+ }
+ Frame {
+ msec: 7824
+ hash: "7b5f32f0e53ab102ef6f1eca7da016dd"
+ }
+ Frame {
+ msec: 7840
+ hash: "25908df38057c7394135108d9618e28d"
+ }
+ Frame {
+ msec: 7856
+ hash: "d3b3ab6e43eef22ca71fc35c36b1f50d"
+ }
+ Frame {
+ msec: 7872
+ hash: "c25759db4e12acbe8e4701c7c86d1957"
+ }
+ Frame {
+ msec: 7888
+ hash: "fe67a155ead8495d646fa7bbcf5db6b4"
+ }
+ Frame {
+ msec: 7904
+ hash: "34e2877a8b84e53e5c85fb1b25d57e2b"
+ }
+ Frame {
+ msec: 7920
+ hash: "2fc6c5a0e9bb80e3c8f12553e7e96d02"
+ }
+ Frame {
+ msec: 7936
+ hash: "b5122a2530e21a01e93862bd8060e320"
+ }
+ Frame {
+ msec: 7952
+ hash: "9c55e0c920bcf5189fb24e1765d221db"
+ }
+ Frame {
+ msec: 7968
+ hash: "1106703562135e36ae62130200960fc8"
+ }
+ Frame {
+ msec: 7984
+ hash: "c24b57dbf01d2646fbbeb3e66636e220"
+ }
+ Frame {
+ msec: 8000
+ hash: "71663a05c04bb77c2e25299a9c6dd9ce"
+ }
+ Frame {
+ msec: 8016
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8032
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8048
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8064
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8080
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8096
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8112
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8128
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8144
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8160
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8176
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8192
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8208
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8224
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8240
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8256
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8272
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8288
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8304
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8320
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8336
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8352
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8368
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8384
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8400
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8416
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8432
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8448
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8464
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8480
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8496
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8512
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8528
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8544
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8560
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8576
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8592
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8608
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8624
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8640
+ image: "packageviews.8.png"
+ }
+ Frame {
+ msec: 8656
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8672
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8688
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Frame {
+ msec: 8704
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 46; y: 147
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8720
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 146
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8736
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 145
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 143
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8752
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 141
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8768
+ hash: "dd6caf22c0cacf5c34686785072da5f7"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 138
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 134
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 46; y: 129
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8784
+ hash: "7b1354e70befc84c343145987c81562f"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 45; y: 122
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8800
+ hash: "6107f00c6472d877b5c109dd58d73145"
+ }
+ Mouse {
+ type: 5
+ button: 0
+ buttons: 1
+ x: 45; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 45; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8816
+ hash: "47288701643899e26b53d28595d59b29"
+ }
+ Frame {
+ msec: 8832
+ hash: "a3b4b613d19c8f21ec1b75c1c660ed1d"
+ }
+ Frame {
+ msec: 8848
+ hash: "7a5d9fe471eb673f68b77d97f9108bac"
+ }
+ Frame {
+ msec: 8864
+ hash: "20a09795ffcf05276d7a5be24b33e207"
+ }
+ Frame {
+ msec: 8880
+ hash: "225e529ac77f225fc8b84ed71cdcd70f"
+ }
+ Frame {
+ msec: 8896
+ hash: "e4188406a3d3d1f1b83547d362a187f8"
+ }
+ Frame {
+ msec: 8912
+ hash: "82707040aad297885ba1c8c6672dc017"
+ }
+ Frame {
+ msec: 8928
+ hash: "a369118e98e2bd67dc4242c5e8c86cb8"
+ }
+ Frame {
+ msec: 8944
+ hash: "001ef50f7d2b7db7e0db8d2190137d0c"
+ }
+ Frame {
+ msec: 8960
+ hash: "2db473b2bd9fd602ed0298501752dae9"
+ }
+ Frame {
+ msec: 8976
+ hash: "f9cdbb4e515abf23721627e3f2748960"
+ }
+ Frame {
+ msec: 8992
+ hash: "cbc072c5b117ce156a4d6661ae488a77"
+ }
+ Frame {
+ msec: 9008
+ hash: "79acb38cec803e6ebeb570dc4d7bbb30"
+ }
+ Frame {
+ msec: 9024
+ hash: "848014437545fc8d2e454a774586a8ca"
+ }
+ Frame {
+ msec: 9040
+ hash: "0836f3a48355f6384c6b3f452df1e7d6"
+ }
+ Frame {
+ msec: 9056
+ hash: "b3da223cdf138e915fcb424cf9181d6b"
+ }
+ Frame {
+ msec: 9072
+ hash: "1a7cf7e7ddaac64eeff0d23997580b8c"
+ }
+ Frame {
+ msec: 9088
+ hash: "cfbd055b2f905db503250b49120948db"
+ }
+ Frame {
+ msec: 9104
+ hash: "c5b8a4ce51ec806f0ce654a8977fb17d"
+ }
+ Frame {
+ msec: 9120
+ hash: "d09ba0ea9e7fed2f50d6463ac74da470"
+ }
+ Frame {
+ msec: 9136
+ hash: "47ec5bab098fd88ef5be3703c316717a"
+ }
+ Frame {
+ msec: 9152
+ hash: "3ea8c442ed43bd3a2aebc9cc2aacfc01"
+ }
+ Frame {
+ msec: 9168
+ hash: "f016f14b0b21781924ac2afe146b1b97"
+ }
+ Frame {
+ msec: 9184
+ hash: "7b7b6954cce0ca202585310520bbb3e3"
+ }
+ Frame {
+ msec: 9200
+ hash: "b0de94ee3b0ce4845101606d2d512426"
+ }
+ Frame {
+ msec: 9216
+ hash: "8dc56bcb2313bd8dd9ef0cbc098b80e5"
+ }
+ Frame {
+ msec: 9232
+ hash: "a1692b26fb73ade5a05e03de3f4a8dbe"
+ }
+ Frame {
+ msec: 9248
+ hash: "672dd46e629475d823b182104f15aa24"
+ }
+ Frame {
+ msec: 9264
+ hash: "2859e53d63c20af7891efc99d5e515b5"
+ }
+ Frame {
+ msec: 9280
+ hash: "b44b1c4eaa33fbd09c8e59c1bf2a8f2a"
+ }
+ Frame {
+ msec: 9296
+ hash: "d520fa81032ca25ec2cb6c358488049d"
+ }
+ Frame {
+ msec: 9312
+ hash: "3676c00bd5c3e9af8c4092afd80f58c2"
+ }
+ Frame {
+ msec: 9328
+ hash: "6be4d4c35aba5a8d32a28dd88f32acd1"
+ }
+ Frame {
+ msec: 9344
+ hash: "375473d4d838ef937c3164e7451d9391"
+ }
+ Frame {
+ msec: 9360
+ hash: "610253e766974af4958c3623547deebd"
+ }
+ Frame {
+ msec: 9376
+ hash: "20b79be381a95930c924240815cc63f4"
+ }
+ Frame {
+ msec: 9392
+ hash: "88130d7132f472ff8495d640adf290cc"
+ }
+ Frame {
+ msec: 9408
+ hash: "2e81f4c9a0221708146adcb508eb2d30"
+ }
+ Frame {
+ msec: 9424
+ hash: "977f52ed922ba5db66440f115f7484a2"
+ }
+ Frame {
+ msec: 9440
+ hash: "706f99c32d00be14ae67b4866fee0cd9"
+ }
+ Frame {
+ msec: 9456
+ hash: "210231604091497b510c4a1d42295574"
+ }
+ Frame {
+ msec: 9472
+ hash: "210231604091497b510c4a1d42295574"
+ }
+ Frame {
+ msec: 9488
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9504
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9520
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9536
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9552
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9568
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9584
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9600
+ image: "packageviews.9.png"
+ }
+ Frame {
+ msec: 9616
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9632
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9648
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9664
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9680
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9696
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9712
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9728
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9744
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9760
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9776
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9792
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9808
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9824
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9840
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9856
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9872
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9888
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9904
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9920
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9936
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9952
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9968
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 9984
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10000
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10016
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10032
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10048
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10064
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10080
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10096
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10112
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10128
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10144
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10160
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10176
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 48; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 10192
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10208
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10224
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10240
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10256
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 48; y: 137
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 10272
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 10288
+ hash: "c54f97c72088b6319efba3c79bbef0fa"
+ }
+ Frame {
+ msec: 10304
+ hash: "3627adf820bc44f99cca852096f337a0"
+ }
+ Frame {
+ msec: 10320
+ hash: "48c0f775534ff9bbe9227e60ad9a3622"
+ }
+ Frame {
+ msec: 10336
+ hash: "da5c6fd80ee0dc20e81031c84ede20cf"
+ }
+ Frame {
+ msec: 10352
+ hash: "ce7595da55b274259771eb99a42df454"
+ }
+ Frame {
+ msec: 10368
+ hash: "c2dd2aa17b9508477699fefe55bfbd06"
+ }
+ Frame {
+ msec: 10384
+ hash: "4ee897ddfec1081eef8bc5d799774f82"
+ }
+ Frame {
+ msec: 10400
+ hash: "f4da67964a175acf4cde4a24b054c24c"
+ }
+ Frame {
+ msec: 10416
+ hash: "e3da951dad465f1a69d8d7c08e888f02"
+ }
+ Frame {
+ msec: 10432
+ hash: "ff862073eada170a07d209048367b823"
+ }
+ Frame {
+ msec: 10448
+ hash: "cb61d5a89c1acc2b646f3c07214bea4a"
+ }
+ Frame {
+ msec: 10464
+ hash: "15d842ac551c15a136c7598adf2fe2b1"
+ }
+ Frame {
+ msec: 10480
+ hash: "04b9e85f7418bbc402e51e0ce8149180"
+ }
+ Frame {
+ msec: 10496
+ hash: "455dff37edfac66f5e4ae78e10b93cf9"
+ }
+ Frame {
+ msec: 10512
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10528
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10544
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10560
+ image: "packageviews.10.png"
+ }
+ Frame {
+ msec: 10576
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10592
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10608
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10624
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10640
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10656
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10672
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10688
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10704
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10720
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10736
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10752
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10768
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10784
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10800
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10816
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10832
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10848
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10864
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10880
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10896
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10912
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10928
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10944
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10960
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10976
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 10992
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11008
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11024
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11040
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11056
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11072
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11088
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11104
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11120
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11136
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11152
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11168
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11184
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11200
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11216
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11232
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11248
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11264
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11280
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11296
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11312
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11328
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11344
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11360
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11376
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11392
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11408
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11424
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11440
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11456
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11472
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11488
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11504
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 47; y: 141
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 11520
+ image: "packageviews.11.png"
+ }
+ Frame {
+ msec: 11536
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11552
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11568
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 47; y: 141
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 11584
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11600
+ hash: "259e9da7c3b8738db1762128f2c8d4b0"
+ }
+ Frame {
+ msec: 11616
+ hash: "cf515f316c197a307a7fb8373df3b107"
+ }
+ Frame {
+ msec: 11632
+ hash: "927379ba611284d5c98a3eb5aca04f7c"
+ }
+ Frame {
+ msec: 11648
+ hash: "387ad2042589de0a19cb13aa0cac8872"
+ }
+ Frame {
+ msec: 11664
+ hash: "6536ad87d1f04b13c28c43ae0fed984f"
+ }
+ Frame {
+ msec: 11680
+ hash: "38d77d6610739614e95c70f32736f238"
+ }
+ Frame {
+ msec: 11696
+ hash: "9a6c3a95b61d3b9b787417600123b6d8"
+ }
+ Frame {
+ msec: 11712
+ hash: "782d907d7d170108beb030c93d9a4d94"
+ }
+ Frame {
+ msec: 11728
+ hash: "646ee08d1ffe676ca0363f70e14c2ed6"
+ }
+ Frame {
+ msec: 11744
+ hash: "830730ed9990c8f96fa5c7e6b4228884"
+ }
+ Frame {
+ msec: 11760
+ hash: "2e678862f358814278d38950c7c5765b"
+ }
+ Frame {
+ msec: 11776
+ hash: "c656eb6ace9caf86d417d79452c4ea34"
+ }
+ Frame {
+ msec: 11792
+ hash: "227a9bb3644c26622ef654ba2c61ddad"
+ }
+ Frame {
+ msec: 11808
+ hash: "bc8188bf8be749bfb28fc64bb5773922"
+ }
+ Frame {
+ msec: 11824
+ hash: "f1e90cfd466bdc26ba98632fe1e5360c"
+ }
+ Frame {
+ msec: 11840
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11856
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11872
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11888
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11904
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11920
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11936
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11952
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11968
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 11984
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12000
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12016
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12032
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12048
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12064
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12080
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12096
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12112
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12128
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12144
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12160
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12176
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12192
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12208
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12224
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12240
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12256
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12272
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12288
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12304
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12320
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12336
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12352
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12368
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12384
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12400
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12416
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12432
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12448
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12464
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12480
+ image: "packageviews.12.png"
+ }
+ Frame {
+ msec: 12496
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12512
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12528
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12544
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12560
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12576
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12592
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12608
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12624
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12640
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12656
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12672
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12688
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12704
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12720
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12736
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12752
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12768
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12784
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12800
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12816
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12832
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12848
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12864
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12880
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12896
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12912
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12928
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12944
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12960
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12976
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+ Frame {
+ msec: 12992
+ hash: "81795ee4213ac62e073d811aaf6b580c"
+ }
+}
diff --git a/tests/auto/declarative/visual/Package_Views/packageviews.qml b/tests/auto/declarative/visual/Package_Views/packageviews.qml
new file mode 100644
index 0000000..c8016b6
--- /dev/null
+++ b/tests/auto/declarative/visual/Package_Views/packageviews.qml
@@ -0,0 +1,89 @@
+import Qt 4.6
+
+Rectangle {
+ id: root
+ width: 200
+ height: 200
+ color: "black"
+
+ VisualDatamodel {
+ id: model
+ model: Listmodel {
+ ListElement { itemColor: "red" }
+ ListElement { itemColor: "green" }
+ ListElement { itemColor: "blue" }
+ ListElement { itemColor: "orange" }
+ ListElement { itemColor: "purple" }
+ ListElement { itemColor: "yellow" }
+ ListElement { itemColor: "slategrey" }
+ ListElement { itemColor: "cyan" }
+ ListElement { itemColor: "red" }
+ ListElement { itemColor: "green" }
+ ListElement { itemColor: "blue" }
+ ListElement { itemColor: "orange" }
+ ListElement { itemColor: "purple" }
+ ListElement { itemColor: "yellow" }
+ ListElement { itemColor: "slategrey" }
+ ListElement { itemColor: "cyan" }
+ }
+ delegate: Package {
+ Rectangle {
+ id: listItem; Package.name: "list"; width:root.width/2; height: 50; color: "transparent"; border.color: "white"
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: myState.state = myState.state == "list" ? "grid" : "list"
+ }
+ }
+ Rectangle {
+ id: gridItem; Package.name: "grid"; width:50; height: 50; color: "transparent"; border.color: "white"
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: myState.state = myState.state == "list" ? "grid" : "list"
+ }
+ }
+ Rectangle { id: myContent; width:50; height: 50; color: itemColor }
+
+ StateGroup {
+ id: myState
+ state: "list"
+ states: [
+ State {
+ name: "list"
+ ParentChange { target: myContent; parent: listItem }
+ PropertyChanges { target: myContent; x: 0; y: 0; width: listItem.width }
+ },
+ State {
+ name: "grid"
+ ParentChange { target: myContent; parent: gridItem }
+ PropertyChanges { target: myContent; x: 0; y: 0; width: gridItem.width }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"; to: "*"
+ SequentialAnimation {
+ ParentAction{}
+ NumberAnimation { matchProperties: "x,y,width"; easing: "easeInOutQuad" }
+ }
+ }
+ ]
+ }
+ }
+ }
+
+ ListView {
+ width: parent.width/2
+ height: parent.height
+ model: model.parts.list
+ }
+
+ GridView {
+ x: parent.width/2
+ width: parent.width/2
+ cellWidth: 50
+ cellHeight: 50
+ height: parent.height
+ model: model.parts.grid
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/bindinganimation.qml b/tests/auto/declarative/visual/animation/bindinganimation/bindinganimation.qml
new file mode 100644
index 0000000..732eb59
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/bindinganimation.qml
@@ -0,0 +1,40 @@
+import Qt 4.6
+
+Rectangle {
+ color: "blue"
+ width: 320
+ height: 240
+ id: page
+ Rectangle {
+ id: myRectangle
+ width: 100
+ height: 100
+ color: "red"
+ x: 10
+ }
+ states: [
+ State {
+ name: "hello"
+ PropertyChanges {
+ target: myRectangle
+ x: 50 + 50
+ }
+ PropertyChanges {
+ target: myMouseRegion
+ onClicked: page.state = ''
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation {
+ matchProperties: "x"
+ }
+ }
+ ]
+ MouseRegion {
+ id: myMouseRegion
+ anchors.fill: parent
+ onClicked: { page.state= 'hello' }
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.0.png b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.0.png
new file mode 100644
index 0000000..1b08c81
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.1.png b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.1.png
new file mode 100644
index 0000000..f3074fc
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.2.png b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.2.png
new file mode 100644
index 0000000..1b08c81
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.3.png b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.3.png
new file mode 100644
index 0000000..e2560e0
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.4.png b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.4.png
new file mode 100644
index 0000000..2ddde86
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.5.png b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.5.png
new file mode 100644
index 0000000..f3074fc
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.6.png b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.6.png
new file mode 100644
index 0000000..1b08c81
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.qml b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.qml
new file mode 100644
index 0000000..8297c5a
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/bindinganimation/data/bindinganimation.qml
@@ -0,0 +1,1655 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 32
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 48
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 64
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 80
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 96
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 112
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 128
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 144
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 160
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 176
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 192
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 208
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 224
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 240
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 256
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 272
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 288
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 304
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 320
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 336
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 352
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 368
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 384
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 400
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 416
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 432
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 448
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 464
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 480
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 496
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 512
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 528
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 544
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 560
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 576
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 592
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 608
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 624
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 640
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 656
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 672
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 688
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 704
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 720
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 736
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 752
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 768
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 784
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 800
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 816
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 832
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 848
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 864
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 880
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 896
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 912
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 928
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 944
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 960
+ image: "bindinganimation.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 992
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1008
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1024
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1040
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1056
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1072
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1088
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1104
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1120
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1136
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1152
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 136; y: 174
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1168
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1184
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1200
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1216
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1232
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1248
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1264
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1280
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 136; y: 174
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1296
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 1312
+ hash: "a78c9394bf3b81f192f42710cd7218b1"
+ }
+ Frame {
+ msec: 1328
+ hash: "7f08e8170feb1d02373c9ab42b6e882d"
+ }
+ Frame {
+ msec: 1344
+ hash: "967fbad8ac664400a3efbe66617d62aa"
+ }
+ Frame {
+ msec: 1360
+ hash: "abc2ec0bc7a93e75b5823310e6284db1"
+ }
+ Frame {
+ msec: 1376
+ hash: "afbd5b24e2f86646f5ec2aa22f3a4b5b"
+ }
+ Frame {
+ msec: 1392
+ hash: "9413dffb7ee853ba0125ac22ab22abbd"
+ }
+ Frame {
+ msec: 1408
+ hash: "fcae0317f81a3ddd713f4db1349a9da0"
+ }
+ Frame {
+ msec: 1424
+ hash: "37739777a5979f3ebf85e47e63341660"
+ }
+ Frame {
+ msec: 1440
+ hash: "72731478d80f024076ea639b55152360"
+ }
+ Frame {
+ msec: 1456
+ hash: "69058485ced6bc992a1a7c5ee34add4c"
+ }
+ Frame {
+ msec: 1472
+ hash: "391ad7ff2362e059f6170dfe306f94a7"
+ }
+ Frame {
+ msec: 1488
+ hash: "f9f74a2e38b52c9266f33e428b6acd9d"
+ }
+ Frame {
+ msec: 1504
+ hash: "25152412c4ea2aec6caf89486c073484"
+ }
+ Frame {
+ msec: 1520
+ hash: "ba403842ba3128b1cdf6a9cb28c90751"
+ }
+ Frame {
+ msec: 1536
+ hash: "e90cd68490cf3ce6ef9fe4e8f92feaa9"
+ }
+ Frame {
+ msec: 1552
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1568
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1584
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1600
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1616
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1632
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1648
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1664
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1680
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1696
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1712
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1728
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1744
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1760
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1776
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1792
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1808
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1824
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1840
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1856
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1872
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1888
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1904
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1920
+ image: "bindinganimation.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1952
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1968
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 1984
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2000
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2016
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2032
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2048
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2064
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2080
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2096
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2112
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2128
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2144
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2160
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2176
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2192
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2208
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2224
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2240
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2256
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2272
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2288
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2304
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2320
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2336
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2352
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2368
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 2384
+ hash: "adc501a3a2b8aaf72f58ba985b57424e"
+ }
+ Frame {
+ msec: 2400
+ hash: "bfa51b7c19753ef7b16d78afffc7b9dd"
+ }
+ Frame {
+ msec: 2416
+ hash: "ffa8471f57765b49fcdb9155393251e5"
+ }
+ Frame {
+ msec: 2432
+ hash: "ddb65481469c38f2331546ee03a44206"
+ }
+ Frame {
+ msec: 2448
+ hash: "6f48d1a9977b77cafd38a5903017605b"
+ }
+ Frame {
+ msec: 2464
+ hash: "4279c814163af3bd069ce21b3cd1c729"
+ }
+ Frame {
+ msec: 2480
+ hash: "17c46242c17983478f34cb49cb91ca6e"
+ }
+ Frame {
+ msec: 2496
+ hash: "42f65c58b1f5f4b5ba70855f4aaa7d2f"
+ }
+ Frame {
+ msec: 2512
+ hash: "6a74d6dc91a8b370200d3765c55c1136"
+ }
+ Frame {
+ msec: 2528
+ hash: "ecda10356cca33901c2acd0a702fee46"
+ }
+ Frame {
+ msec: 2544
+ hash: "4f58226bdbda7339d972eca065f75766"
+ }
+ Frame {
+ msec: 2560
+ hash: "a39c80859a7643c9879da9c77b644703"
+ }
+ Frame {
+ msec: 2576
+ hash: "16fe17b15900ff0464ab20ea921e5b1f"
+ }
+ Frame {
+ msec: 2592
+ hash: "bc5c83b2014b7260900587ae3637598f"
+ }
+ Frame {
+ msec: 2608
+ hash: "96c077e3a572edff04fa9b2f7020ffd0"
+ }
+ Frame {
+ msec: 2624
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2640
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2656
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2672
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2688
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2704
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2720
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2736
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2752
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2768
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2784
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2800
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2816
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2832
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2848
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2864
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2880
+ image: "bindinganimation.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2912
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2928
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2944
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2960
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2976
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 2992
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3008
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3024
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3040
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3056
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3072
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3088
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3104
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3120
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3136
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3152
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3168
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3184
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3200
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3216
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3232
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3248
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3264
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3280
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3296
+ hash: "7cb5fc371040e587de9f06ce14a4b29a"
+ }
+ Frame {
+ msec: 3312
+ hash: "a78c9394bf3b81f192f42710cd7218b1"
+ }
+ Frame {
+ msec: 3328
+ hash: "7f08e8170feb1d02373c9ab42b6e882d"
+ }
+ Frame {
+ msec: 3344
+ hash: "967fbad8ac664400a3efbe66617d62aa"
+ }
+ Frame {
+ msec: 3360
+ hash: "abc2ec0bc7a93e75b5823310e6284db1"
+ }
+ Frame {
+ msec: 3376
+ hash: "afbd5b24e2f86646f5ec2aa22f3a4b5b"
+ }
+ Frame {
+ msec: 3392
+ hash: "9413dffb7ee853ba0125ac22ab22abbd"
+ }
+ Frame {
+ msec: 3408
+ hash: "fcae0317f81a3ddd713f4db1349a9da0"
+ }
+ Frame {
+ msec: 3424
+ hash: "37739777a5979f3ebf85e47e63341660"
+ }
+ Frame {
+ msec: 3440
+ hash: "72731478d80f024076ea639b55152360"
+ }
+ Frame {
+ msec: 3456
+ hash: "69058485ced6bc992a1a7c5ee34add4c"
+ }
+ Frame {
+ msec: 3472
+ hash: "391ad7ff2362e059f6170dfe306f94a7"
+ }
+ Mouse {
+ type: 4
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3488
+ hash: "f9f74a2e38b52c9266f33e428b6acd9d"
+ }
+ Frame {
+ msec: 3504
+ hash: "25152412c4ea2aec6caf89486c073484"
+ }
+ Frame {
+ msec: 3520
+ hash: "ba403842ba3128b1cdf6a9cb28c90751"
+ }
+ Frame {
+ msec: 3536
+ hash: "e90cd68490cf3ce6ef9fe4e8f92feaa9"
+ }
+ Frame {
+ msec: 3552
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 3568
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 3584
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 3600
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3616
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 3632
+ hash: "adc501a3a2b8aaf72f58ba985b57424e"
+ }
+ Frame {
+ msec: 3648
+ hash: "bfa51b7c19753ef7b16d78afffc7b9dd"
+ }
+ Frame {
+ msec: 3664
+ hash: "ffa8471f57765b49fcdb9155393251e5"
+ }
+ Frame {
+ msec: 3680
+ hash: "ddb65481469c38f2331546ee03a44206"
+ }
+ Frame {
+ msec: 3696
+ hash: "6f48d1a9977b77cafd38a5903017605b"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3712
+ hash: "4279c814163af3bd069ce21b3cd1c729"
+ }
+ Frame {
+ msec: 3728
+ hash: "17c46242c17983478f34cb49cb91ca6e"
+ }
+ Frame {
+ msec: 3744
+ hash: "42f65c58b1f5f4b5ba70855f4aaa7d2f"
+ }
+ Frame {
+ msec: 3760
+ hash: "6a74d6dc91a8b370200d3765c55c1136"
+ }
+ Frame {
+ msec: 3776
+ hash: "ecda10356cca33901c2acd0a702fee46"
+ }
+ Frame {
+ msec: 3792
+ hash: "4f58226bdbda7339d972eca065f75766"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3808
+ hash: "4f58226bdbda7339d972eca065f75766"
+ }
+ Frame {
+ msec: 3824
+ hash: "5fae0bdc65c609cb766ce585b8c649db"
+ }
+ Frame {
+ msec: 3840
+ image: "bindinganimation.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "6a74d6dc91a8b370200d3765c55c1136"
+ }
+ Frame {
+ msec: 3872
+ hash: "4f41101378a104e72228eeb4ba395ca8"
+ }
+ Frame {
+ msec: 3888
+ hash: "37739777a5979f3ebf85e47e63341660"
+ }
+ Frame {
+ msec: 3904
+ hash: "f4fe2cc93d65e086ba8ded1438269eb2"
+ }
+ Mouse {
+ type: 4
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3920
+ hash: "4279c814163af3bd069ce21b3cd1c729"
+ }
+ Frame {
+ msec: 3936
+ hash: "72a0c017a2fa90a4aeadfa6e552ff573"
+ }
+ Frame {
+ msec: 3952
+ hash: "391ad7ff2362e059f6170dfe306f94a7"
+ }
+ Frame {
+ msec: 3968
+ hash: "0b0c6419e1e5b016d9c22bd98fd452b1"
+ }
+ Frame {
+ msec: 3984
+ hash: "365c824c330398d267ea52ae9468b9ee"
+ }
+ Frame {
+ msec: 4000
+ hash: "65ad7e0189c096792331bd1bb0daf0db"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4016
+ hash: "65ad7e0189c096792331bd1bb0daf0db"
+ }
+ Frame {
+ msec: 4032
+ hash: "a21aa1984f068650cce2a124a82c12be"
+ }
+ Frame {
+ msec: 4048
+ hash: "8006ceaa02d22b5fdfeab400d39a0caf"
+ }
+ Frame {
+ msec: 4064
+ hash: "a2cebc35e5c2c709a2cd83e1df6eaeab"
+ }
+ Frame {
+ msec: 4080
+ hash: "07f751ea4cf877ba72fbb36f9da268d7"
+ }
+ Frame {
+ msec: 4096
+ hash: "72731478d80f024076ea639b55152360"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4112
+ hash: "37739777a5979f3ebf85e47e63341660"
+ }
+ Frame {
+ msec: 4128
+ hash: "ed47684a0b21836cd27549e0989e96dd"
+ }
+ Frame {
+ msec: 4144
+ hash: "772396bb23c713f34ea5c23bfbcb115e"
+ }
+ Frame {
+ msec: 4160
+ hash: "d9af30557f99b086bb1a185a946b580d"
+ }
+ Frame {
+ msec: 4176
+ hash: "575d30ac088448b01f49082519bbb3a1"
+ }
+ Frame {
+ msec: 4192
+ hash: "2e3f134664df8204a291af2c9f81239a"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4208
+ hash: "2e3f134664df8204a291af2c9f81239a"
+ }
+ Frame {
+ msec: 4224
+ hash: "4f58226bdbda7339d972eca065f75766"
+ }
+ Frame {
+ msec: 4240
+ hash: "5fae0bdc65c609cb766ce585b8c649db"
+ }
+ Frame {
+ msec: 4256
+ hash: "82363265ed2b611a54f8d48b2af22f11"
+ }
+ Frame {
+ msec: 4272
+ hash: "f9deee3a204c939562b896a6179743d2"
+ }
+ Frame {
+ msec: 4288
+ hash: "42f65c58b1f5f4b5ba70855f4aaa7d2f"
+ }
+ Mouse {
+ type: 4
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4304
+ hash: "3223ed179c828fadb3eca9c6373176c1"
+ }
+ Frame {
+ msec: 4320
+ hash: "56125a260a79bc38bb0ef44fd65ba49b"
+ }
+ Frame {
+ msec: 4336
+ hash: "07f751ea4cf877ba72fbb36f9da268d7"
+ }
+ Frame {
+ msec: 4352
+ hash: "6f48d1a9977b77cafd38a5903017605b"
+ }
+ Frame {
+ msec: 4368
+ hash: "8006ceaa02d22b5fdfeab400d39a0caf"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4384
+ hash: "8006ceaa02d22b5fdfeab400d39a0caf"
+ }
+ Frame {
+ msec: 4400
+ hash: "6f48d1a9977b77cafd38a5903017605b"
+ }
+ Frame {
+ msec: 4416
+ hash: "69058485ced6bc992a1a7c5ee34add4c"
+ }
+ Frame {
+ msec: 4432
+ hash: "dafcce427161a70c3513841ac22aea00"
+ }
+ Frame {
+ msec: 4448
+ hash: "3223ed179c828fadb3eca9c6373176c1"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4464
+ hash: "b08811b237ce7a460c80d285f04d53d8"
+ }
+ Frame {
+ msec: 4480
+ hash: "fcae0317f81a3ddd713f4db1349a9da0"
+ }
+ Frame {
+ msec: 4496
+ hash: "772396bb23c713f34ea5c23bfbcb115e"
+ }
+ Frame {
+ msec: 4512
+ hash: "ecda10356cca33901c2acd0a702fee46"
+ }
+ Frame {
+ msec: 4528
+ hash: "575d30ac088448b01f49082519bbb3a1"
+ }
+ Frame {
+ msec: 4544
+ hash: "abc2ec0bc7a93e75b5823310e6284db1"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4560
+ hash: "abc2ec0bc7a93e75b5823310e6284db1"
+ }
+ Frame {
+ msec: 4576
+ hash: "575d30ac088448b01f49082519bbb3a1"
+ }
+ Frame {
+ msec: 4592
+ hash: "ecda10356cca33901c2acd0a702fee46"
+ }
+ Frame {
+ msec: 4608
+ hash: "772396bb23c713f34ea5c23bfbcb115e"
+ }
+ Frame {
+ msec: 4624
+ hash: "fcae0317f81a3ddd713f4db1349a9da0"
+ }
+ Frame {
+ msec: 4640
+ hash: "b08811b237ce7a460c80d285f04d53d8"
+ }
+ Mouse {
+ type: 4
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4656
+ hash: "17c46242c17983478f34cb49cb91ca6e"
+ }
+ Frame {
+ msec: 4672
+ hash: "dafcce427161a70c3513841ac22aea00"
+ }
+ Frame {
+ msec: 4688
+ hash: "69058485ced6bc992a1a7c5ee34add4c"
+ }
+ Frame {
+ msec: 4704
+ hash: "6f48d1a9977b77cafd38a5903017605b"
+ }
+ Frame {
+ msec: 4720
+ hash: "ddb65481469c38f2331546ee03a44206"
+ }
+ Frame {
+ msec: 4736
+ hash: "a21aa1984f068650cce2a124a82c12be"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4752
+ hash: "a21aa1984f068650cce2a124a82c12be"
+ }
+ Frame {
+ msec: 4768
+ hash: "8006ceaa02d22b5fdfeab400d39a0caf"
+ }
+ Frame {
+ msec: 4784
+ hash: "6f48d1a9977b77cafd38a5903017605b"
+ }
+ Frame {
+ msec: 4800
+ image: "bindinganimation.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "56125a260a79bc38bb0ef44fd65ba49b"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4832
+ hash: "56c72b5da44bd5efdc47c3b9c3eac409"
+ }
+ Frame {
+ msec: 4848
+ hash: "42f65c58b1f5f4b5ba70855f4aaa7d2f"
+ }
+ Frame {
+ msec: 4864
+ hash: "6a74d6dc91a8b370200d3765c55c1136"
+ }
+ Frame {
+ msec: 4880
+ hash: "9413dffb7ee853ba0125ac22ab22abbd"
+ }
+ Frame {
+ msec: 4896
+ hash: "527b1f9e7a222483134675a73f9cf5b7"
+ }
+ Frame {
+ msec: 4912
+ hash: "ffeb3db6d3f177acf6f92049359a9025"
+ }
+ Frame {
+ msec: 4928
+ hash: "a39c80859a7643c9879da9c77b644703"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 122; y: 175
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4944
+ hash: "a39c80859a7643c9879da9c77b644703"
+ }
+ Frame {
+ msec: 4960
+ hash: "ffeb3db6d3f177acf6f92049359a9025"
+ }
+ Frame {
+ msec: 4976
+ hash: "527b1f9e7a222483134675a73f9cf5b7"
+ }
+ Frame {
+ msec: 4992
+ hash: "9413dffb7ee853ba0125ac22ab22abbd"
+ }
+ Frame {
+ msec: 5008
+ hash: "6a74d6dc91a8b370200d3765c55c1136"
+ }
+ Frame {
+ msec: 5024
+ hash: "4f41101378a104e72228eeb4ba395ca8"
+ }
+ Frame {
+ msec: 5040
+ hash: "56c72b5da44bd5efdc47c3b9c3eac409"
+ }
+ Frame {
+ msec: 5056
+ hash: "72731478d80f024076ea639b55152360"
+ }
+ Frame {
+ msec: 5072
+ hash: "07f751ea4cf877ba72fbb36f9da268d7"
+ }
+ Frame {
+ msec: 5088
+ hash: "a2cebc35e5c2c709a2cd83e1df6eaeab"
+ }
+ Frame {
+ msec: 5104
+ hash: "8006ceaa02d22b5fdfeab400d39a0caf"
+ }
+ Frame {
+ msec: 5120
+ hash: "f9f74a2e38b52c9266f33e428b6acd9d"
+ }
+ Frame {
+ msec: 5136
+ hash: "a93f930ec8528f954cd4a770c9a8171b"
+ }
+ Frame {
+ msec: 5152
+ hash: "bfa51b7c19753ef7b16d78afffc7b9dd"
+ }
+ Frame {
+ msec: 5168
+ hash: "df62027b6b53c69a071cb3dc09c3a7ed"
+ }
+ Frame {
+ msec: 5184
+ hash: "0d59ac57f8790fe741a31d12c3438abf"
+ }
+ Frame {
+ msec: 5200
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5216
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5232
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5248
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5264
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5280
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5296
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5312
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5328
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5344
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5360
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5376
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5392
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5408
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5424
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5440
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5456
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5472
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5488
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5504
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5520
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5536
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5552
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5568
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5584
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5600
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5616
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5632
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5648
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5664
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5680
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5696
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5712
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5728
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5744
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5760
+ image: "bindinganimation.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5792
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5808
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5824
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5840
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+ Frame {
+ msec: 5856
+ hash: "383ba6b9efcc58fca512982a207631f6"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/colorAnimation/colorAnimation.qml b/tests/auto/declarative/visual/animation/colorAnimation/colorAnimation.qml
new file mode 100644
index 0000000..0e98d7e
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/colorAnimation/colorAnimation.qml
@@ -0,0 +1,41 @@
+import Qt 4.6
+
+Rectangle {
+ id: mainrect
+ width: 200; height: 200
+ state: "first"
+ states: [
+ State {
+ name: "first"
+ PropertyChanges {
+ target: mainrect
+ color: "red"
+ }
+ },
+ State {
+ name: "second"
+ PropertyChanges {
+ target: mainrect
+ color: "blue"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "first"
+ to: "second"
+ reversible: true
+ SequentialAnimation {
+ ColorAnimation {
+ duration: 2000
+ target: mainrect
+ property: "color"
+ }
+ }
+ }
+ ]
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { mainrect.state = 'second' }
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.0.png b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.0.png
new file mode 100644
index 0000000..f4a6cfd
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.1.png b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.1.png
new file mode 100644
index 0000000..f4a6cfd
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.2.png b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.2.png
new file mode 100644
index 0000000..f4a6cfd
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.qml b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.qml
new file mode 100644
index 0000000..900bf5c
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/colorAnimation/data/colorAnimation.qml
@@ -0,0 +1,951 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 32
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 48
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 64
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 80
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 96
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 112
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 128
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 144
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 160
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 176
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 192
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 208
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 224
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 240
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 256
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 272
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 288
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 304
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 320
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 336
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 352
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 368
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 384
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 400
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 416
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 432
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 448
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 464
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 480
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 496
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 512
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 93; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 528
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 544
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 560
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 576
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Frame {
+ msec: 592
+ hash: "acc736435c9f84aa82941ba561bc5dbc"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 93; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 608
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 624
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 640
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 656
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 672
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 688
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 704
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 720
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 736
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 752
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 768
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 784
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 800
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 816
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 832
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 848
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 864
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 880
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 896
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 912
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 928
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 944
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 960
+ image: "colorAnimation.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 992
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1008
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1024
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1040
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1056
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1072
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1088
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1104
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1120
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1136
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1152
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1168
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1184
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1200
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1216
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1232
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1248
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1264
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1280
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1296
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1312
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1328
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1344
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1360
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1376
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1392
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1408
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1424
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1440
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1456
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1472
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1488
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1504
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1520
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1536
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1552
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1568
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1584
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1600
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1616
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1632
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1648
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1664
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1680
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1696
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1712
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1728
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1744
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1760
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1776
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1792
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1808
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1824
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1840
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1856
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1872
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1888
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1904
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1920
+ image: "colorAnimation.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1952
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1968
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 1984
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2000
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2016
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2032
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2048
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2064
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2080
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2096
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2112
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2128
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2144
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2160
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2176
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2192
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2208
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2224
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2240
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2256
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2272
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2288
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2304
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2320
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2336
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2352
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2368
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2384
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2400
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2416
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2432
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2448
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2464
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2480
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2496
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2512
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2528
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2544
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2560
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2576
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2592
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2608
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2624
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2640
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2656
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2672
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2688
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2704
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2720
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2736
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2752
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2768
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2784
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2800
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2816
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2832
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2848
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2864
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2880
+ image: "colorAnimation.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2912
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2928
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2944
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2960
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2976
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 2992
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3008
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3024
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3040
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3056
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3072
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3088
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3104
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3120
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3136
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3152
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3168
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3184
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3200
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3216
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3232
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3248
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3264
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3280
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3296
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3312
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3328
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3344
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3360
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3376
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3392
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3408
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3424
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3440
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3456
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3472
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3488
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3504
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3520
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3536
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3552
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3568
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3584
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3600
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3616
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3632
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3648
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3664
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+ Frame {
+ msec: 3680
+ hash: "8c0fcda4f8956394c53fc4ba18caa850"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/easing/data/easing.0.png b/tests/auto/declarative/visual/animation/easing/data/easing.0.png
new file mode 100644
index 0000000..4f75bfd
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/easing/data/easing.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/easing/data/easing.1.png b/tests/auto/declarative/visual/animation/easing/data/easing.1.png
new file mode 100644
index 0000000..dc17765
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/easing/data/easing.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/easing/data/easing.2.png b/tests/auto/declarative/visual/animation/easing/data/easing.2.png
new file mode 100644
index 0000000..7f83548
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/easing/data/easing.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/easing/data/easing.3.png b/tests/auto/declarative/visual/animation/easing/data/easing.3.png
new file mode 100644
index 0000000..c68e0fa
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/easing/data/easing.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/easing/data/easing.qml b/tests/auto/declarative/visual/animation/easing/data/easing.qml
new file mode 100644
index 0000000..d8e8688
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/easing/data/easing.qml
@@ -0,0 +1,779 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 32
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 48
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 64
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 80
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 96
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 112
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 128
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 144
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 160
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 176
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 192
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 208
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 224
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 240
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 256
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 272
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 111; y: 419
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 288
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 304
+ hash: "8f4c40d2e2b4f064bcb77c5ae43928c6"
+ }
+ Frame {
+ msec: 320
+ hash: "8b65094a9b7d5394fc67f92ea058627f"
+ }
+ Frame {
+ msec: 336
+ hash: "da450826b471a60ba98dabc581631ba1"
+ }
+ Frame {
+ msec: 352
+ hash: "e820fb4f1bc97152aa940b07db549f1b"
+ }
+ Frame {
+ msec: 368
+ hash: "b7d8186beca2fa0e37099f72419350f4"
+ }
+ Frame {
+ msec: 384
+ hash: "8500b93774f214e5e4789e25500262b8"
+ }
+ Frame {
+ msec: 400
+ hash: "277e1dff70285cca536b3e1fc2590688"
+ }
+ Frame {
+ msec: 416
+ hash: "b05b18f92c2089c681661566117ae0f5"
+ }
+ Frame {
+ msec: 432
+ hash: "6fec9c6b6ac3e3ea4126e3824a8d7566"
+ }
+ Frame {
+ msec: 448
+ hash: "53c6c90dd1eb7ca47721fc116474aebf"
+ }
+ Frame {
+ msec: 464
+ hash: "cf729c4a31414af3d2705878ba615738"
+ }
+ Frame {
+ msec: 480
+ hash: "f146b8a68960d507f893ef001189220e"
+ }
+ Frame {
+ msec: 496
+ hash: "18ff56b870bb048af246f928ee42a9b0"
+ }
+ Frame {
+ msec: 512
+ hash: "beee98f73fe7e878ada37b3070fa0c1d"
+ }
+ Frame {
+ msec: 528
+ hash: "435d389082912950a0be2b5dff480319"
+ }
+ Frame {
+ msec: 544
+ hash: "dc39b080eaddeaf4e309b90b7d97a835"
+ }
+ Frame {
+ msec: 560
+ hash: "666b1cde53f78d7db9c81e21adbe406a"
+ }
+ Frame {
+ msec: 576
+ hash: "c5c9627f4329e48aa96ebfbc982b6ba6"
+ }
+ Frame {
+ msec: 592
+ hash: "a583042052e5da7e80a4956337d6d1ff"
+ }
+ Frame {
+ msec: 608
+ hash: "a4a5df787e15da6f28275a12898e7620"
+ }
+ Frame {
+ msec: 624
+ hash: "02cacec2ccc803ebc03c5540484cbcaa"
+ }
+ Frame {
+ msec: 640
+ hash: "00600df1f006f358feaf43bfae9d32a5"
+ }
+ Frame {
+ msec: 656
+ hash: "737c884ba0d6d38b66252f4b97a36c33"
+ }
+ Frame {
+ msec: 672
+ hash: "7eeeade8100c84a6b56efa51cf597baf"
+ }
+ Frame {
+ msec: 688
+ hash: "18ab79d495097f0103dcf14db1897a88"
+ }
+ Frame {
+ msec: 704
+ hash: "21d3b0da00c46a101e09048928cd8027"
+ }
+ Frame {
+ msec: 720
+ hash: "a5995b0341872c275ffbc5aaee6eb853"
+ }
+ Frame {
+ msec: 736
+ hash: "bb4a37c1bd5e412ebce54d9539017723"
+ }
+ Frame {
+ msec: 752
+ hash: "63dcde9e2751ca94ed7d739feb359221"
+ }
+ Frame {
+ msec: 768
+ hash: "5790c8407e2e4d1a6a937d86d57d8edb"
+ }
+ Frame {
+ msec: 784
+ hash: "3a1c77abf6822030db60a036027dc86e"
+ }
+ Frame {
+ msec: 800
+ hash: "2a13c573ab9846cce60384dd7138b2b4"
+ }
+ Frame {
+ msec: 816
+ hash: "98983c2525265830033495b61071a5aa"
+ }
+ Frame {
+ msec: 832
+ hash: "26d2bba3d77053b410715afb497d4063"
+ }
+ Frame {
+ msec: 848
+ hash: "fd65d954c16acee425d9de65af68ef40"
+ }
+ Frame {
+ msec: 864
+ hash: "094fcc18d28b19ac6b452dd8106d813b"
+ }
+ Frame {
+ msec: 880
+ hash: "160105f6f99a960763535e4d51990ef6"
+ }
+ Frame {
+ msec: 896
+ hash: "0d5d1e6a66fc1f49f1106f01fb5a1c52"
+ }
+ Frame {
+ msec: 912
+ hash: "f6abc32680865783a4d94ecb738f9ff6"
+ }
+ Frame {
+ msec: 928
+ hash: "350509eceb134d5b18647e5ad07dbb47"
+ }
+ Frame {
+ msec: 944
+ hash: "a84e4e7c5385dc1f24ca219f45d529a5"
+ }
+ Frame {
+ msec: 960
+ image: "easing.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "efcc5ae79da3fa2f4c7d6eaa35e32d33"
+ }
+ Frame {
+ msec: 992
+ hash: "ff4afce604c8ecb4f08d1ddef8552534"
+ }
+ Frame {
+ msec: 1008
+ hash: "e2e63e12e9a5f8459720dd8b023ed17b"
+ }
+ Frame {
+ msec: 1024
+ hash: "991a01f92bcfa9cd9fe98e3f39d192fc"
+ }
+ Frame {
+ msec: 1040
+ hash: "bc3d2f0f3fac650c981457f3694c2518"
+ }
+ Frame {
+ msec: 1056
+ hash: "ee39fc9b1a602bf813d9118aa21901ac"
+ }
+ Frame {
+ msec: 1072
+ hash: "42120d098f2adf1e331332b33442dd3e"
+ }
+ Frame {
+ msec: 1088
+ hash: "1660c69b77b800d1ab57b93f0fc12aa5"
+ }
+ Frame {
+ msec: 1104
+ hash: "0630a3d6b8cb5dece5dc660f05036ec6"
+ }
+ Frame {
+ msec: 1120
+ hash: "9163f0bd9c5888794d7a09d3359bf1e5"
+ }
+ Frame {
+ msec: 1136
+ hash: "e0b7ad4883f679948c852ff152ba7907"
+ }
+ Frame {
+ msec: 1152
+ hash: "f748fc44f99b706e42b899cb18dbaaf7"
+ }
+ Frame {
+ msec: 1168
+ hash: "c84442f0cb1cf0bb50dae7d1c701aaf8"
+ }
+ Frame {
+ msec: 1184
+ hash: "d7b41567e3f3aa9576fe2793872134b7"
+ }
+ Frame {
+ msec: 1200
+ hash: "a1d10ff1adb85000902486fc8e4faa8d"
+ }
+ Frame {
+ msec: 1216
+ hash: "44b7b5d77068e360ead3af84e7d80232"
+ }
+ Frame {
+ msec: 1232
+ hash: "486c0b19c1379d9eefdf575a085e2875"
+ }
+ Frame {
+ msec: 1248
+ hash: "1d474472856d4740d960eb2f788ca5a6"
+ }
+ Frame {
+ msec: 1264
+ hash: "c74082553ab0f4ee00f5044e3369580b"
+ }
+ Frame {
+ msec: 1280
+ hash: "89fcd5514f336075ad32cae69518c1e5"
+ }
+ Frame {
+ msec: 1296
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1312
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1328
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1344
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1360
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1376
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1392
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1408
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1424
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1440
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1456
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1472
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1488
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1504
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1520
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1536
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1552
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1568
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1584
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1600
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 111; y: 419
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1616
+ hash: "9dd235eb98998d9bdd92e01300297257"
+ }
+ Frame {
+ msec: 1632
+ hash: "b77240f32e83d4f332d815c626f1e560"
+ }
+ Frame {
+ msec: 1648
+ hash: "7d89669231224cf8e02d75338c37c278"
+ }
+ Frame {
+ msec: 1664
+ hash: "a8cf7c179011ee8187a8e1111683e52e"
+ }
+ Frame {
+ msec: 1680
+ hash: "3e87a57e05da09a8260801320431b922"
+ }
+ Frame {
+ msec: 1696
+ hash: "a2b0d99c8a232715fe03e8772a36634c"
+ }
+ Frame {
+ msec: 1712
+ hash: "5b4634cd495ae7bb9c69a5c9c346189e"
+ }
+ Frame {
+ msec: 1728
+ hash: "492f8f2b84af355ef41c1a7cda3a8a73"
+ }
+ Frame {
+ msec: 1744
+ hash: "88e4eb08520fb5acc3d88ac4f0900542"
+ }
+ Frame {
+ msec: 1760
+ hash: "0c09cdcb906b4ce9840fd7502c39e5b9"
+ }
+ Frame {
+ msec: 1776
+ hash: "b054083bdd212cc03167a90df2d7eac5"
+ }
+ Frame {
+ msec: 1792
+ hash: "83971c2d37616ab92680364d6ac288a6"
+ }
+ Frame {
+ msec: 1808
+ hash: "a73951d25e2cb7c1d04c88c86dfa0e4d"
+ }
+ Frame {
+ msec: 1824
+ hash: "31fc8b20302abac97e506c37a14bbb7e"
+ }
+ Frame {
+ msec: 1840
+ hash: "f760ccd7339e01a9423da7b592498291"
+ }
+ Frame {
+ msec: 1856
+ hash: "24dfcd5553f854908396de751fb15b88"
+ }
+ Frame {
+ msec: 1872
+ hash: "1daf38a6e6199f980e9494a3eb480047"
+ }
+ Frame {
+ msec: 1888
+ hash: "a39e2de1090209e5dbc8cc26577ec97d"
+ }
+ Frame {
+ msec: 1904
+ hash: "f4edc780b063e34461263ed3b753be88"
+ }
+ Frame {
+ msec: 1920
+ image: "easing.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "a19b0353604491f56f72be0d20d76955"
+ }
+ Frame {
+ msec: 1952
+ hash: "9a70f109eebfcede2311ef77ceb50a44"
+ }
+ Frame {
+ msec: 1968
+ hash: "7b28313d6860aeefd4a4e136d38d62f8"
+ }
+ Frame {
+ msec: 1984
+ hash: "95d84f38473159fe6b38f84ffe371714"
+ }
+ Frame {
+ msec: 2000
+ hash: "07f91261794edb0ac1fde9bb4ff36011"
+ }
+ Frame {
+ msec: 2016
+ hash: "f9a4a6b92a9c2d265688f1bfac18fa0a"
+ }
+ Frame {
+ msec: 2032
+ hash: "cdec7cc00380fde4f73be997a992251a"
+ }
+ Frame {
+ msec: 2048
+ hash: "a52b34f84e98fcd8babb1d39979fc9c7"
+ }
+ Frame {
+ msec: 2064
+ hash: "bf05b3c79a9616f2e6c33d348b30e0ba"
+ }
+ Frame {
+ msec: 2080
+ hash: "c5931785685b4f4854d3ddfff5dd5466"
+ }
+ Frame {
+ msec: 2096
+ hash: "bae163e02b860a9ca19d1bcb60ac1f8e"
+ }
+ Frame {
+ msec: 2112
+ hash: "a36295a1ebb35e538f8899ae3ae3b36a"
+ }
+ Frame {
+ msec: 2128
+ hash: "b6448d61803d9b2c05b438aa8ce8bcd5"
+ }
+ Frame {
+ msec: 2144
+ hash: "631bf4caff2d93ef96a426100ffc5b32"
+ }
+ Frame {
+ msec: 2160
+ hash: "a8777c84a03996493f719f5fcfc80d00"
+ }
+ Frame {
+ msec: 2176
+ hash: "86e1759df103ef776bb03f24941f49da"
+ }
+ Frame {
+ msec: 2192
+ hash: "01a790ea60adeaf368c66bd53aa8fcb3"
+ }
+ Frame {
+ msec: 2208
+ hash: "79e5aca8ef6b9764f7f99cdfb51222ae"
+ }
+ Frame {
+ msec: 2224
+ hash: "82d10cc01b9be4683c5aa76096bd462c"
+ }
+ Frame {
+ msec: 2240
+ hash: "95d961a92c597e432611947f7480796a"
+ }
+ Frame {
+ msec: 2256
+ hash: "e8ee89b5313c7e2c66741fe1c2090029"
+ }
+ Frame {
+ msec: 2272
+ hash: "2e3e8cf25dc1a3f09e7bf2a086f8e3bb"
+ }
+ Frame {
+ msec: 2288
+ hash: "68ca8ad381f48db23d2bc5da9da0c17a"
+ }
+ Frame {
+ msec: 2304
+ hash: "e29f2411667049e8fae6c080f61c5869"
+ }
+ Frame {
+ msec: 2320
+ hash: "5b0a6fadedf3024e8ecb7f2c73a2277d"
+ }
+ Frame {
+ msec: 2336
+ hash: "af2eac625ef1fd928093ccd60bc0058e"
+ }
+ Frame {
+ msec: 2352
+ hash: "8a1ff780ebdc9e416e60ea0940e8f2d6"
+ }
+ Frame {
+ msec: 2368
+ hash: "7eb316c51cfd8ad972b7040247a651eb"
+ }
+ Frame {
+ msec: 2384
+ hash: "1bac7075c10c87a69e71c3859f0db41d"
+ }
+ Frame {
+ msec: 2400
+ hash: "0f16f40567729065cf9ecfcc15395a7b"
+ }
+ Frame {
+ msec: 2416
+ hash: "719f4e776776f0db5c68ae7c6177e9b7"
+ }
+ Frame {
+ msec: 2432
+ hash: "75172dbf31fd8d706f54748c59099845"
+ }
+ Frame {
+ msec: 2448
+ hash: "d730b550e05167b05350e0e6636dd97d"
+ }
+ Frame {
+ msec: 2464
+ hash: "e1f33eb5f023d9d42a99f8bc23223c45"
+ }
+ Frame {
+ msec: 2480
+ hash: "8a4b0df5bed6c7be73c194ce2bb6a271"
+ }
+ Frame {
+ msec: 2496
+ hash: "44a9ea371f12d4ac3a569121a995ae16"
+ }
+ Frame {
+ msec: 2512
+ hash: "14747e2e9e072210b9d6db50b4f704a1"
+ }
+ Frame {
+ msec: 2528
+ hash: "eea52abf430f8cc1adc37e7180036584"
+ }
+ Frame {
+ msec: 2544
+ hash: "0a9f6b14bc02e929a45bf4ebb736f9d3"
+ }
+ Frame {
+ msec: 2560
+ hash: "a68a6eef0fc8754564c47c88b60d9a2a"
+ }
+ Frame {
+ msec: 2576
+ hash: "eeb469e2fbda131d83538055e88ecdf7"
+ }
+ Frame {
+ msec: 2592
+ hash: "0f7b673472050e807c9d935fde5afd83"
+ }
+ Frame {
+ msec: 2608
+ hash: "80c90cce66bdd2324ca98bc591c22b44"
+ }
+ Frame {
+ msec: 2624
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2640
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2656
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2672
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2688
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2704
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2720
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2736
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2752
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2768
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2784
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2800
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2816
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2832
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2848
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2864
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2880
+ image: "easing.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2912
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2928
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2944
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2960
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2976
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 2992
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 3008
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+ Frame {
+ msec: 3024
+ hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/easing/easing.qml b/tests/auto/declarative/visual/animation/easing/easing.qml
new file mode 100644
index 0000000..1e8e907
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/easing/easing.qml
@@ -0,0 +1,193 @@
+import Qt 4.6
+
+Rectangle {
+ id: item
+ width: 600
+ height: layout.height
+ color: "white"
+ resources: [
+ ListModel {
+ id: easingtypes
+ ListElement {
+ type: "easeLinear"
+ }
+ ListElement {
+ type: "easeInQuad"
+ }
+ ListElement {
+ type: "easeOutQuad"
+ }
+ ListElement {
+ type: "easeInOutQuad"
+ }
+ ListElement {
+ type: "easeOutInQuad"
+ }
+ ListElement {
+ type: "easeInCubic"
+ }
+ ListElement {
+ type: "easeOutCubic"
+ }
+ ListElement {
+ type: "easeInOutCubic"
+ }
+ ListElement {
+ type: "easeOutInCubic"
+ }
+ ListElement {
+ type: "easeInQuart"
+ }
+ ListElement {
+ type: "easeOutQuart"
+ }
+ ListElement {
+ type: "easeInOutQuart"
+ }
+ ListElement {
+ type: "easeOutInQuart"
+ }
+ ListElement {
+ type: "easeInQuint"
+ }
+ ListElement {
+ type: "easeOutQuint"
+ }
+ ListElement {
+ type: "easeInOutQuint"
+ }
+ ListElement {
+ type: "easeOutInQuint"
+ }
+ ListElement {
+ type: "easeInSine"
+ }
+ ListElement {
+ type: "easeOutSine"
+ }
+ ListElement {
+ type: "easeInOutSine"
+ }
+ ListElement {
+ type: "easeOutInSine"
+ }
+ ListElement {
+ type: "easeInExpo"
+ }
+ ListElement {
+ type: "easeOutExpo"
+ }
+ ListElement {
+ type: "easeInOutExpo"
+ }
+ ListElement {
+ type: "easeOutInExpo"
+ }
+ ListElement {
+ type: "easeInCirc"
+ }
+ ListElement {
+ type: "easeOutCirc"
+ }
+ ListElement {
+ type: "easeInOutCirc"
+ }
+ ListElement {
+ type: "easeOutInCirc"
+ }
+ ListElement {
+ type: "easeInElastic"
+ }
+ ListElement {
+ type: "easeOutElastic"
+ }
+ ListElement {
+ type: "easeInOutElastic"
+ }
+ ListElement {
+ type: "easeOutInElastic"
+ }
+ ListElement {
+ type: "easeInBack"
+ }
+ ListElement {
+ type: "easeOutBack"
+ }
+ ListElement {
+ type: "easeInOutBack"
+ }
+ ListElement {
+ type: "easeOutInBack"
+ }
+ ListElement {
+ type: "easeOutBounce"
+ }
+ ListElement {
+ type: "easeInBounce"
+ }
+ ListElement {
+ type: "easeInOutBounce"
+ }
+ ListElement {
+ type: "easeOutInBounce"
+ }
+ }
+ ]
+ Column {
+ id: layout
+ anchors.left: item.left
+ anchors.right: item.right
+ Repeater {
+ model: easingtypes
+ Component {
+ Rectangle {
+ id: block
+ Text {
+ text: type
+ anchors.centerIn: parent
+ font.italic: true
+ color: index & 1 ? "black" : "white"
+ opacity: 0 // 1 for debugging
+ }
+ width: 120
+ height: 18
+ color: index & 1 ? "red" : "blue"
+ states: [
+ State {
+ name: "from"
+ when: !mouse.pressed
+ PropertyChanges {
+ target: block
+ x: 0
+ }
+ },
+ State {
+ name: "to"
+ when: mouse.pressed
+ PropertyChanges {
+ target: block
+ x: item.width-block.width
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"
+ to: "to"
+ reversible: true
+ NumberAnimation {
+ matchProperties: "x"
+ easing: type
+ duration: 1000
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ MouseRegion {
+ id: mouse
+ anchors.fill: layout
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/easing/pics/qtlogo.png b/tests/auto/declarative/visual/animation/easing/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/easing/pics/qtlogo.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.0.png b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.0.png
new file mode 100644
index 0000000..82c18d7
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.1.png b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.1.png
new file mode 100644
index 0000000..b9a3b89
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.2.png b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.2.png
new file mode 100644
index 0000000..789615b
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.qml b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.qml
new file mode 100644
index 0000000..5f5b8fc
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parallelAnimation/data/parallelAnimation.qml
@@ -0,0 +1,463 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 32
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 48
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 64
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 80
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 96
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 112
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 128
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 144
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 160
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 176
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 192
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 208
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 224
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 240
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 256
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 272
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 288
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 304
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 320
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 336
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 352
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 368
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 384
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 400
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 416
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 432
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 448
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 464
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 480
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 496
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 512
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 528
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 544
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 560
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 576
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 592
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 608
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 624
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 640
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 656
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 672
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 688
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 704
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 720
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 736
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 752
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 137; y: 74
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 768
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 784
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 800
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 816
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 832
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 848
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 864
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 137; y: 74
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 880
+ hash: "4faa7727bafeea0771f2db62f0141ac9"
+ }
+ Frame {
+ msec: 896
+ hash: "0fada111cb977c4de8c7499e44714f38"
+ }
+ Frame {
+ msec: 912
+ hash: "1817e010332117dcddc1a1b1a2caf52d"
+ }
+ Frame {
+ msec: 928
+ hash: "e4add6bf93479c9bca571419fe2fabf9"
+ }
+ Frame {
+ msec: 944
+ hash: "d8812e206d2cbf434d58db6a35439a44"
+ }
+ Frame {
+ msec: 960
+ image: "parallelAnimation.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "a238178c584aaf2563d29bff927d5bab"
+ }
+ Frame {
+ msec: 992
+ hash: "f583e9fe8feda02e796a61c5fed7b0eb"
+ }
+ Frame {
+ msec: 1008
+ hash: "b3a1a4fd85912831e551a8c07da1a561"
+ }
+ Frame {
+ msec: 1024
+ hash: "f7c111ee4a04af6c1da958f8b56c28ee"
+ }
+ Frame {
+ msec: 1040
+ hash: "f53fa374817d81ee44fb98e64e464b36"
+ }
+ Frame {
+ msec: 1056
+ hash: "547ddef13cbcaaf57bb1f4e2bb7bc822"
+ }
+ Frame {
+ msec: 1072
+ hash: "8b10ccfef926103a6d67d68eee250f83"
+ }
+ Frame {
+ msec: 1088
+ hash: "008bbb50dc659e6f5eea15290680edd7"
+ }
+ Frame {
+ msec: 1104
+ hash: "0217e3230d3df44363a023d0d7defc5f"
+ }
+ Frame {
+ msec: 1120
+ hash: "ab9907a92452de6878f4c346febe705c"
+ }
+ Frame {
+ msec: 1136
+ hash: "7bce31f347a7f0598d2d64026c702f3e"
+ }
+ Frame {
+ msec: 1152
+ hash: "032080184907bc5b01db7675802d7dbe"
+ }
+ Frame {
+ msec: 1168
+ hash: "2cba43a2e5febcc44bfd1379b9cb2591"
+ }
+ Frame {
+ msec: 1184
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1200
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1216
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1232
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1248
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1264
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1280
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1296
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1312
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1328
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1344
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1360
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1376
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1392
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1408
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1424
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1440
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1456
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1472
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1488
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1504
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1520
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1536
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1552
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1568
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1584
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1600
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1616
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1632
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1648
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1664
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1680
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1696
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1712
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+ Frame {
+ msec: 1728
+ hash: "b901a51b5605621adff7b34c61f8f320"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/parallelAnimation/parallelAnimation.qml b/tests/auto/declarative/visual/animation/parallelAnimation/parallelAnimation.qml
new file mode 100644
index 0000000..9e0422f
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parallelAnimation/parallelAnimation.qml
@@ -0,0 +1,43 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 200
+ Rectangle {
+ id: redRect
+ width: 100; height: 100
+ color: "red"
+ }
+ Rectangle {
+ id: redRect2
+ width: 100; height: 100
+ y: 100
+ color: "red"
+ }
+
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: parent.state = "state1"
+ }
+
+ states: State {
+ name: "state1"
+ PropertyChanges {
+ target: redRect
+ x: 300
+ color: "purple"
+ }
+ PropertyChanges {
+ target: redRect2
+ x: 300
+ color: "purple"
+ }
+ }
+
+ transitions: Transition {
+ PropertyAnimation { matchTargets: redRect; matchProperties: "x,color"; duration: 300 }
+ ParallelAnimation {
+ NumberAnimation { matchTargets: redRect2; matchProperties: "x"; duration: 300 }
+ ColorAnimation { matchTargets: redRect2; matchProperties: "color"; duration: 300 }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/parentAction/data/parentAction.0.png b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.0.png
new file mode 100644
index 0000000..a0032f8
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parentAction/data/parentAction.1.png b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.1.png
new file mode 100644
index 0000000..958b6af
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parentAction/data/parentAction.2.png b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.2.png
new file mode 100644
index 0000000..3a1811f
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parentAction/data/parentAction.3.png b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.3.png
new file mode 100644
index 0000000..36064c2
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parentAction/data/parentAction.4.png b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.4.png
new file mode 100644
index 0000000..c493a1d
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parentAction/data/parentAction.5.png b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.5.png
new file mode 100644
index 0000000..c493a1d
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/parentAction/data/parentAction.qml b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.qml
new file mode 100644
index 0000000..de27af7
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/data/parentAction.qml
@@ -0,0 +1,1207 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 32
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 48
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 64
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 80
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 96
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 112
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 128
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 144
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 160
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 176
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 192
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 208
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 224
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 240
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 256
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 272
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 288
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 304
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 320
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 336
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 352
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 368
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 384
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 400
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 416
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 432
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 448
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 464
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 480
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 496
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 512
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 528
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 544
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 560
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 576
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 150; y: 274
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 592
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 608
+ hash: "a7bb3d44c8bcf403906afa86f5bc3062"
+ }
+ Frame {
+ msec: 624
+ hash: "2b366e6009e70fa0227a1fee662fe1bf"
+ }
+ Frame {
+ msec: 640
+ hash: "c12869fb8002aa36c3bfad7fd0979240"
+ }
+ Frame {
+ msec: 656
+ hash: "56c583e77b5e0a8707e977dc937c2acf"
+ }
+ Frame {
+ msec: 672
+ hash: "6b191d57a45a3f2d010a7f44064e409a"
+ }
+ Frame {
+ msec: 688
+ hash: "9457ee33c999a63fa4bd4db5c3ceac8b"
+ }
+ Frame {
+ msec: 704
+ hash: "446b23b662640ad6ad8c456f956fe73a"
+ }
+ Frame {
+ msec: 720
+ hash: "23c59708069406486e4979c7d59f3f4a"
+ }
+ Frame {
+ msec: 736
+ hash: "c9ce43ddca79b5b6f26af2c2259dc071"
+ }
+ Frame {
+ msec: 752
+ hash: "e838229ba70c30112918f19bb471fa34"
+ }
+ Frame {
+ msec: 768
+ hash: "0cbaeddb2ff6408a37a68fc685e2bca0"
+ }
+ Frame {
+ msec: 784
+ hash: "616b4ec719586b151ba3d709e51038bf"
+ }
+ Frame {
+ msec: 800
+ hash: "89b2c709f5c3083c204a9450e605c1d4"
+ }
+ Frame {
+ msec: 816
+ hash: "427a5c2d13631d899ff2d673e762f114"
+ }
+ Frame {
+ msec: 832
+ hash: "958aa9ca5a6b91aa6dfbc2a1ae3e2deb"
+ }
+ Frame {
+ msec: 848
+ hash: "09a3ac0010ed8f3df2cfa7ed9d0a92e4"
+ }
+ Frame {
+ msec: 864
+ hash: "5607ea54f9990f3232d6f56080e1ef15"
+ }
+ Frame {
+ msec: 880
+ hash: "600682467c55288b9d5e65299637dd72"
+ }
+ Frame {
+ msec: 896
+ hash: "bc7a238611574a13650f854ceac35032"
+ }
+ Frame {
+ msec: 912
+ hash: "e5f6b19b3685a96d4d0c3b8384513643"
+ }
+ Frame {
+ msec: 928
+ hash: "d5d23b0fc09136fd1ae121e311866cc3"
+ }
+ Frame {
+ msec: 944
+ hash: "5099e5edd1a6bd37f5f6c836a6ca7644"
+ }
+ Frame {
+ msec: 960
+ image: "parentAction.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "97dd20f7774cfd8379e1d1b44f8ddc7b"
+ }
+ Frame {
+ msec: 992
+ hash: "ab2deea9e4f8c43ed58b5a355800ecda"
+ }
+ Frame {
+ msec: 1008
+ hash: "88ec383ce368259d3cc18612b6f5b941"
+ }
+ Frame {
+ msec: 1024
+ hash: "f84b20b849a77e50717f99b9d844240e"
+ }
+ Frame {
+ msec: 1040
+ hash: "6c042360c2d24ad56cec32d01ce82d6b"
+ }
+ Frame {
+ msec: 1056
+ hash: "c86b464720192f3e039fa5d8ab5f09bb"
+ }
+ Frame {
+ msec: 1072
+ hash: "35ec432fdf91fcd1dfcd945cfe785b09"
+ }
+ Frame {
+ msec: 1088
+ hash: "27a2ec28e4fef006622e8211fd709853"
+ }
+ Frame {
+ msec: 1104
+ hash: "8454d1f5ed89551e2a403c869885116a"
+ }
+ Frame {
+ msec: 1120
+ hash: "7e33aed53dc4338c168274d972c8e711"
+ }
+ Frame {
+ msec: 1136
+ hash: "e0192ea2049d6bae6012f00406630a92"
+ }
+ Frame {
+ msec: 1152
+ hash: "a2ea5489a373084169024035a0f69e71"
+ }
+ Frame {
+ msec: 1168
+ hash: "6947a72c4d959b90dafdaddcac815b3e"
+ }
+ Frame {
+ msec: 1184
+ hash: "0e22cc3c96d0934095b7254f0f28b18b"
+ }
+ Frame {
+ msec: 1200
+ hash: "72529ddc6f2678a783aedf445d7038a4"
+ }
+ Frame {
+ msec: 1216
+ hash: "38f03c0ee50488ffd23a2fb3d3445461"
+ }
+ Frame {
+ msec: 1232
+ hash: "b441721ed30c787874a2a71a94e1ba44"
+ }
+ Frame {
+ msec: 1248
+ hash: "1e37f26d78590414b2ef01c72ad136a9"
+ }
+ Frame {
+ msec: 1264
+ hash: "88e4af80d068485ebd8c3d51f9bbfe8d"
+ }
+ Frame {
+ msec: 1280
+ hash: "107707216c16c629d8409cf006f9f2dc"
+ }
+ Frame {
+ msec: 1296
+ hash: "f56f3f4f140ac072f7df47eddfc76844"
+ }
+ Frame {
+ msec: 1312
+ hash: "41239a9d8ed793c24967875aabeae8a5"
+ }
+ Frame {
+ msec: 1328
+ hash: "30035e37320dae4f9ead01a30895eb38"
+ }
+ Frame {
+ msec: 1344
+ hash: "fb2f535b42b862b65f8adb3ad1a46779"
+ }
+ Frame {
+ msec: 1360
+ hash: "e10ba7f74d52fc963e20a4647ff0d620"
+ }
+ Frame {
+ msec: 1376
+ hash: "5abf5388566bed2fdb71afc8cd7cfe9b"
+ }
+ Frame {
+ msec: 1392
+ hash: "91990471563e3c8292e8e8325a1d17a2"
+ }
+ Frame {
+ msec: 1408
+ hash: "59a6293a48f83a9197adcffed3f32f15"
+ }
+ Frame {
+ msec: 1424
+ hash: "db3e75df318e9f0d239ce9b76e92eff3"
+ }
+ Frame {
+ msec: 1440
+ hash: "3b5c64bc64a701edb5c2e40b23443bc3"
+ }
+ Frame {
+ msec: 1456
+ hash: "9db08c0375148b2317427591b5f43608"
+ }
+ Frame {
+ msec: 1472
+ hash: "2d761f1530846eff87a7625a120e0afd"
+ }
+ Frame {
+ msec: 1488
+ hash: "c5460f8c58b83c2ac15842ddb023ad4f"
+ }
+ Frame {
+ msec: 1504
+ hash: "0efb51810a2dc359c7964268c98ea8eb"
+ }
+ Frame {
+ msec: 1520
+ hash: "b92a42012df57eb261badf1f518b8e67"
+ }
+ Frame {
+ msec: 1536
+ hash: "8d348bae62af2d35bdfee806a1c39910"
+ }
+ Frame {
+ msec: 1552
+ hash: "762d9bb4ed11d249bfd902a541129d60"
+ }
+ Frame {
+ msec: 1568
+ hash: "bddbd9f64a9f7156984feccd5fa94093"
+ }
+ Frame {
+ msec: 1584
+ hash: "353a98e1573b0518941ff22bf2776244"
+ }
+ Frame {
+ msec: 1600
+ hash: "1765aed97e29f25dee93a77a06557b82"
+ }
+ Frame {
+ msec: 1616
+ hash: "73b5c2bdb7f268f7a33e129c8ba44013"
+ }
+ Frame {
+ msec: 1632
+ hash: "46ac1976fb9932d0ef6e0b5927386ad9"
+ }
+ Frame {
+ msec: 1648
+ hash: "90b5b5b46c9c352e8be41cc74f96133a"
+ }
+ Frame {
+ msec: 1664
+ hash: "0efe0036577c890fd45cd7dd53014616"
+ }
+ Frame {
+ msec: 1680
+ hash: "7f32df17481abf40ccb33afe6d17085d"
+ }
+ Frame {
+ msec: 1696
+ hash: "1fa8544c48a476764f4f8278c14b651d"
+ }
+ Frame {
+ msec: 1712
+ hash: "f8f06ece30f690deeba5999ce63bf40b"
+ }
+ Frame {
+ msec: 1728
+ hash: "885b230f4b2fe380c7cf68955940d206"
+ }
+ Frame {
+ msec: 1744
+ hash: "d0fc5aa4df46099bb46a1d7db30baa09"
+ }
+ Frame {
+ msec: 1760
+ hash: "8fa7fe5197cbe1ff67f8a2c47f1f0740"
+ }
+ Frame {
+ msec: 1776
+ hash: "aa3b3b03460daf54f085551e1a46c08b"
+ }
+ Frame {
+ msec: 1792
+ hash: "35a1728a2430027a9474fb7d61090643"
+ }
+ Frame {
+ msec: 1808
+ hash: "2b1cff3986b8b03f1061176a4722b0f9"
+ }
+ Frame {
+ msec: 1824
+ hash: "8047be1b35ee3d5078a68c6cdc35eeb7"
+ }
+ Frame {
+ msec: 1840
+ hash: "7f7afa48bb7d612b354c8488e72c8339"
+ }
+ Frame {
+ msec: 1856
+ hash: "691a876caefce9aa0f5140c17059b8f4"
+ }
+ Frame {
+ msec: 1872
+ hash: "903bec66e47db766dc431f060726988c"
+ }
+ Frame {
+ msec: 1888
+ hash: "f13593fc891f0b050c01b61963019da1"
+ }
+ Frame {
+ msec: 1904
+ hash: "aa00de965bdb370a5974b195c3fb38af"
+ }
+ Frame {
+ msec: 1920
+ image: "parentAction.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "168d3e27261c0943e6262b6be27adfb0"
+ }
+ Frame {
+ msec: 1952
+ hash: "6fafebd0b396e7c0a78c767c6af936ba"
+ }
+ Frame {
+ msec: 1968
+ hash: "827e3a3fcd6fd8588e9fcc043769b3a8"
+ }
+ Frame {
+ msec: 1984
+ hash: "155329bf1c1a6f6c37bf7e6e8a92c59b"
+ }
+ Frame {
+ msec: 2000
+ hash: "d3008d1e7cee5170171699ef6fb9aa81"
+ }
+ Frame {
+ msec: 2016
+ hash: "5c1244e7806e131a6063f22a66e4eb12"
+ }
+ Frame {
+ msec: 2032
+ hash: "fcd6b372229a6cf14face81e9d614456"
+ }
+ Frame {
+ msec: 2048
+ hash: "bf1a375a81bf43c5671cccc62e9a0462"
+ }
+ Frame {
+ msec: 2064
+ hash: "0e22404508470baaa6621f37361951fa"
+ }
+ Frame {
+ msec: 2080
+ hash: "45046f28c103caa161e41861f71731c4"
+ }
+ Frame {
+ msec: 2096
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2112
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2128
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2144
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2160
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2176
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2192
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2208
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2224
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2240
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2256
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2272
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2288
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2304
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2320
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2336
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2352
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2368
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2384
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2400
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2416
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2432
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2448
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2464
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2480
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2496
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2512
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2528
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2544
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2560
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2576
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2592
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2608
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2624
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2640
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2656
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2672
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2688
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2704
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2720
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2736
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2752
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 150; y: 274
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2768
+ hash: "7a92731c713470a2b2c91fd6b83447de"
+ }
+ Frame {
+ msec: 2784
+ hash: "44a0b46c21bd4c76d44883ba146e3614"
+ }
+ Frame {
+ msec: 2800
+ hash: "2224abc3333a2bc5fa1cf3c4e8d6a6f9"
+ }
+ Frame {
+ msec: 2816
+ hash: "ea9c05c0295a300e21aacbdfd5b4968e"
+ }
+ Frame {
+ msec: 2832
+ hash: "e630e2893f89a6ae536bcbd1a084af07"
+ }
+ Frame {
+ msec: 2848
+ hash: "af56f1e79eb3746efb9e4bcbc3fbced8"
+ }
+ Frame {
+ msec: 2864
+ hash: "96be8c3ba0d7a85c6f6df877b869b563"
+ }
+ Frame {
+ msec: 2880
+ image: "parentAction.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "603d8684cb6f097e3ab2a2e5ef053112"
+ }
+ Frame {
+ msec: 2912
+ hash: "0433d242d1dd40a3792f55f807ebbff4"
+ }
+ Frame {
+ msec: 2928
+ hash: "1190067cacc7361f6cfe09f153c7a07e"
+ }
+ Frame {
+ msec: 2944
+ hash: "98e917880471511122847ad8a406e3a3"
+ }
+ Frame {
+ msec: 2960
+ hash: "fff06869074a3a6c5823ed3fb6fa7a43"
+ }
+ Frame {
+ msec: 2976
+ hash: "602d95daee8f160a0fd784931d0a06bd"
+ }
+ Frame {
+ msec: 2992
+ hash: "f7e466bbd52f40e88ff567758f4db835"
+ }
+ Frame {
+ msec: 3008
+ hash: "54417a4c4fb71d458439ad2e2126f8e1"
+ }
+ Frame {
+ msec: 3024
+ hash: "fe150dd5056b9dbf1cd0b196e9a7a47b"
+ }
+ Frame {
+ msec: 3040
+ hash: "1384c871bead85916f7bfcdebc370697"
+ }
+ Frame {
+ msec: 3056
+ hash: "5f13339cc0e604b75a9d1d85342fa717"
+ }
+ Frame {
+ msec: 3072
+ hash: "655069d61b7a44e729a2cbb33d683c3e"
+ }
+ Frame {
+ msec: 3088
+ hash: "2324e9e4a02e41855b066983dbf0e61d"
+ }
+ Frame {
+ msec: 3104
+ hash: "0217baf091325b95c033ba073bd68ce5"
+ }
+ Frame {
+ msec: 3120
+ hash: "c27854c3af5b58db85846a1762ab18ba"
+ }
+ Frame {
+ msec: 3136
+ hash: "45246ee6383ceb6260f84571a885ba90"
+ }
+ Frame {
+ msec: 3152
+ hash: "d82ded86f093d1a376994cacf43d0343"
+ }
+ Frame {
+ msec: 3168
+ hash: "c9179d30f80c6101bca2bed40d6a859f"
+ }
+ Frame {
+ msec: 3184
+ hash: "a63e032d20a9d985c6c345434d98a364"
+ }
+ Frame {
+ msec: 3200
+ hash: "fc7d6797ce15edf7fadb9dae691ecd5c"
+ }
+ Frame {
+ msec: 3216
+ hash: "76cf37ad8c50fed8b1900784b647819c"
+ }
+ Frame {
+ msec: 3232
+ hash: "256aab3690c9ba928bb4d4dd3bbfc756"
+ }
+ Frame {
+ msec: 3248
+ hash: "90cab52fdefbae4e7d0f0f93b46ebeb0"
+ }
+ Frame {
+ msec: 3264
+ hash: "badb5103bf826dc467f6e620cc2b47be"
+ }
+ Frame {
+ msec: 3280
+ hash: "e7d0e437de5ebc0fa07b2a4ef11159cb"
+ }
+ Frame {
+ msec: 3296
+ hash: "5931b1c3932ab91446324165d7e2603a"
+ }
+ Frame {
+ msec: 3312
+ hash: "ce1808db90ba955ab3cb845500f4c013"
+ }
+ Frame {
+ msec: 3328
+ hash: "142f8a440d1fe2d868f47ba3006de9d7"
+ }
+ Frame {
+ msec: 3344
+ hash: "10d32a6cc90319ea66d7f2c1241590ce"
+ }
+ Frame {
+ msec: 3360
+ hash: "7f633559d715396e6de451b3dd2fadbd"
+ }
+ Frame {
+ msec: 3376
+ hash: "d44590ae51ceef5e082747c44bc41be9"
+ }
+ Frame {
+ msec: 3392
+ hash: "2b498181668fb1fbf65294d575654929"
+ }
+ Frame {
+ msec: 3408
+ hash: "7efeeffd08e4de440da83511313de729"
+ }
+ Frame {
+ msec: 3424
+ hash: "8de2331393d1e712192d11ed096836d3"
+ }
+ Frame {
+ msec: 3440
+ hash: "fa9381ef2e295865a9b8cb9b36a0eacf"
+ }
+ Frame {
+ msec: 3456
+ hash: "97debc4432c5ecb7f606a81e5411b02c"
+ }
+ Frame {
+ msec: 3472
+ hash: "eb4c1bb1f4398e3c18182c28a015be76"
+ }
+ Frame {
+ msec: 3488
+ hash: "a976aa509f4c6f309d9a6011eeae02aa"
+ }
+ Frame {
+ msec: 3504
+ hash: "457de7ee05e0ef0ef120a3d4e371c02e"
+ }
+ Frame {
+ msec: 3520
+ hash: "0c01f9f150fe33155fa20703735a6d27"
+ }
+ Frame {
+ msec: 3536
+ hash: "5af4f80624082a264010247ea8630a1a"
+ }
+ Frame {
+ msec: 3552
+ hash: "b23a1191d149549fa29a61b6dc70f037"
+ }
+ Frame {
+ msec: 3568
+ hash: "e00fb32cb13b1347e4b7b9fdbcca68e5"
+ }
+ Frame {
+ msec: 3584
+ hash: "fef0503c82f253f8bc3fb3e705a98aa7"
+ }
+ Frame {
+ msec: 3600
+ hash: "7a9beca28340d2aa89da5e05f5ac2a55"
+ }
+ Frame {
+ msec: 3616
+ hash: "f3c57ea07ab486ffa1f46da60de0b8f1"
+ }
+ Frame {
+ msec: 3632
+ hash: "ef0a4ad9ac339fd6ea50dbe6baa9387f"
+ }
+ Frame {
+ msec: 3648
+ hash: "1b317a9eb4ce022f005d551546c688a4"
+ }
+ Frame {
+ msec: 3664
+ hash: "628e912a4a26800b9b7b5e60e60e3a7d"
+ }
+ Frame {
+ msec: 3680
+ hash: "3587b75e4d834a88729754d2c2a4b193"
+ }
+ Frame {
+ msec: 3696
+ hash: "084bc1360a38123589baec5aae15b4ff"
+ }
+ Frame {
+ msec: 3712
+ hash: "47f0f6c3cdf456826a6fd6846e58dcc8"
+ }
+ Frame {
+ msec: 3728
+ hash: "ed982c4c3ebd132baaaf43efad40a3f7"
+ }
+ Frame {
+ msec: 3744
+ hash: "d7ddce47c23fada4c69d53d934582d71"
+ }
+ Frame {
+ msec: 3760
+ hash: "74f2f911bee26c4c551f4c70596753ae"
+ }
+ Frame {
+ msec: 3776
+ hash: "3ed7cbf10dfce3a485d7878766cf9da6"
+ }
+ Frame {
+ msec: 3792
+ hash: "87a74257551ab6c7fcfe05e815482ae9"
+ }
+ Frame {
+ msec: 3808
+ hash: "4f63e4904e97d4ce832b20b7317a9958"
+ }
+ Frame {
+ msec: 3824
+ hash: "f912da8781e547c6e28890655c1b8884"
+ }
+ Frame {
+ msec: 3840
+ image: "parentAction.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "faa640ccf993324400254ffb862ac279"
+ }
+ Frame {
+ msec: 3872
+ hash: "b67f342424d1b9a364b09da8994fcd6b"
+ }
+ Frame {
+ msec: 3888
+ hash: "b2407732194c1e0c2a9bfb379b94b562"
+ }
+ Frame {
+ msec: 3904
+ hash: "55733608d0302ef90c124322ac6d8dc6"
+ }
+ Frame {
+ msec: 3920
+ hash: "734f5b628a26d3d7c91ee84fb26d5b5f"
+ }
+ Frame {
+ msec: 3936
+ hash: "27839fefa4a218cd77843358392bb874"
+ }
+ Frame {
+ msec: 3952
+ hash: "8cac19559d37bd2b581cef0a4c707753"
+ }
+ Frame {
+ msec: 3968
+ hash: "91422870aa1471571e7dd8ff5103f76c"
+ }
+ Frame {
+ msec: 3984
+ hash: "7156166d5f8d13483467ef515627c95d"
+ }
+ Frame {
+ msec: 4000
+ hash: "6028e8374c2ce42a9a9e85b4a8b53027"
+ }
+ Frame {
+ msec: 4016
+ hash: "17c99592be58d2e03f9f173c47c0649b"
+ }
+ Frame {
+ msec: 4032
+ hash: "6084b53186c6a7eda38ac7fa34bf45ce"
+ }
+ Frame {
+ msec: 4048
+ hash: "e82131a8a5a06519f49308bbc25738cf"
+ }
+ Frame {
+ msec: 4064
+ hash: "77bdb69cbe55d9c503c6aa1c0f974d87"
+ }
+ Frame {
+ msec: 4080
+ hash: "b2346ec5d376651347281d5fb00fc4d7"
+ }
+ Frame {
+ msec: 4096
+ hash: "36a3b72c9d7f09795c546855a269801d"
+ }
+ Frame {
+ msec: 4112
+ hash: "4e5478b33baca797f3f8f72c2c6c51ad"
+ }
+ Frame {
+ msec: 4128
+ hash: "e59d12be3ed1f58de010d385ddfe78e5"
+ }
+ Frame {
+ msec: 4144
+ hash: "9674106a146effd47c2724a2dd82ae84"
+ }
+ Frame {
+ msec: 4160
+ hash: "862cec781f169f713032e6d52d3616ce"
+ }
+ Frame {
+ msec: 4176
+ hash: "c8d47bdfb6518ef4827677023313d559"
+ }
+ Frame {
+ msec: 4192
+ hash: "19413931b3e788067dfaef39b47d30ff"
+ }
+ Frame {
+ msec: 4208
+ hash: "600e426532c0348cd622257b0773efd5"
+ }
+ Frame {
+ msec: 4224
+ hash: "6d975e259d4efa108375d271451531c1"
+ }
+ Frame {
+ msec: 4240
+ hash: "50b0da4848564c063694202ce16ea808"
+ }
+ Frame {
+ msec: 4256
+ hash: "0a9450739031f680735b5210e6a30c3f"
+ }
+ Frame {
+ msec: 4272
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4288
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4304
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4320
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4336
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4352
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4368
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4384
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4400
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4416
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4432
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4448
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4464
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4480
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4496
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4512
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4528
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4544
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4560
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4576
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4592
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4608
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4624
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4640
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4656
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4672
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4688
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+ Frame {
+ msec: 4704
+ hash: "23ce049cd7e715c28f5845fd1a1fc195"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/parentAction/parentAction.qml b/tests/auto/declarative/visual/animation/parentAction/parentAction.qml
new file mode 100644
index 0000000..1e3f402
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/parentAction/parentAction.qml
@@ -0,0 +1,55 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 400
+ Item {
+ scale: .5
+ rotation: 15
+ transformOrigin: "Center"
+ x: 10; y: 10
+ Rectangle {
+ id: myRect
+ x: 5
+ width: 100; height: 100
+ transformOrigin: "BottomLeft"
+ color: "red"
+ }
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ Item {
+ x: 200; y: 200
+ rotation: 52;
+ scale: 2
+ Item {
+ id: newParent
+ x: 100; y: 100
+ }
+ }
+
+ states: State {
+ name: "moved"
+ when: clickable.pressed
+ ParentChange {
+ target: myRect
+ parent: newParent
+ }
+ PropertyChanges {
+ target: myRect
+ rotation: -52
+ scale: 1
+ color: "blue"
+ }
+ }
+
+ transitions: Transition {
+ SequentialAnimation {
+ ColorAnimation { duration: 500}
+ ParentAction {}
+ NumberAnimation { matchProperties: "rotation, scale"; duration: 1000 }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.0.png b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.0.png
new file mode 100644
index 0000000..693a794
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.1.png b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.1.png
new file mode 100644
index 0000000..06d43f1
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.2.png b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.2.png
new file mode 100644
index 0000000..e619baf
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.3.png b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.3.png
new file mode 100644
index 0000000..30c7671
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.4.png b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.4.png
new file mode 100644
index 0000000..132803c
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.5.png b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.5.png
new file mode 100644
index 0000000..8372bc3
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.qml b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.qml
new file mode 100644
index 0000000..73c6542
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/data/pauseAnimation.qml
@@ -0,0 +1,1619 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 32
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 48
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 64
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 80
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 96
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 112
+ hash: "336d31586171f22d541b989d24b95cbb"
+ }
+ Frame {
+ msec: 128
+ hash: "6d63fb5c8a80f0280e88b2cdf8641bb9"
+ }
+ Frame {
+ msec: 144
+ hash: "ef8941674cb61f54853dc33652bb854e"
+ }
+ Frame {
+ msec: 160
+ hash: "b3f4a2165ec1ee971542b8ef89656cea"
+ }
+ Frame {
+ msec: 176
+ hash: "af3120fe262d2489c0ed33fbbee1549f"
+ }
+ Frame {
+ msec: 192
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 208
+ hash: "21f0b0437a999bbde66a913032d495c2"
+ }
+ Frame {
+ msec: 224
+ hash: "0809d32d5bc1bfce199b1f39a1c68d4f"
+ }
+ Frame {
+ msec: 240
+ hash: "022137587b39f5123835482178a1f1cf"
+ }
+ Frame {
+ msec: 256
+ hash: "97566ce9558d13ea0780bce233097b27"
+ }
+ Frame {
+ msec: 272
+ hash: "96d79b07da105b7f631ed61582b26f7e"
+ }
+ Frame {
+ msec: 288
+ hash: "f4732ff2df93fe67cb850dec34184924"
+ }
+ Frame {
+ msec: 304
+ hash: "054e6e52f74a3e24f04e6ad0071f79f8"
+ }
+ Frame {
+ msec: 320
+ hash: "f541af93a9fde62e4bd1c91d30f91e65"
+ }
+ Frame {
+ msec: 336
+ hash: "c4f844ee71f23635bb3ec7375f6a134f"
+ }
+ Frame {
+ msec: 352
+ hash: "3e52e06db2bf78762bb9816fe6b105d9"
+ }
+ Frame {
+ msec: 368
+ hash: "d9604be23a91327e6ab454609a9d4a13"
+ }
+ Frame {
+ msec: 384
+ hash: "dc98a9bdd99367c1e9b838d4be489dcc"
+ }
+ Frame {
+ msec: 400
+ hash: "e87b00bfc2c2a75a4234ec02a057ad3a"
+ }
+ Frame {
+ msec: 416
+ hash: "5be4f5c67941efb6fcea363c79f1e321"
+ }
+ Frame {
+ msec: 432
+ hash: "6cc9de62a0c8fa5e42eac1b01e99ac32"
+ }
+ Frame {
+ msec: 448
+ hash: "62a7133012348f2ec3a388fb685ecc3f"
+ }
+ Frame {
+ msec: 464
+ hash: "4ac43a03cc6f2020ab5f894d704092ac"
+ }
+ Frame {
+ msec: 480
+ hash: "c1a7b7d6d64ac5584c073c2881290696"
+ }
+ Frame {
+ msec: 496
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 512
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 528
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 544
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 560
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 576
+ hash: "c1a7b7d6d64ac5584c073c2881290696"
+ }
+ Frame {
+ msec: 592
+ hash: "c1a7b7d6d64ac5584c073c2881290696"
+ }
+ Frame {
+ msec: 608
+ hash: "4ac43a03cc6f2020ab5f894d704092ac"
+ }
+ Frame {
+ msec: 624
+ hash: "4ac43a03cc6f2020ab5f894d704092ac"
+ }
+ Frame {
+ msec: 640
+ hash: "ffd39c1122fe2f7877ef30591b539b40"
+ }
+ Frame {
+ msec: 656
+ hash: "62a7133012348f2ec3a388fb685ecc3f"
+ }
+ Frame {
+ msec: 672
+ hash: "45281a70021f81dbef30334b1480da1b"
+ }
+ Frame {
+ msec: 688
+ hash: "6cc9de62a0c8fa5e42eac1b01e99ac32"
+ }
+ Frame {
+ msec: 704
+ hash: "79ec710576427df73dd03f39fba6e2eb"
+ }
+ Frame {
+ msec: 720
+ hash: "5be4f5c67941efb6fcea363c79f1e321"
+ }
+ Frame {
+ msec: 736
+ hash: "7d9096b1eb940c82a37baf39ef3ccf3e"
+ }
+ Frame {
+ msec: 752
+ hash: "e87b00bfc2c2a75a4234ec02a057ad3a"
+ }
+ Frame {
+ msec: 768
+ hash: "da60100dc55023c3bab367d97c8f6a85"
+ }
+ Frame {
+ msec: 784
+ hash: "dc98a9bdd99367c1e9b838d4be489dcc"
+ }
+ Frame {
+ msec: 800
+ hash: "3f869538028a09020d5e8f528f4fb119"
+ }
+ Frame {
+ msec: 816
+ hash: "9650fd0364c01b11e4f5dcce51d008af"
+ }
+ Frame {
+ msec: 832
+ hash: "2cb09d9655ecc30ae6a591b28c0d355c"
+ }
+ Frame {
+ msec: 848
+ hash: "4db9bc6c11caf1d77794c2eabb62a44e"
+ }
+ Frame {
+ msec: 864
+ hash: "ce2b5dd7418868acf86fea6ad19cc0c5"
+ }
+ Frame {
+ msec: 880
+ hash: "7c27ef654e645679c90520d6cf00b0c4"
+ }
+ Frame {
+ msec: 896
+ hash: "ab3e211df3ef7f5f7a8d712edc891c0f"
+ }
+ Frame {
+ msec: 912
+ hash: "19d2ae617a49b57dd012677e2834469c"
+ }
+ Frame {
+ msec: 928
+ hash: "5025eb75c88f0760f637e0342b7f88a2"
+ }
+ Frame {
+ msec: 944
+ hash: "005acbef952a8ee536e6308a48223e65"
+ }
+ Frame {
+ msec: 960
+ image: "pauseAnimation.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "5f18a81707f23d377e81a27c1fc41ce9"
+ }
+ Frame {
+ msec: 992
+ hash: "bcc35497884c158396c7f60759d1fda4"
+ }
+ Frame {
+ msec: 1008
+ hash: "7a4528b000a4ea142d1c77407fa1f581"
+ }
+ Frame {
+ msec: 1024
+ hash: "ba967a7d810a4531e577e5f6bd2def33"
+ }
+ Frame {
+ msec: 1040
+ hash: "f5afd9cf8ffe27e9992454b9e68688cb"
+ }
+ Frame {
+ msec: 1056
+ hash: "51d475c7f64a86d3a18fb115297a7b6b"
+ }
+ Frame {
+ msec: 1072
+ hash: "49f5d6fd45c195a8d245b7fefc1277ab"
+ }
+ Frame {
+ msec: 1088
+ hash: "f9b0b278659e3a0f78611e6b7f0f2176"
+ }
+ Frame {
+ msec: 1104
+ hash: "0809d32d5bc1bfce199b1f39a1c68d4f"
+ }
+ Frame {
+ msec: 1120
+ hash: "b7208d103b63a936dff8dd8ed224237f"
+ }
+ Frame {
+ msec: 1136
+ hash: "a57c81049b0dc68090ec7c3327b9922c"
+ }
+ Frame {
+ msec: 1152
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 1168
+ hash: "af3120fe262d2489c0ed33fbbee1549f"
+ }
+ Frame {
+ msec: 1184
+ hash: "0c20d12464abbdc45041ea5d9f2719b1"
+ }
+ Frame {
+ msec: 1200
+ hash: "dd60cbaff6f34027474e92315dbc0ebc"
+ }
+ Frame {
+ msec: 1216
+ hash: "336d31586171f22d541b989d24b95cbb"
+ }
+ Frame {
+ msec: 1232
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 1248
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 1264
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 1280
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 1296
+ hash: "336d31586171f22d541b989d24b95cbb"
+ }
+ Frame {
+ msec: 1312
+ hash: "f0d8132489c2f2ef760e905b3c093726"
+ }
+ Frame {
+ msec: 1328
+ hash: "6d63fb5c8a80f0280e88b2cdf8641bb9"
+ }
+ Frame {
+ msec: 1344
+ hash: "dd60cbaff6f34027474e92315dbc0ebc"
+ }
+ Frame {
+ msec: 1360
+ hash: "ef8941674cb61f54853dc33652bb854e"
+ }
+ Frame {
+ msec: 1376
+ hash: "bc426fb7c31751665b0d3f16e2cb0173"
+ }
+ Frame {
+ msec: 1392
+ hash: "0c20d12464abbdc45041ea5d9f2719b1"
+ }
+ Frame {
+ msec: 1408
+ hash: "53ae93140252373eaa4d9da73756bd8e"
+ }
+ Frame {
+ msec: 1424
+ hash: "721d7061811b5439c2e8e395917494bc"
+ }
+ Frame {
+ msec: 1440
+ hash: "af3120fe262d2489c0ed33fbbee1549f"
+ }
+ Frame {
+ msec: 1456
+ hash: "a8b624ebfc9ab713d1ce55f318a6e90d"
+ }
+ Frame {
+ msec: 1472
+ hash: "a88a8129259f86df5a73addc3649ad37"
+ }
+ Frame {
+ msec: 1488
+ hash: "a88a8129259f86df5a73addc3649ad37"
+ }
+ Frame {
+ msec: 1504
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 1520
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 1536
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 1552
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 1568
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 1584
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 1600
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 1616
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 1632
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 1648
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 1664
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 1680
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 1696
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 1712
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 1728
+ hash: "a88a8129259f86df5a73addc3649ad37"
+ }
+ Frame {
+ msec: 1744
+ hash: "a8b624ebfc9ab713d1ce55f318a6e90d"
+ }
+ Frame {
+ msec: 1760
+ hash: "a8b624ebfc9ab713d1ce55f318a6e90d"
+ }
+ Frame {
+ msec: 1776
+ hash: "af3120fe262d2489c0ed33fbbee1549f"
+ }
+ Frame {
+ msec: 1792
+ hash: "721d7061811b5439c2e8e395917494bc"
+ }
+ Frame {
+ msec: 1808
+ hash: "b3f4a2165ec1ee971542b8ef89656cea"
+ }
+ Frame {
+ msec: 1824
+ hash: "0c20d12464abbdc45041ea5d9f2719b1"
+ }
+ Frame {
+ msec: 1840
+ hash: "bc426fb7c31751665b0d3f16e2cb0173"
+ }
+ Frame {
+ msec: 1856
+ hash: "ef8941674cb61f54853dc33652bb854e"
+ }
+ Frame {
+ msec: 1872
+ hash: "dd60cbaff6f34027474e92315dbc0ebc"
+ }
+ Frame {
+ msec: 1888
+ hash: "6d63fb5c8a80f0280e88b2cdf8641bb9"
+ }
+ Frame {
+ msec: 1904
+ hash: "e74fe4a6bd92cbe8629c8bc8a870104d"
+ }
+ Frame {
+ msec: 1920
+ image: "pauseAnimation.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 1952
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 1968
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 1984
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2000
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 2016
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 2032
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 2048
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 2064
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 2080
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 2096
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2112
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2128
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2144
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2160
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2176
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2192
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2208
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 2224
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 2240
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 2256
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 2272
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 2288
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 2304
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 2320
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2336
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2352
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2368
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2384
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2400
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2416
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 2432
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 2448
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2464
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2480
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2496
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 2512
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2528
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2544
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2560
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2576
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2592
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2608
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2624
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2640
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2656
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2672
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2688
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2704
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2720
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2736
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2752
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2768
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2784
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2800
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2816
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2832
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2848
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2864
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2880
+ image: "pauseAnimation.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2912
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2928
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2944
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2960
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2976
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 2992
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3008
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3024
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3040
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3056
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3072
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3088
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3104
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3120
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3136
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3152
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3168
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3184
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3200
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3216
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3232
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3248
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3264
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3280
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3296
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3312
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3328
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3344
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3360
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3376
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3392
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3408
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3424
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3440
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3456
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3472
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3488
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3504
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3520
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3536
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 3552
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 3568
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 3584
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 3600
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 3616
+ hash: "e74fe4a6bd92cbe8629c8bc8a870104d"
+ }
+ Frame {
+ msec: 3632
+ hash: "e11455d4e23a5a865e222a7aba4ba4f9"
+ }
+ Frame {
+ msec: 3648
+ hash: "8757668e56be6449ec375f0b8fed1be3"
+ }
+ Frame {
+ msec: 3664
+ hash: "53ae93140252373eaa4d9da73756bd8e"
+ }
+ Frame {
+ msec: 3680
+ hash: "a88a8129259f86df5a73addc3649ad37"
+ }
+ Frame {
+ msec: 3696
+ hash: "630d90eef2673a69e8ebc4ef1ba40e81"
+ }
+ Frame {
+ msec: 3712
+ hash: "b7208d103b63a936dff8dd8ed224237f"
+ }
+ Frame {
+ msec: 3728
+ hash: "1516c3547c7cf64832b3bc7da7c44521"
+ }
+ Frame {
+ msec: 3744
+ hash: "49f5d6fd45c195a8d245b7fefc1277ab"
+ }
+ Frame {
+ msec: 3760
+ hash: "f5afd9cf8ffe27e9992454b9e68688cb"
+ }
+ Frame {
+ msec: 3776
+ hash: "7a4528b000a4ea142d1c77407fa1f581"
+ }
+ Frame {
+ msec: 3792
+ hash: "5f18a81707f23d377e81a27c1fc41ce9"
+ }
+ Frame {
+ msec: 3808
+ hash: "005acbef952a8ee536e6308a48223e65"
+ }
+ Frame {
+ msec: 3824
+ hash: "85c135ef72d3d25658a3663e69ffb7c2"
+ }
+ Frame {
+ msec: 3840
+ image: "pauseAnimation.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "20258f07c613958c32f783466771391a"
+ }
+ Frame {
+ msec: 3872
+ hash: "9650fd0364c01b11e4f5dcce51d008af"
+ }
+ Frame {
+ msec: 3888
+ hash: "f340cdf60c6d4c29d26b7202a093ec70"
+ }
+ Frame {
+ msec: 3904
+ hash: "d754d35d0793f9f7d4f6249a874e4c45"
+ }
+ Frame {
+ msec: 3920
+ hash: "79ec710576427df73dd03f39fba6e2eb"
+ }
+ Frame {
+ msec: 3936
+ hash: "45281a70021f81dbef30334b1480da1b"
+ }
+ Frame {
+ msec: 3952
+ hash: "ffd39c1122fe2f7877ef30591b539b40"
+ }
+ Frame {
+ msec: 3968
+ hash: "4ac43a03cc6f2020ab5f894d704092ac"
+ }
+ Frame {
+ msec: 3984
+ hash: "c1a7b7d6d64ac5584c073c2881290696"
+ }
+ Frame {
+ msec: 4000
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 4016
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 4032
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 4048
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 4064
+ hash: "29ece1bca4d21fb5862091317d430a13"
+ }
+ Frame {
+ msec: 4080
+ hash: "c1a7b7d6d64ac5584c073c2881290696"
+ }
+ Frame {
+ msec: 4096
+ hash: "c1a7b7d6d64ac5584c073c2881290696"
+ }
+ Frame {
+ msec: 4112
+ hash: "4ac43a03cc6f2020ab5f894d704092ac"
+ }
+ Frame {
+ msec: 4128
+ hash: "4ac43a03cc6f2020ab5f894d704092ac"
+ }
+ Frame {
+ msec: 4144
+ hash: "ffd39c1122fe2f7877ef30591b539b40"
+ }
+ Frame {
+ msec: 4160
+ hash: "62a7133012348f2ec3a388fb685ecc3f"
+ }
+ Frame {
+ msec: 4176
+ hash: "45281a70021f81dbef30334b1480da1b"
+ }
+ Frame {
+ msec: 4192
+ hash: "6cc9de62a0c8fa5e42eac1b01e99ac32"
+ }
+ Frame {
+ msec: 4208
+ hash: "79ec710576427df73dd03f39fba6e2eb"
+ }
+ Frame {
+ msec: 4224
+ hash: "5be4f5c67941efb6fcea363c79f1e321"
+ }
+ Frame {
+ msec: 4240
+ hash: "7d9096b1eb940c82a37baf39ef3ccf3e"
+ }
+ Frame {
+ msec: 4256
+ hash: "e87b00bfc2c2a75a4234ec02a057ad3a"
+ }
+ Frame {
+ msec: 4272
+ hash: "da60100dc55023c3bab367d97c8f6a85"
+ }
+ Frame {
+ msec: 4288
+ hash: "dc98a9bdd99367c1e9b838d4be489dcc"
+ }
+ Frame {
+ msec: 4304
+ hash: "b2c778a5eff5f01edc54f03d8b4de8c7"
+ }
+ Frame {
+ msec: 4320
+ hash: "9650fd0364c01b11e4f5dcce51d008af"
+ }
+ Frame {
+ msec: 4336
+ hash: "2cb09d9655ecc30ae6a591b28c0d355c"
+ }
+ Frame {
+ msec: 4352
+ hash: "4db9bc6c11caf1d77794c2eabb62a44e"
+ }
+ Frame {
+ msec: 4368
+ hash: "ce2b5dd7418868acf86fea6ad19cc0c5"
+ }
+ Frame {
+ msec: 4384
+ hash: "c4f844ee71f23635bb3ec7375f6a134f"
+ }
+ Frame {
+ msec: 4400
+ hash: "4e1fda8a0495ef968c1cffb1257426d7"
+ }
+ Frame {
+ msec: 4416
+ hash: "19d2ae617a49b57dd012677e2834469c"
+ }
+ Frame {
+ msec: 4432
+ hash: "f438e8d2c16b5de677924c8411219b19"
+ }
+ Frame {
+ msec: 4448
+ hash: "005acbef952a8ee536e6308a48223e65"
+ }
+ Frame {
+ msec: 4464
+ hash: "87b71778d52cd8563d171151d4d32407"
+ }
+ Frame {
+ msec: 4480
+ hash: "691cd8bf5c7802ff6c5024827a379fc6"
+ }
+ Frame {
+ msec: 4496
+ hash: "ab442c0173c3d221b6782d28001dac77"
+ }
+ Frame {
+ msec: 4512
+ hash: "6f886d4538704c2fad4d84c68214109f"
+ }
+ Frame {
+ msec: 4528
+ hash: "56d39f233fae41c60499d6161f891cbc"
+ }
+ Frame {
+ msec: 4544
+ hash: "95d987c3fd1352fb81c42c63634fe53b"
+ }
+ Frame {
+ msec: 4560
+ hash: "96dc84c0c548021910e7c5b580179054"
+ }
+ Frame {
+ msec: 4576
+ hash: "ddb71cbd57f6e43744d533d4f72b08db"
+ }
+ Frame {
+ msec: 4592
+ hash: "f7ab4b197bea455b22f259913438d207"
+ }
+ Frame {
+ msec: 4608
+ hash: "2ad64cb01c9d50e0118d5ece0a644df2"
+ }
+ Frame {
+ msec: 4624
+ hash: "6579681c59dd571df0ee4429d74fb5c7"
+ }
+ Frame {
+ msec: 4640
+ hash: "630d90eef2673a69e8ebc4ef1ba40e81"
+ }
+ Frame {
+ msec: 4656
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 4672
+ hash: "721d7061811b5439c2e8e395917494bc"
+ }
+ Frame {
+ msec: 4688
+ hash: "bc426fb7c31751665b0d3f16e2cb0173"
+ }
+ Frame {
+ msec: 4704
+ hash: "e11455d4e23a5a865e222a7aba4ba4f9"
+ }
+ Frame {
+ msec: 4720
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 4736
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 4752
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 4768
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 4784
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 4800
+ image: "pauseAnimation.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "f0d8132489c2f2ef760e905b3c093726"
+ }
+ Frame {
+ msec: 4832
+ hash: "e11455d4e23a5a865e222a7aba4ba4f9"
+ }
+ Frame {
+ msec: 4848
+ hash: "dd60cbaff6f34027474e92315dbc0ebc"
+ }
+ Frame {
+ msec: 4864
+ hash: "8757668e56be6449ec375f0b8fed1be3"
+ }
+ Frame {
+ msec: 4880
+ hash: "bc426fb7c31751665b0d3f16e2cb0173"
+ }
+ Frame {
+ msec: 4896
+ hash: "b3f4a2165ec1ee971542b8ef89656cea"
+ }
+ Frame {
+ msec: 4912
+ hash: "53ae93140252373eaa4d9da73756bd8e"
+ }
+ Frame {
+ msec: 4928
+ hash: "721d7061811b5439c2e8e395917494bc"
+ }
+ Frame {
+ msec: 4944
+ hash: "af3120fe262d2489c0ed33fbbee1549f"
+ }
+ Frame {
+ msec: 4960
+ hash: "a8b624ebfc9ab713d1ce55f318a6e90d"
+ }
+ Frame {
+ msec: 4976
+ hash: "a88a8129259f86df5a73addc3649ad37"
+ }
+ Frame {
+ msec: 4992
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 5008
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 5024
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 5040
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 5056
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 5072
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 5088
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 5104
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 5120
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 5136
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 5152
+ hash: "1373545e43fff7251cec9e8375ea267f"
+ }
+ Frame {
+ msec: 5168
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 5184
+ hash: "e553f365912586c6408c8c53b1b7d118"
+ }
+ Frame {
+ msec: 5200
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 5216
+ hash: "3db5e30ef19ea693c21ccf72892c4390"
+ }
+ Frame {
+ msec: 5232
+ hash: "a88a8129259f86df5a73addc3649ad37"
+ }
+ Frame {
+ msec: 5248
+ hash: "a8b624ebfc9ab713d1ce55f318a6e90d"
+ }
+ Frame {
+ msec: 5264
+ hash: "af3120fe262d2489c0ed33fbbee1549f"
+ }
+ Frame {
+ msec: 5280
+ hash: "721d7061811b5439c2e8e395917494bc"
+ }
+ Frame {
+ msec: 5296
+ hash: "53ae93140252373eaa4d9da73756bd8e"
+ }
+ Frame {
+ msec: 5312
+ hash: "b3f4a2165ec1ee971542b8ef89656cea"
+ }
+ Frame {
+ msec: 5328
+ hash: "0c20d12464abbdc45041ea5d9f2719b1"
+ }
+ Frame {
+ msec: 5344
+ hash: "8757668e56be6449ec375f0b8fed1be3"
+ }
+ Frame {
+ msec: 5360
+ hash: "ef8941674cb61f54853dc33652bb854e"
+ }
+ Frame {
+ msec: 5376
+ hash: "e11455d4e23a5a865e222a7aba4ba4f9"
+ }
+ Frame {
+ msec: 5392
+ hash: "6d63fb5c8a80f0280e88b2cdf8641bb9"
+ }
+ Frame {
+ msec: 5408
+ hash: "e74fe4a6bd92cbe8629c8bc8a870104d"
+ }
+ Frame {
+ msec: 5424
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5440
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 5456
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 5472
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 5488
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5504
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 5520
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 5536
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 5552
+ hash: "ce57e27af329eba4fac3ab891f0407ce"
+ }
+ Frame {
+ msec: 5568
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 5584
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 5600
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5616
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5632
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5648
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5664
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5680
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5696
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5712
+ hash: "3042003c067b257de2cb32f650dde693"
+ }
+ Frame {
+ msec: 5728
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 5744
+ hash: "a725b59b4947357546bbfc7df3d830af"
+ }
+ Frame {
+ msec: 5760
+ image: "pauseAnimation.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 5792
+ hash: "41ba853c3403f68a23e708df82e21c53"
+ }
+ Frame {
+ msec: 5808
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 5824
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5840
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 5856
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5872
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5888
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5904
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5920
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 5936
+ hash: "dcf2867c127e041970047ec8f3edc04f"
+ }
+ Frame {
+ msec: 5952
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5968
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 5984
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 6000
+ hash: "675ebbdd22dd22ce45993df4af1acfe9"
+ }
+ Frame {
+ msec: 6016
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6032
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6048
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6064
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6080
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6096
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6112
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6128
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6144
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6160
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6176
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6192
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6208
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6224
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6240
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6256
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6272
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6288
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6304
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6320
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6336
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6352
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6368
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 6384
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6400
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+ Frame {
+ msec: 6416
+ hash: "a350b70c5238a340e85fd4a3ec0390a3"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/pauseAnimation.qml b/tests/auto/declarative/visual/animation/pauseAnimation/pauseAnimation.qml
new file mode 100644
index 0000000..f2e065d
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/pauseAnimation.qml
@@ -0,0 +1,29 @@
+import Qt 4.6
+
+Rectangle {
+ id: rect
+ width: 120
+ height: 200
+ color: "white"
+ Image {
+ id: img
+ source: "pics/qtlogo.png"
+ x: 60-width/2
+ y: 200-height
+ y: SequentialAnimation {
+ repeat: true
+ NumberAnimation {
+ to: 0; duration: 500
+ easing: "easeInOutQuad"
+ }
+ NumberAnimation {
+ to: 200-img.height
+ easing: "easeOutBounce"
+ duration: 2000
+ }
+ PauseAnimation {
+ duration: 1000
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/pauseAnimation/pics/qtlogo.png b/tests/auto/declarative/visual/animation/pauseAnimation/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/pauseAnimation/pics/qtlogo.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.0.png b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.0.png
new file mode 100644
index 0000000..64d6b06
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.1.png b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.1.png
new file mode 100644
index 0000000..f7fce15
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.2.png b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.2.png
new file mode 100644
index 0000000..3080df5
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.qml b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.qml
new file mode 100644
index 0000000..7c8c233
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/propertyAction/data/propertyAction.qml
@@ -0,0 +1,939 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 32
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 48
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 64
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 80
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 96
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 112
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 128
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 144
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 160
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 176
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 192
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 208
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 224
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 240
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 256
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 272
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 288
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 304
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 320
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 336
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 352
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 368
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 384
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 400
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 416
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 432
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 448
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 464
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 480
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 496
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 512
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 528
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 544
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 560
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 576
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 592
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 608
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 624
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 640
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 656
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 672
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 688
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 704
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 720
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 736
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 752
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 768
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 784
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 800
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 816
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 832
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 848
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 864
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 880
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 896
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 912
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 928
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 944
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 960
+ image: "propertyAction.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 992
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1008
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1024
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1040
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1056
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1072
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1088
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1104
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1120
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1136
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1152
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1168
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1184
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1200
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1216
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1232
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1248
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1264
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1280
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1296
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1312
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1328
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1344
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1360
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1376
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1392
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1408
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1424
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1440
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1456
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1472
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1488
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1504
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1520
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1536
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1552
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1568
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1584
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1600
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 109; y: 247
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1616
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1632
+ hash: "c91921dba899d7a86de3cd013773889f"
+ }
+ Frame {
+ msec: 1648
+ hash: "888c0fc86155e10b5fc577ef6ec5755a"
+ }
+ Frame {
+ msec: 1664
+ hash: "7fd61a8910bf7b0d2bf57653a268c5d8"
+ }
+ Frame {
+ msec: 1680
+ hash: "f42f5073f90a423adf011d0e168c8a9b"
+ }
+ Frame {
+ msec: 1696
+ hash: "a3d89deb6cfa2bbbaa1d7d5b5e5b48d5"
+ }
+ Frame {
+ msec: 1712
+ hash: "f10e997d7a17c18251a32d58b018105a"
+ }
+ Frame {
+ msec: 1728
+ hash: "09ffb57d5f67edfa34d6aad36a002554"
+ }
+ Frame {
+ msec: 1744
+ hash: "01f3a2f5b9815f1397a907b099339360"
+ }
+ Frame {
+ msec: 1760
+ hash: "58c0910c49748edd2ef8472960179472"
+ }
+ Frame {
+ msec: 1776
+ hash: "cc82c5f7f93c5bc1af1c6c509268566a"
+ }
+ Frame {
+ msec: 1792
+ hash: "3ef272c6439b85fbc166375d1b98403c"
+ }
+ Frame {
+ msec: 1808
+ hash: "98c576f0900e4b8752d1f951bb6bf391"
+ }
+ Frame {
+ msec: 1824
+ hash: "4d66dd64d8736ef50163e08723873478"
+ }
+ Frame {
+ msec: 1840
+ hash: "9a5d8455b6763456185625811253e0b1"
+ }
+ Frame {
+ msec: 1856
+ hash: "77e85731efa786a2492aae19a87523c6"
+ }
+ Frame {
+ msec: 1872
+ hash: "f3199d0c860f1236e0b9472bef8785bc"
+ }
+ Frame {
+ msec: 1888
+ hash: "f3199d0c860f1236e0b9472bef8785bc"
+ }
+ Frame {
+ msec: 1904
+ hash: "32ccdab249268b01d9f1658a736052f1"
+ }
+ Frame {
+ msec: 1920
+ image: "propertyAction.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "db3010ef552146df938c237f6c92bff5"
+ }
+ Frame {
+ msec: 1952
+ hash: "101e8595d0301e88376ec52ba9361f84"
+ }
+ Frame {
+ msec: 1968
+ hash: "119d548c59baa7e47266d2ceca663288"
+ }
+ Frame {
+ msec: 1984
+ hash: "f141fafe102a0b9a2bf33e8c3fc800ff"
+ }
+ Frame {
+ msec: 2000
+ hash: "b01f9ca8d4fbff17b3d48c70898a044d"
+ }
+ Frame {
+ msec: 2016
+ hash: "cf67954a2d1b22e8d2cfdc26419bafb8"
+ }
+ Frame {
+ msec: 2032
+ hash: "7680b2b5a63dea13d733947297e01355"
+ }
+ Frame {
+ msec: 2048
+ hash: "af1c017acf6b3c8cff86c9ceb60db3cb"
+ }
+ Frame {
+ msec: 2064
+ hash: "0b23ec51f71fddae5e2238ab5754f1db"
+ }
+ Frame {
+ msec: 2080
+ hash: "976643961ecbdc86335180ba812b874e"
+ }
+ Frame {
+ msec: 2096
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2112
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2128
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2144
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2160
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2176
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2192
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2208
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2224
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2240
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2256
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2272
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2288
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2304
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2320
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2336
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2352
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2368
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2384
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2400
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2416
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2432
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2448
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2464
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2480
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2496
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2512
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2528
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2544
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2560
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2576
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2592
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2608
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2624
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2640
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2656
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2672
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2688
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2704
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2720
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2736
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2752
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 109; y: 247
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2768
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2784
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2800
+ hash: "ab924ae435262e76381c2e4af5d64342"
+ }
+ Frame {
+ msec: 2816
+ hash: "d60758fc12471a19d31c85f058f2ded7"
+ }
+ Frame {
+ msec: 2832
+ hash: "c62e2956f8eb5d2c8cd76ba05c5929d5"
+ }
+ Frame {
+ msec: 2848
+ hash: "f2967ee7e035a9ff258116a2706529f8"
+ }
+ Frame {
+ msec: 2864
+ hash: "885c4705c6c29f69c56c44abc1251d75"
+ }
+ Frame {
+ msec: 2880
+ image: "propertyAction.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "f4af6871e522511f95bc4c5abfc2a562"
+ }
+ Frame {
+ msec: 2912
+ hash: "b27e1e7e0d90468525309528ccfe2823"
+ }
+ Frame {
+ msec: 2928
+ hash: "78e7d84a4466258b40315fe61b7ca15c"
+ }
+ Frame {
+ msec: 2944
+ hash: "471013d921d8d6e7468fd6aba0b75c71"
+ }
+ Frame {
+ msec: 2960
+ hash: "856048da893c9136ac5740bc89b64128"
+ }
+ Frame {
+ msec: 2976
+ hash: "32ccdab249268b01d9f1658a736052f1"
+ }
+ Frame {
+ msec: 2992
+ hash: "2264fa3acd979f104633c1301a0efd8f"
+ }
+ Frame {
+ msec: 3008
+ hash: "f3199d0c860f1236e0b9472bef8785bc"
+ }
+ Frame {
+ msec: 3024
+ hash: "ad899d1ecaa43a5541be7b70413caee5"
+ }
+ Frame {
+ msec: 3040
+ hash: "4e652524c992f5ee1b987275ca509728"
+ }
+ Frame {
+ msec: 3056
+ hash: "a44b3dec2a016694bc8553a51b29d46c"
+ }
+ Frame {
+ msec: 3072
+ hash: "7fbe20346bc3c28c345e0797b55599f3"
+ }
+ Frame {
+ msec: 3088
+ hash: "bcff18ad433bb4f08126ee66efb037d1"
+ }
+ Frame {
+ msec: 3104
+ hash: "836666c64f73c38e87de95944ff2fe72"
+ }
+ Frame {
+ msec: 3120
+ hash: "4379982d23db239b1741b5d72c53e160"
+ }
+ Frame {
+ msec: 3136
+ hash: "0ed9476337214e1493c1510b8a4c90f8"
+ }
+ Frame {
+ msec: 3152
+ hash: "dab637406577a1924c7dbb30680e1af3"
+ }
+ Frame {
+ msec: 3168
+ hash: "dcc79277fdb8966e5a3f2ed1b2fc4292"
+ }
+ Frame {
+ msec: 3184
+ hash: "5f207d1dfad4907f200d76104881bf56"
+ }
+ Frame {
+ msec: 3200
+ hash: "3434fc7f81e859722585dae97c557864"
+ }
+ Frame {
+ msec: 3216
+ hash: "7c775b9be8c5293d4962324574267c22"
+ }
+ Frame {
+ msec: 3232
+ hash: "da0ff6955c2e4cd86421bdb9053f56e6"
+ }
+ Frame {
+ msec: 3248
+ hash: "a1297d525a3ad41abbbb7c2f15efd4fb"
+ }
+ Frame {
+ msec: 3264
+ hash: "5326b220995b2a1eaa308ad10fd353fa"
+ }
+ Frame {
+ msec: 3280
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3296
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3312
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3328
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3344
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3360
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3376
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3392
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3408
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3424
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3440
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3456
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3472
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3488
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3504
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3520
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3536
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3552
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3568
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3584
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3600
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3616
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 3632
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/propertyAction/propertyAction.qml b/tests/auto/declarative/visual/animation/propertyAction/propertyAction.qml
new file mode 100644
index 0000000..b670166
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/propertyAction/propertyAction.qml
@@ -0,0 +1,34 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 400
+ Rectangle {
+ id: myRect
+ width: 100; height: 100
+ color: "red"
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ states: State {
+ name: "state1"
+ when: clickable.pressed
+ PropertyChanges {
+ target: myRect
+ x: 50; y: 50
+ color: "blue"
+ }
+ }
+
+ transitions: Transition {
+ to: "state1"
+ reversible: true
+ SequentialAnimation {
+ ColorAnimation {}
+ PropertyAction { matchProperties: "x" }
+ NumberAnimation { matchProperties: "y"; easing: "InOutQuad" }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.0.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.0.png
new file mode 100644
index 0000000..c7bbf38
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.1.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.1.png
new file mode 100644
index 0000000..612500b
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.2.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.2.png
new file mode 100644
index 0000000..c7bbf38
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.3.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.3.png
new file mode 100644
index 0000000..c7bbf38
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.4.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.4.png
new file mode 100644
index 0000000..1910eb4
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.5.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.5.png
new file mode 100644
index 0000000..3b8eebd
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.6.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.6.png
new file mode 100644
index 0000000..c7bbf38
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.7.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.7.png
new file mode 100644
index 0000000..c7bbf38
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.8.png b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.8.png
new file mode 100644
index 0000000..960be31
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/reanchor/data/reanchor.qml b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.qml
new file mode 100644
index 0000000..0f58de5
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/data/reanchor.qml
@@ -0,0 +1,2471 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 32
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 48
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 64
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 80
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 96
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 112
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 128
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 144
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 160
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 176
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 192
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 208
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 224
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 240
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 256
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 272
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 288
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 304
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 320
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 336
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 352
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 368
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 384
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 400
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 416
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 432
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 448
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 464
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 480
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 496
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 512
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 528
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 544
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 560
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 576
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 592
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 608
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 624
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 640
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 656
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 672
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 688
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 704
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 720
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 736
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 752
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 768
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 784
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 800
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 816
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 832
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 848
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 864
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 880
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 896
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 912
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 928
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 944
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 960
+ image: "reanchor.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 992
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1008
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1024
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1040
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1056
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1072
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1088
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1104
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1120
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1136
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1152
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1168
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1184
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1200
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1216
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1232
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1248
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1264
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1280
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1296
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1312
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1328
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1344
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1360
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 88; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1376
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1392
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1408
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1424
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1440
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 88; y: 115
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1456
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 1472
+ hash: "c2d6dd91f3e9cdcacbadcb449c8a9896"
+ }
+ Frame {
+ msec: 1488
+ hash: "1098ea19aecebd71208e101d522c1981"
+ }
+ Frame {
+ msec: 1504
+ hash: "8cc59c20d796c073038518d2855fb6f0"
+ }
+ Frame {
+ msec: 1520
+ hash: "914a89d0cfdc68145024ce2305a5e76e"
+ }
+ Frame {
+ msec: 1536
+ hash: "7a2e3ca2660df24d9a6ec49a7422ebe1"
+ }
+ Frame {
+ msec: 1552
+ hash: "b71496d986d5f0aa76b4f1663627f1f7"
+ }
+ Frame {
+ msec: 1568
+ hash: "41b29a523db919bc0a4e0a9a88bfc873"
+ }
+ Frame {
+ msec: 1584
+ hash: "97632a0de766b9ffbf71f21eeb0ff9a2"
+ }
+ Frame {
+ msec: 1600
+ hash: "94cc196e62c150008461ff9996b4cae8"
+ }
+ Frame {
+ msec: 1616
+ hash: "32e96ad2d15fa2386d365ab249ddf4f4"
+ }
+ Frame {
+ msec: 1632
+ hash: "209394314f971b12fbc61ca45010cc62"
+ }
+ Frame {
+ msec: 1648
+ hash: "b917c2684dda8af00278b34ababdcf5c"
+ }
+ Frame {
+ msec: 1664
+ hash: "92b506860c1c5dc52f87c24c89921b05"
+ }
+ Frame {
+ msec: 1680
+ hash: "7b7e96113fa9359954be9b3ac87943c3"
+ }
+ Frame {
+ msec: 1696
+ hash: "42bc69db42c5df902038cec414246ec5"
+ }
+ Frame {
+ msec: 1712
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1728
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1744
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1760
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1776
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1792
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1808
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1824
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1840
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1856
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1872
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1888
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1904
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1920
+ image: "reanchor.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1952
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1968
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 1984
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2000
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2016
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2032
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2048
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2064
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2080
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2096
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 87; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2112
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2128
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2144
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2160
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2176
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2192
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2208
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 87; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2224
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 2240
+ hash: "2d1aa011f2008a6147ba593e3cf272d7"
+ }
+ Frame {
+ msec: 2256
+ hash: "206699ea84ce9fd60c1603b7a48a5134"
+ }
+ Frame {
+ msec: 2272
+ hash: "68eb6df93a2b6db7023f7c3cc71d5b5f"
+ }
+ Frame {
+ msec: 2288
+ hash: "5a4cd0620959dde92eeeaaa4dcd13091"
+ }
+ Frame {
+ msec: 2304
+ hash: "17b763187a777253b25b22f5dd7253ae"
+ }
+ Frame {
+ msec: 2320
+ hash: "1de9dcf4d385266f4482e2d0967d9119"
+ }
+ Frame {
+ msec: 2336
+ hash: "833496add6dbc3103a28a47e453a738b"
+ }
+ Frame {
+ msec: 2352
+ hash: "b3bab2e9c56db60cd54e68369e6b790d"
+ }
+ Frame {
+ msec: 2368
+ hash: "ee91c6cd909bec401a1a7eebd10b8b02"
+ }
+ Frame {
+ msec: 2384
+ hash: "0ed679ad0ab7bd3544947bccda88647b"
+ }
+ Frame {
+ msec: 2400
+ hash: "d7dfcdc8a4233821919f1732d8c39712"
+ }
+ Frame {
+ msec: 2416
+ hash: "c52829ee689e4c312a9dff8dbd4a79f9"
+ }
+ Frame {
+ msec: 2432
+ hash: "7962badda0e80a61b67943d3b31f892d"
+ }
+ Frame {
+ msec: 2448
+ hash: "fc5f2c24e3d8743ab5b20aaa122bacc2"
+ }
+ Frame {
+ msec: 2464
+ hash: "201b9ee6c9ac6208ef812fe2e95020ef"
+ }
+ Frame {
+ msec: 2480
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2496
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2512
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2528
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2544
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2560
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2576
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2592
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2608
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2624
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2640
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2656
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2672
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2688
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2704
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2720
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2736
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2752
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 87; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2768
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2784
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2800
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2816
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2832
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2848
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 2864
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 87; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 2880
+ image: "reanchor.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "c2d6dd91f3e9cdcacbadcb449c8a9896"
+ }
+ Frame {
+ msec: 2912
+ hash: "1098ea19aecebd71208e101d522c1981"
+ }
+ Frame {
+ msec: 2928
+ hash: "8cc59c20d796c073038518d2855fb6f0"
+ }
+ Frame {
+ msec: 2944
+ hash: "914a89d0cfdc68145024ce2305a5e76e"
+ }
+ Frame {
+ msec: 2960
+ hash: "7a2e3ca2660df24d9a6ec49a7422ebe1"
+ }
+ Frame {
+ msec: 2976
+ hash: "b71496d986d5f0aa76b4f1663627f1f7"
+ }
+ Frame {
+ msec: 2992
+ hash: "41b29a523db919bc0a4e0a9a88bfc873"
+ }
+ Frame {
+ msec: 3008
+ hash: "97632a0de766b9ffbf71f21eeb0ff9a2"
+ }
+ Frame {
+ msec: 3024
+ hash: "94cc196e62c150008461ff9996b4cae8"
+ }
+ Frame {
+ msec: 3040
+ hash: "32e96ad2d15fa2386d365ab249ddf4f4"
+ }
+ Frame {
+ msec: 3056
+ hash: "209394314f971b12fbc61ca45010cc62"
+ }
+ Frame {
+ msec: 3072
+ hash: "b917c2684dda8af00278b34ababdcf5c"
+ }
+ Frame {
+ msec: 3088
+ hash: "92b506860c1c5dc52f87c24c89921b05"
+ }
+ Frame {
+ msec: 3104
+ hash: "7b7e96113fa9359954be9b3ac87943c3"
+ }
+ Frame {
+ msec: 3120
+ hash: "42bc69db42c5df902038cec414246ec5"
+ }
+ Frame {
+ msec: 3136
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3152
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3168
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3184
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3200
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3216
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3232
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3248
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3264
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3280
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3296
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3312
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3328
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3344
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3360
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 87; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3376
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3392
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3408
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3424
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3440
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3456
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3472
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 87; y: 114
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 3488
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 3504
+ hash: "2d1aa011f2008a6147ba593e3cf272d7"
+ }
+ Frame {
+ msec: 3520
+ hash: "206699ea84ce9fd60c1603b7a48a5134"
+ }
+ Frame {
+ msec: 3536
+ hash: "68eb6df93a2b6db7023f7c3cc71d5b5f"
+ }
+ Frame {
+ msec: 3552
+ hash: "5a4cd0620959dde92eeeaaa4dcd13091"
+ }
+ Frame {
+ msec: 3568
+ hash: "17b763187a777253b25b22f5dd7253ae"
+ }
+ Frame {
+ msec: 3584
+ hash: "1de9dcf4d385266f4482e2d0967d9119"
+ }
+ Frame {
+ msec: 3600
+ hash: "833496add6dbc3103a28a47e453a738b"
+ }
+ Frame {
+ msec: 3616
+ hash: "b3bab2e9c56db60cd54e68369e6b790d"
+ }
+ Frame {
+ msec: 3632
+ hash: "ee91c6cd909bec401a1a7eebd10b8b02"
+ }
+ Frame {
+ msec: 3648
+ hash: "0ed679ad0ab7bd3544947bccda88647b"
+ }
+ Frame {
+ msec: 3664
+ hash: "d7dfcdc8a4233821919f1732d8c39712"
+ }
+ Frame {
+ msec: 3680
+ hash: "c52829ee689e4c312a9dff8dbd4a79f9"
+ }
+ Frame {
+ msec: 3696
+ hash: "7962badda0e80a61b67943d3b31f892d"
+ }
+ Frame {
+ msec: 3712
+ hash: "fc5f2c24e3d8743ab5b20aaa122bacc2"
+ }
+ Frame {
+ msec: 3728
+ hash: "201b9ee6c9ac6208ef812fe2e95020ef"
+ }
+ Frame {
+ msec: 3744
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3760
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3776
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3792
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3808
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3824
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3840
+ image: "reanchor.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3872
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3888
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3904
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3920
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3936
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3952
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3968
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 3984
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4000
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4016
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4032
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4048
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4064
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4080
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4096
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4112
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4128
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4144
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4160
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4176
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4192
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4208
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4224
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4240
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4256
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4272
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4288
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4304
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4320
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4336
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4352
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4368
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4384
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4400
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4416
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4432
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4448
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4464
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4480
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4496
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4512
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4528
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 174; y: 174
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4544
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4560
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4576
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4592
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4608
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4624
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4640
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4656
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 174; y: 174
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 4672
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 4688
+ hash: "5d38bf4a033de31985ae9989107908af"
+ }
+ Frame {
+ msec: 4704
+ hash: "ed1bd2abd42848ecd07f0f0654c2b80f"
+ }
+ Frame {
+ msec: 4720
+ hash: "588de6662123733303d93f62c6481f6a"
+ }
+ Frame {
+ msec: 4736
+ hash: "aae79c2fbb2fd1ac7efa9802bff40f95"
+ }
+ Frame {
+ msec: 4752
+ hash: "f17512798136f67f25aaa0aeb60678e1"
+ }
+ Frame {
+ msec: 4768
+ hash: "79578a1e0e3e9cd45c210d0c5d3e75d6"
+ }
+ Frame {
+ msec: 4784
+ hash: "5dad4ff201744cda6ff41f89414c8d11"
+ }
+ Frame {
+ msec: 4800
+ image: "reanchor.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "c4559982aa3f3d291364deed4bd96d65"
+ }
+ Frame {
+ msec: 4832
+ hash: "0dff03ea9154bdb2a813358b04cfbde9"
+ }
+ Frame {
+ msec: 4848
+ hash: "09bdf2869dee1c0cbe3c8c2e9254580b"
+ }
+ Frame {
+ msec: 4864
+ hash: "ba7762978bbd63d624029910fe16fb6d"
+ }
+ Frame {
+ msec: 4880
+ hash: "f00d198ab8f4f625b60e9e2071d8adfd"
+ }
+ Frame {
+ msec: 4896
+ hash: "adcec9c9a5b0d60cf45b2915365ea09c"
+ }
+ Frame {
+ msec: 4912
+ hash: "a65cd6fbb26d618692ef23148015a4f2"
+ }
+ Frame {
+ msec: 4928
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 4944
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 4960
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 4976
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 4992
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5008
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5024
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5040
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5056
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5072
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5088
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5104
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5120
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5136
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5152
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5168
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5184
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5200
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5216
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5232
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5248
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5264
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5280
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5296
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5312
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5328
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5344
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5360
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5376
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5392
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5408
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5424
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5440
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5456
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5472
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5488
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5504
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5520
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5536
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5552
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5568
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5584
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5600
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5616
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5632
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5648
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5664
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5680
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5696
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5712
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5728
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5744
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5760
+ image: "reanchor.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5792
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5808
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 95; y: 78
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5824
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5840
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5856
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5872
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5888
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5904
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5920
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5936
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 95; y: 78
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 5952
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 5968
+ hash: "103bbc9ce594851f5243b103f8fef1c1"
+ }
+ Frame {
+ msec: 5984
+ hash: "c381148b052be2e6244f24c2292b89cf"
+ }
+ Frame {
+ msec: 6000
+ hash: "2fda1d635fa47bff7de867df3dadfb4f"
+ }
+ Frame {
+ msec: 6016
+ hash: "4d35e00af33ad5dc84998cda2d066b4e"
+ }
+ Frame {
+ msec: 6032
+ hash: "14005d52d372acf6d3495f69bbf00b7d"
+ }
+ Frame {
+ msec: 6048
+ hash: "29728f64d12e858d960c4e197824ef43"
+ }
+ Frame {
+ msec: 6064
+ hash: "798822f0c20ef87cb01fe1dcd76c7585"
+ }
+ Frame {
+ msec: 6080
+ hash: "4cdeea0f91587ef32a2c2e282f6d00e6"
+ }
+ Frame {
+ msec: 6096
+ hash: "08ca5d16771e58da6cdd20b86dc65f03"
+ }
+ Frame {
+ msec: 6112
+ hash: "e9aeb432709d275048ad9d84fb21db1a"
+ }
+ Frame {
+ msec: 6128
+ hash: "3b642f27d356fd1815dc50f8e750623d"
+ }
+ Frame {
+ msec: 6144
+ hash: "7c1db0ec278849ec044ea0aa3383075b"
+ }
+ Frame {
+ msec: 6160
+ hash: "da902850879c95d4ddffbb1ba0060f25"
+ }
+ Frame {
+ msec: 6176
+ hash: "e4053bd0db7752e7a47e096da645b69b"
+ }
+ Frame {
+ msec: 6192
+ hash: "aabbb6d34399818347db265151a547b7"
+ }
+ Frame {
+ msec: 6208
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6224
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6240
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6256
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6272
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6288
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6304
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6320
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6336
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6352
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6368
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6384
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6400
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6416
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6432
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6448
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6464
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6480
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6496
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6512
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6528
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6544
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6560
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6576
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6592
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6608
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6624
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6640
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6656
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6672
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6688
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6704
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6720
+ image: "reanchor.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6752
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6768
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6784
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6800
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6816
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6832
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6848
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6864
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6880
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6896
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6912
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6928
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6944
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6960
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6976
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 6992
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7008
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7024
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7040
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7056
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7072
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7088
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7104
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7120
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7136
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7152
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7168
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7184
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7200
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7216
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7232
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7248
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7264
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7280
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7296
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7312
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7328
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7344
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7360
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7376
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7392
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7408
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7424
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7440
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7456
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7472
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7488
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7504
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7520
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7536
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7552
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7568
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7584
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7600
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 86; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7616
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7632
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7648
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Frame {
+ msec: 7664
+ hash: "213811853dbefdc418099721e3bf8651"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 86; y: 136
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 7680
+ image: "reanchor.7.png"
+ }
+ Frame {
+ msec: 7696
+ hash: "c2d6dd91f3e9cdcacbadcb449c8a9896"
+ }
+ Frame {
+ msec: 7712
+ hash: "1098ea19aecebd71208e101d522c1981"
+ }
+ Frame {
+ msec: 7728
+ hash: "8cc59c20d796c073038518d2855fb6f0"
+ }
+ Frame {
+ msec: 7744
+ hash: "914a89d0cfdc68145024ce2305a5e76e"
+ }
+ Frame {
+ msec: 7760
+ hash: "7a2e3ca2660df24d9a6ec49a7422ebe1"
+ }
+ Frame {
+ msec: 7776
+ hash: "b71496d986d5f0aa76b4f1663627f1f7"
+ }
+ Frame {
+ msec: 7792
+ hash: "41b29a523db919bc0a4e0a9a88bfc873"
+ }
+ Frame {
+ msec: 7808
+ hash: "97632a0de766b9ffbf71f21eeb0ff9a2"
+ }
+ Frame {
+ msec: 7824
+ hash: "94cc196e62c150008461ff9996b4cae8"
+ }
+ Frame {
+ msec: 7840
+ hash: "32e96ad2d15fa2386d365ab249ddf4f4"
+ }
+ Frame {
+ msec: 7856
+ hash: "209394314f971b12fbc61ca45010cc62"
+ }
+ Frame {
+ msec: 7872
+ hash: "b917c2684dda8af00278b34ababdcf5c"
+ }
+ Frame {
+ msec: 7888
+ hash: "92b506860c1c5dc52f87c24c89921b05"
+ }
+ Frame {
+ msec: 7904
+ hash: "7b7e96113fa9359954be9b3ac87943c3"
+ }
+ Frame {
+ msec: 7920
+ hash: "42bc69db42c5df902038cec414246ec5"
+ }
+ Frame {
+ msec: 7936
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 7952
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 7968
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 7984
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8000
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8016
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8032
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8048
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8064
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8080
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8096
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8112
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8128
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8144
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8160
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8176
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8192
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8208
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8224
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8240
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8256
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8272
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8288
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8304
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8320
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8336
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8352
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8368
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8384
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8400
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 177; y: 173
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8416
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8432
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8448
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8464
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8480
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8496
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8512
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Mouse {
+ type: 3
+ button: 1
+ buttons: 0
+ x: 177; y: 173
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 8528
+ hash: "7eb4027421fd6aa7d668a704e40a6e61"
+ }
+ Frame {
+ msec: 8544
+ hash: "b4f30663a9b21e42375645e970f57d0b"
+ }
+ Frame {
+ msec: 8560
+ hash: "6c12dbf4af8801573515b61123d4b1d7"
+ }
+ Frame {
+ msec: 8576
+ hash: "facc61397c734bb4409d5664dc059a14"
+ }
+ Frame {
+ msec: 8592
+ hash: "897e15e37276454d11fac6a528e967a6"
+ }
+ Frame {
+ msec: 8608
+ hash: "cf8173519f1e042c227ff61c62308640"
+ }
+ Frame {
+ msec: 8624
+ hash: "d0fcda14ea4bcfebf04ccf99e292ac6a"
+ }
+ Frame {
+ msec: 8640
+ image: "reanchor.8.png"
+ }
+ Frame {
+ msec: 8656
+ hash: "74b4ababa97def538f5340e88a4419a4"
+ }
+ Frame {
+ msec: 8672
+ hash: "b96b5b64505b1814ddd42a52569d7fd9"
+ }
+ Frame {
+ msec: 8688
+ hash: "0e3e07aad030b2075c4bc61b02ebe49e"
+ }
+ Frame {
+ msec: 8704
+ hash: "c5eebc652c58e3a44d5ed481100ef242"
+ }
+ Frame {
+ msec: 8720
+ hash: "d4a74185304c126739af728ddda40e0c"
+ }
+ Frame {
+ msec: 8736
+ hash: "448572d3c1060b8311952429a7f9430d"
+ }
+ Frame {
+ msec: 8752
+ hash: "00f64c09657a8afd6caa186efb6ad860"
+ }
+ Frame {
+ msec: 8768
+ hash: "2a360e6feaaf303e9ee63145085796e6"
+ }
+ Frame {
+ msec: 8784
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8800
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8816
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8832
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8848
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8864
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8880
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8896
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8912
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8928
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8944
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8960
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8976
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 8992
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9008
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9024
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9040
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9056
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9072
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9088
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9104
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9120
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9136
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 9152
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9168
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9184
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9200
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9216
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9232
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9248
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9264
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9280
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9296
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+ Frame {
+ msec: 9312
+ hash: "1137e22c68e043950811dee295e19b04"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/reanchor/reanchor.qml b/tests/auto/declarative/visual/animation/reanchor/reanchor.qml
new file mode 100644
index 0000000..1cc68a9
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/reanchor/reanchor.qml
@@ -0,0 +1,68 @@
+import Qt 4.6
+
+Rectangle {
+ id: container
+ width: 200; height: 200
+ Rectangle {
+ id: myRect
+ objectName: "MyRect"
+ color: "green";
+ anchors.left: parent.left
+ anchors.right: rightGuideline.left
+ anchors.top: topGuideline.top
+ anchors.bottom: container.bottom
+ }
+ Item { id: leftGuideline; x: 10 }
+ Item { id: rightGuideline; x: 150 }
+ Item { id: topGuideline; y: 10 }
+ Item { id: bottomGuideline; y: 150 }
+ Item { id: topGuideline2; y: 50 }
+ Item { id: bottomGuideline2; y: 175 }
+
+ MouseRegion {
+ id: wholeArea
+ anchors.fill: parent
+ onClicked: {
+ if (container.state == "") {
+ container.state = "reanchored";
+ } else if (container.state == "reanchored") {
+ container.state = "reanchored2";
+ } else if (container.state == "reanchored2")
+ container.state = "reanchored";
+ }
+ }
+
+ states: [ State {
+ name: "reanchored"
+ AnchorChanges {
+ target: myRect;
+ left: leftGuideline.left
+ right: container.right
+ top: container.top
+ bottom: bottomGuideline.bottom
+ }
+ }, State {
+ name: "reanchored2"
+ AnchorChanges {
+ target: myRect;
+ reset: "left, right"
+ top: topGuideline2.top
+ bottom: bottomGuideline2.bottom
+ }
+ }]
+
+ transitions: Transition {
+ NumberAnimation { matchProperties: "x,y,width,height" }
+ }
+
+ MouseRegion {
+ width: 50; height: 50
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ onClicked: {
+ container.state = "";
+ }
+ }
+
+ state: "reanchored"
+}
diff --git a/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.0.png b/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.0.png
new file mode 100644
index 0000000..64d6b06
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.1.png b/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.1.png
new file mode 100644
index 0000000..1a25c63
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.qml b/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.qml
new file mode 100644
index 0000000..01da490
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/scriptAction/data/scriptAction.qml
@@ -0,0 +1,535 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 32
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 48
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 64
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 80
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 96
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 112
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 128
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 144
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 160
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 176
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 192
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 208
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 224
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 240
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 256
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 272
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 288
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 304
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 320
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 336
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 352
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 368
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 384
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 400
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 416
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 432
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 448
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 464
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 480
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 496
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 512
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 528
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 544
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 560
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 576
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 592
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 608
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 624
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 640
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 656
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 672
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 688
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 704
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 720
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 736
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 752
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 768
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 784
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 800
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 816
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 832
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 848
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 864
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 880
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 896
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 912
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 928
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 944
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 960
+ image: "scriptAction.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 992
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1008
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1024
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1040
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1056
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1072
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1088
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Mouse {
+ type: 2
+ button: 1
+ buttons: 1
+ x: 146; y: 259
+ modifiers: 0
+ sendToViewport: true
+ }
+ Frame {
+ msec: 1104
+ hash: "55b713dcb7c810bf126e06cc97d26d24"
+ }
+ Frame {
+ msec: 1120
+ hash: "9850cd8ed4643900409d1a87ef0bc4cf"
+ }
+ Frame {
+ msec: 1136
+ hash: "1cf03396b01e931e4e7e8e7e57e19c5f"
+ }
+ Frame {
+ msec: 1152
+ hash: "25fe648b85ec2d82621853dcbdbf695a"
+ }
+ Frame {
+ msec: 1168
+ hash: "1ca701e56fe387d5849f6933eb53aee9"
+ }
+ Frame {
+ msec: 1184
+ hash: "b39ecb792659a053a8985e2a849d6d51"
+ }
+ Frame {
+ msec: 1200
+ hash: "9a783432a054beec81cc5687f75a36dc"
+ }
+ Frame {
+ msec: 1216
+ hash: "edbd222d7ba6c6f819ded45fe316d461"
+ }
+ Frame {
+ msec: 1232
+ hash: "eaf20159c4b90f90872bbd514d3a0cec"
+ }
+ Frame {
+ msec: 1248
+ hash: "964807dd9b91e765577a773ef1ce2593"
+ }
+ Frame {
+ msec: 1264
+ hash: "16e12026ab14657b0f36b8315684455d"
+ }
+ Frame {
+ msec: 1280
+ hash: "d001a6b2fec3c66baaa45d9ff93b3f63"
+ }
+ Frame {
+ msec: 1296
+ hash: "fef11eb5f635bc11cd9679b7213b3b92"
+ }
+ Frame {
+ msec: 1312
+ hash: "0a0cd5f5004048d88712cfe6943470c0"
+ }
+ Frame {
+ msec: 1328
+ hash: "0d83178afdae5feaa9915d56c24373ad"
+ }
+ Frame {
+ msec: 1344
+ hash: "0a9e6e0b7b23ce93dc4e1f886cf9c7d1"
+ }
+ Frame {
+ msec: 1360
+ hash: "f3199d0c860f1236e0b9472bef8785bc"
+ }
+ Frame {
+ msec: 1376
+ hash: "f3199d0c860f1236e0b9472bef8785bc"
+ }
+ Frame {
+ msec: 1392
+ hash: "32ccdab249268b01d9f1658a736052f1"
+ }
+ Frame {
+ msec: 1408
+ hash: "dc98f32a1a2d6e74998123b5232107b0"
+ }
+ Frame {
+ msec: 1424
+ hash: "db3010ef552146df938c237f6c92bff5"
+ }
+ Frame {
+ msec: 1440
+ hash: "101e8595d0301e88376ec52ba9361f84"
+ }
+ Frame {
+ msec: 1456
+ hash: "119d548c59baa7e47266d2ceca663288"
+ }
+ Frame {
+ msec: 1472
+ hash: "f141fafe102a0b9a2bf33e8c3fc800ff"
+ }
+ Frame {
+ msec: 1488
+ hash: "b01f9ca8d4fbff17b3d48c70898a044d"
+ }
+ Frame {
+ msec: 1504
+ hash: "cf67954a2d1b22e8d2cfdc26419bafb8"
+ }
+ Frame {
+ msec: 1520
+ hash: "7680b2b5a63dea13d733947297e01355"
+ }
+ Frame {
+ msec: 1536
+ hash: "af1c017acf6b3c8cff86c9ceb60db3cb"
+ }
+ Frame {
+ msec: 1552
+ hash: "0b23ec51f71fddae5e2238ab5754f1db"
+ }
+ Frame {
+ msec: 1568
+ hash: "976643961ecbdc86335180ba812b874e"
+ }
+ Frame {
+ msec: 1584
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1600
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1616
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1632
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1648
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1664
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1680
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1696
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1712
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1728
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1744
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1760
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1776
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1792
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1808
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1824
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1840
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1856
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1872
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1888
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1904
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1920
+ image: "scriptAction.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1952
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1968
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 1984
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2000
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2016
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2032
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+ Frame {
+ msec: 2048
+ hash: "aeed60899abb6c486a5b1df81f9a0224"
+ }
+}
diff --git a/tests/auto/declarative/visual/animation/scriptAction/scriptAction.qml b/tests/auto/declarative/visual/animation/scriptAction/scriptAction.qml
new file mode 100644
index 0000000..872701b
--- /dev/null
+++ b/tests/auto/declarative/visual/animation/scriptAction/scriptAction.qml
@@ -0,0 +1,35 @@
+import Qt 4.6
+
+Rectangle {
+ width: 400; height: 400
+ Rectangle {
+ id: myRect
+ width: 100; height: 100
+ color: "red"
+ }
+ MouseRegion {
+ id: clickable
+ anchors.fill: parent
+ }
+
+ states: State {
+ name: "state1"
+ when: clickable.pressed
+ PropertyChanges {
+ target: myRect
+ x: 50; y: 50
+ }
+ StateChangeScript {
+ name: "setColor"
+ script: myRect.color = "blue"
+ }
+ }
+
+ transitions: Transition {
+ SequentialAnimation {
+ NumberAnimation { matchProperties: "x"; easing: "InOutQuad" }
+ ScriptAction { stateChangeScriptName: "setColor" }
+ NumberAnimation { matchProperties: "y"; easing: "InOutQuad" }
+ }
+ }
+}
diff --git a/tests/auto/declarative/visual/fillmode/data/fillmode.0.png b/tests/auto/declarative/visual/fillmode/data/fillmode.0.png
new file mode 100644
index 0000000..9c9ceae
--- /dev/null
+++ b/tests/auto/declarative/visual/fillmode/data/fillmode.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/fillmode/data/fillmode.qml b/tests/auto/declarative/visual/fillmode/data/fillmode.qml
new file mode 100644
index 0000000..7ac6f51
--- /dev/null
+++ b/tests/auto/declarative/visual/fillmode/data/fillmode.qml
@@ -0,0 +1,279 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 32
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 48
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 64
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 80
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 96
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 112
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 128
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 144
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 160
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 176
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 192
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 208
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 224
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 240
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 256
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 272
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 288
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 304
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 320
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 336
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 352
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 368
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 384
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 400
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 416
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 432
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 448
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 464
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 480
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 496
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 512
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 528
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 544
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 560
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 576
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 592
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 608
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 624
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 640
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 656
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 672
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 688
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 704
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 720
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 736
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 752
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 768
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 784
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 800
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 816
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 832
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 848
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 864
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 880
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 896
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 912
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 928
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 944
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 960
+ image: "fillmode.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 992
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 1008
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 1024
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 1040
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+ Frame {
+ msec: 1056
+ hash: "c8cb8d51ca04231dc272133faaf2fb6d"
+ }
+}
diff --git a/tests/auto/declarative/visual/fillmode/face.png b/tests/auto/declarative/visual/fillmode/face.png
new file mode 100644
index 0000000..9623b1a
--- /dev/null
+++ b/tests/auto/declarative/visual/fillmode/face.png
Binary files differ
diff --git a/tests/auto/declarative/visual/fillmode/fillmode.qml b/tests/auto/declarative/visual/fillmode/fillmode.qml
new file mode 100644
index 0000000..8450bf2
--- /dev/null
+++ b/tests/auto/declarative/visual/fillmode/fillmode.qml
@@ -0,0 +1,16 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen; width: 750; height: 600; color: "gray"
+ property string source: "face.png"
+
+ Grid {
+ columns: 3
+ Image { width: 250; height: 300; source: screen.source; fillMode: Image.Stretch }
+ Image { width: 250; height: 300; source: screen.source; fillMode: Image.PreserveAspectFit; smooth: true }
+ Image { width: 250; height: 300; source: screen.source; fillMode: Image.PreserveAspectCrop }
+ Image { width: 250; height: 300; source: screen.source; fillMode: Image.Tile; smooth: true }
+ Image { width: 250; height: 300; source: screen.source; fillMode: Image.TileHorizontally }
+ Image { width: 250; height: 300; source: screen.source; fillMode: Image.TileVertically }
+ }
+}
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test.0.png b/tests/auto/declarative/visual/focusscope/data-MAC/test.0.png
new file mode 100644
index 0000000..0f33d99
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test.1.png b/tests/auto/declarative/visual/focusscope/data-MAC/test.1.png
new file mode 100644
index 0000000..0f33d99
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test.2.png b/tests/auto/declarative/visual/focusscope/data-MAC/test.2.png
new file mode 100644
index 0000000..06a3dbd
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test.3.png b/tests/auto/declarative/visual/focusscope/data-MAC/test.3.png
new file mode 100644
index 0000000..e0d02d6
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test.4.png b/tests/auto/declarative/visual/focusscope/data-MAC/test.4.png
new file mode 100644
index 0000000..e0d02d6
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test.5.png b/tests/auto/declarative/visual/focusscope/data-MAC/test.5.png
new file mode 100644
index 0000000..e0d02d6
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test.qml b/tests/auto/declarative/visual/focusscope/data-MAC/test.qml
new file mode 100644
index 0000000..44900fc
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test.qml
@@ -0,0 +1,1599 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 32
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 48
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 64
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 80
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 96
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 112
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 128
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 144
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 160
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 176
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 192
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 208
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 224
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 240
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 256
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 272
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 288
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 304
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 320
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 336
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 352
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 368
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 384
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 400
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 416
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 432
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 448
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 464
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 480
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 496
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 512
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 528
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 544
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 560
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 576
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 592
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 608
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 624
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 640
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 656
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 672
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 688
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 704
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 720
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 736
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 752
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 768
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 784
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 800
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 816
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 832
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 848
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 864
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 880
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 896
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 912
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 928
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 944
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 960
+ image: "test.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 992
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1008
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1024
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1040
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1056
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1072
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1088
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1104
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1120
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1136
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1152
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1168
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1184
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1200
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1216
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1232
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1248
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1264
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1280
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1296
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1312
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1328
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1344
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1360
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1376
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1392
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1408
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1424
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1440
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1456
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1472
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1488
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1504
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1520
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1536
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1552
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1568
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1584
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1600
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1616
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1632
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1648
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1664
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1680
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1696
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1712
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1728
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1744
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1760
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1776
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1792
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 1808
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1824
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1840
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1856
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1872
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1888
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1904
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1920
+ image: "test.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1952
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1968
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 1984
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2000
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2016
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2032
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2048
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2064
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2080
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2096
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2112
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2128
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2144
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2160
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2176
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2192
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2208
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2224
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2240
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2256
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2272
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2288
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2304
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2320
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2336
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 2352
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Key {
+ type: 6
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2368
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2384
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2400
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2416
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2432
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2448
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2464
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Key {
+ type: 7
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2480
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2496
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2512
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2528
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2544
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2560
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2576
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2592
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2608
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2624
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2640
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2656
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2672
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2688
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2704
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2720
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2736
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2752
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2768
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2784
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2800
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2816
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2832
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2848
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2864
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2880
+ image: "test.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2912
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2928
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2944
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2960
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 2976
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Key {
+ type: 6
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2992
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3008
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3024
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3040
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3056
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3072
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3088
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Key {
+ type: 7
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3104
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3120
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3136
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3152
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3168
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3184
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3200
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3216
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3232
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3248
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3264
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3280
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3296
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3312
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3328
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3344
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3360
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3376
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3392
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3408
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3424
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3440
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3456
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3472
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3488
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3504
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3520
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Frame {
+ msec: 3536
+ hash: "70f4ce2881f2340167f314b49716707a"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3552
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3568
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3584
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3600
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3616
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3632
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3648
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3664
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3680
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3696
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3712
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3728
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3744
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3760
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3776
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3792
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3808
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3824
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3840
+ image: "test.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3872
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3888
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3904
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3920
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3936
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3952
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3968
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 3984
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4000
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4016
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4032
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4048
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4064
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4080
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4096
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4112
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4128
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4144
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4160
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4176
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Key {
+ type: 6
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4192
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4208
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4224
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4240
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4256
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4272
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Key {
+ type: 7
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4288
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4304
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4320
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4336
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4352
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4368
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4384
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4400
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4416
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4432
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4448
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4464
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4480
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4496
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4512
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4528
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4544
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4560
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4576
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4592
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4608
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4624
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4640
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4656
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4672
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4688
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4704
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4720
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4736
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4752
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4768
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Frame {
+ msec: 4784
+ hash: "773f573d4b37181f7a784597a30cd73d"
+ }
+ Key {
+ type: 6
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4800
+ image: "test.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4832
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4848
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4864
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4880
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4896
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Key {
+ type: 7
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4912
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4928
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4944
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4960
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4976
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 4992
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5008
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5024
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5040
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5056
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5072
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5088
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5104
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5120
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5136
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5152
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5168
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5184
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5200
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5216
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5232
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5248
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5264
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5280
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5296
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5312
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5328
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5344
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5360
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5376
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5392
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5408
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5424
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5440
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5456
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5472
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5488
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5504
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5520
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5536
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5552
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5568
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5584
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5600
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5616
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5632
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5648
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5664
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5680
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5696
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5712
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5728
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5744
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5760
+ image: "test.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5792
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5808
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5824
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5840
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5856
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5872
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+ Frame {
+ msec: 5888
+ hash: "715a587be7a5803af2827e882236d187"
+ }
+}
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test2.0.png b/tests/auto/declarative/visual/focusscope/data-MAC/test2.0.png
new file mode 100644
index 0000000..fa711c1
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test2.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test2.1.png b/tests/auto/declarative/visual/focusscope/data-MAC/test2.1.png
new file mode 100644
index 0000000..fa711c1
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test2.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test2.qml b/tests/auto/declarative/visual/focusscope/data-MAC/test2.qml
new file mode 100644
index 0000000..7837ad9
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test2.qml
@@ -0,0 +1,607 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 32
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 48
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 64
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 80
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 96
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 112
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 128
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 144
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 160
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 176
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 192
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 208
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 224
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 240
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 256
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 272
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 288
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 304
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 320
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 336
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 352
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 368
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 384
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 400
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 416
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 432
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 448
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 464
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 480
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 496
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 512
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 528
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 544
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 560
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 576
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 592
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 608
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 624
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 640
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 656
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 672
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 688
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 704
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 720
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 736
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 752
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 768
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 784
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 800
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 816
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 832
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 848
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 864
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 880
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 896
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 912
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 928
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 944
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 960
+ image: "test2.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 992
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1008
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1024
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1040
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1056
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1072
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1088
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1104
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1120
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1136
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1152
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1168
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1184
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1200
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1216
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1232
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1248
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1264
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1280
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1296
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1312
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1328
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1344
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1360
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1376
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1392
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1408
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1424
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1440
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1456
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1472
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1488
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1504
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1520
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1536
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1552
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1568
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1584
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1600
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1616
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1632
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1648
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1664
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1680
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1696
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1712
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1728
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1744
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1760
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1776
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1792
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1808
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1824
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1840
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1856
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1872
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1888
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1904
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1920
+ image: "test2.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1952
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1968
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 1984
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2000
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2016
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2032
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2048
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2064
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2080
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2096
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2112
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2128
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2144
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2160
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2176
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2192
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2208
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2224
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2240
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2256
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2272
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2288
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2304
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2320
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2336
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2352
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+ Frame {
+ msec: 2368
+ hash: "9ecdd4addcaea53cdca16f3496ceb15c"
+ }
+}
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.0.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.0.png
new file mode 100644
index 0000000..9309e37
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.1.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.1.png
new file mode 100644
index 0000000..20e6c8e
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.2.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.2.png
new file mode 100644
index 0000000..c7559ac
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.3.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.3.png
new file mode 100644
index 0000000..bf2844b
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.4.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.4.png
new file mode 100644
index 0000000..beef0bf
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.5.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.5.png
new file mode 100644
index 0000000..1847dc7
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.6.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.6.png
new file mode 100644
index 0000000..c7559ac
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.7.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.7.png
new file mode 100644
index 0000000..20e6c8e
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.8.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.8.png
new file mode 100644
index 0000000..9309e37
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.9.png b/tests/auto/declarative/visual/focusscope/data-MAC/test3.9.png
new file mode 100644
index 0000000..7ac879b
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.9.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-MAC/test3.qml b/tests/auto/declarative/visual/focusscope/data-MAC/test3.qml
new file mode 100644
index 0000000..7308a23
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-MAC/test3.qml
@@ -0,0 +1,2879 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 32
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 48
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 64
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 80
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 96
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 112
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 128
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 144
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 160
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 176
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 192
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 208
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 224
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 240
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 256
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 272
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 288
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 304
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 320
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 336
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 352
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 368
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 384
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 400
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 416
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 432
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 448
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 464
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 480
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 496
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 512
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 528
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 544
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 560
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 576
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 592
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 608
+ hash: "ce962a38caeb7bf7eef05112fbb52f91"
+ }
+ Frame {
+ msec: 624
+ hash: "779f0660ce5bc2c2fc9f05d8b86158a8"
+ }
+ Frame {
+ msec: 640
+ hash: "615e07a3c83539321befb44aa8fac811"
+ }
+ Frame {
+ msec: 656
+ hash: "8a00b9f66ca7fdb0e4975f547025f873"
+ }
+ Frame {
+ msec: 672
+ hash: "43bbe82799b1d8453f89a7ef928b1e54"
+ }
+ Frame {
+ msec: 688
+ hash: "2cc468d6e14c27ff1c0bd6064ae47509"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 704
+ hash: "1dc9d1b95016ccbeaca5b7a867a5cc3a"
+ }
+ Frame {
+ msec: 720
+ hash: "f36734c91fe41a7947965dac97393ad4"
+ }
+ Frame {
+ msec: 736
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 752
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 768
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 784
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 800
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 816
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 832
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 848
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 864
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 880
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 896
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 912
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 928
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 944
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 960
+ image: "test3.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 992
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 1008
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 1024
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 1040
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 1056
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 1072
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 1088
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1104
+ hash: "1c29b3d1086b261c2a9e94d49567484f"
+ }
+ Frame {
+ msec: 1120
+ hash: "6ab17a210b45dae1ed99fd1689bb3e46"
+ }
+ Frame {
+ msec: 1136
+ hash: "feb504605f7f27ca3a2bf080c1fb1e19"
+ }
+ Frame {
+ msec: 1152
+ hash: "bec2d2e2222587a379af12a30e078886"
+ }
+ Frame {
+ msec: 1168
+ hash: "39cb2bdc44273023b557a0f56df61d85"
+ }
+ Frame {
+ msec: 1184
+ hash: "2cda045b452c4645be1cdb4efd238532"
+ }
+ Frame {
+ msec: 1200
+ hash: "1f3efbfadd22734b5fd656596c11885b"
+ }
+ Frame {
+ msec: 1216
+ hash: "7277c05a06e481a5af13e4fe39e322f8"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1232
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1248
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1264
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1280
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1296
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1312
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1328
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1344
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1360
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1376
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1392
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1408
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1424
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1440
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1456
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1472
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1488
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1504
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 1520
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1536
+ hash: "c5f88e95ead1f4542b766577d80e70fd"
+ }
+ Frame {
+ msec: 1552
+ hash: "d38118f26b9c2b68dc8fdb8d2a959134"
+ }
+ Frame {
+ msec: 1568
+ hash: "44c483c899220f040aa7808f15fac429"
+ }
+ Frame {
+ msec: 1584
+ hash: "02a63967944c8c53a9741318e99a326e"
+ }
+ Frame {
+ msec: 1600
+ hash: "7fc10e91212af979e09c8d3b98625c1b"
+ }
+ Frame {
+ msec: 1616
+ hash: "d14b69d18adc548dfb68dae1559effdb"
+ }
+ Frame {
+ msec: 1632
+ hash: "cb9bce7fa14a367197fa34ad3acc4cdd"
+ }
+ Frame {
+ msec: 1648
+ hash: "105a0e3d36296eba16077c4cf93547ae"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1664
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1680
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1696
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1712
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1728
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1744
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1760
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1776
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1792
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1808
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1824
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1840
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1856
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1872
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1888
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1904
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1920
+ image: "test3.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1952
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1968
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 1984
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 2000
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2016
+ hash: "6e4e4321cda32abab394419a9e6494dc"
+ }
+ Frame {
+ msec: 2032
+ hash: "45b79c56379afa7243547fedfa3260db"
+ }
+ Frame {
+ msec: 2048
+ hash: "4635555c632f325a151d340a3eb742b9"
+ }
+ Frame {
+ msec: 2064
+ hash: "0255da44fa95548427139073c994234c"
+ }
+ Frame {
+ msec: 2080
+ hash: "eac0c428ea7b7aa55a469562d2cb3fd6"
+ }
+ Frame {
+ msec: 2096
+ hash: "06ab23a83a5900cfdde98d4563414511"
+ }
+ Frame {
+ msec: 2112
+ hash: "808e4a745c58872d52ec6a3e669aea5c"
+ }
+ Frame {
+ msec: 2128
+ hash: "e6231b43f93fd6ae3e0990def1168c39"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2144
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2160
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2176
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2192
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2208
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2224
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2240
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2256
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2272
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2288
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2304
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2320
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2336
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2352
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2368
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2384
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2400
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2416
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2432
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2448
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2464
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2480
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2496
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 2512
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2528
+ hash: "e1c32968e36cb95be250121187ddf13e"
+ }
+ Frame {
+ msec: 2544
+ hash: "70498453babe3ab5e0fec62bcd0ff332"
+ }
+ Frame {
+ msec: 2560
+ hash: "76fc1b1e6b22771bf08dfdd16b3f24e9"
+ }
+ Frame {
+ msec: 2576
+ hash: "c6be4f26750b8bc1a5b71ff381e462c6"
+ }
+ Frame {
+ msec: 2592
+ hash: "986f738d0f0f70b88f951d9f028ef61b"
+ }
+ Frame {
+ msec: 2608
+ hash: "2201ad4f92bcf24ab62d0ddb8b2a64c1"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2624
+ hash: "27e9a18cb70c8f2ab9e4dd7af321e8e4"
+ }
+ Frame {
+ msec: 2640
+ hash: "3a352127f49f8c589b7b7da1232caf6b"
+ }
+ Frame {
+ msec: 2656
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2672
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2688
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2704
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2720
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2736
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2752
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2768
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2784
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2800
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2816
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2832
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2848
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2864
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2880
+ image: "test3.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2912
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2928
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2944
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2960
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 2976
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2992
+ hash: "20f96d3fbef9d51d8b8a28a6d58fabb2"
+ }
+ Frame {
+ msec: 3008
+ hash: "1e5d888fd4685960b8ae0a79e2287e89"
+ }
+ Frame {
+ msec: 3024
+ hash: "2115c2e6689ce6669abf9f3741eb5df1"
+ }
+ Frame {
+ msec: 3040
+ hash: "c67949eb5f2210c6b2dad4ff352831ed"
+ }
+ Frame {
+ msec: 3056
+ hash: "d982500bee0a6f6fb0861fb3c32319eb"
+ }
+ Frame {
+ msec: 3072
+ hash: "ffb111084712d5ecf072ade52103b985"
+ }
+ Frame {
+ msec: 3088
+ hash: "e5d594c8f08b9d283a3998648a383332"
+ }
+ Frame {
+ msec: 3104
+ hash: "20632ba6a4c14386eb01167059f7b617"
+ }
+ Frame {
+ msec: 3120
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3136
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3152
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3168
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3184
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3200
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3216
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3232
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3248
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3264
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3280
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3296
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3312
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3328
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3344
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3360
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3376
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3392
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3408
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3424
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3440
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3456
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3472
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 3488
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3504
+ hash: "f60a72dd52f6f319706dc97f873a484f"
+ }
+ Frame {
+ msec: 3520
+ hash: "a21fbcbb3c0ede708f2862959b84654f"
+ }
+ Frame {
+ msec: 3536
+ hash: "40e5f7530391e7641498c7870ce986c9"
+ }
+ Frame {
+ msec: 3552
+ hash: "809daf15ad3e9f981f1306da18dd6872"
+ }
+ Frame {
+ msec: 3568
+ hash: "4b053d234c8c9a5afb7800abe28ea96f"
+ }
+ Frame {
+ msec: 3584
+ hash: "e011e3aaf143befc8e207945fdfc9f47"
+ }
+ Frame {
+ msec: 3600
+ hash: "55539d51f833b8a98fc14031a4a70c4c"
+ }
+ Frame {
+ msec: 3616
+ hash: "07c2b526c022d0deae61acba26d7ea24"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3632
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3648
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3664
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3680
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3696
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3712
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3728
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3744
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3760
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3776
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3792
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3808
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3824
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3840
+ image: "test3.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3872
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3888
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3904
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3920
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3936
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3952
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3968
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 3984
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4000
+ hash: "7d2f24d5a68397bedc2f9e3652715126"
+ }
+ Frame {
+ msec: 4016
+ hash: "55ff9205bb36d8f8965fb122a8686203"
+ }
+ Frame {
+ msec: 4032
+ hash: "8968377cbbdf7a46b6f13690826ac711"
+ }
+ Frame {
+ msec: 4048
+ hash: "8ce9afffac571f1a2cc6986d79dd2c8f"
+ }
+ Frame {
+ msec: 4064
+ hash: "f75c375cdf8e1b83398e9b18e7c39852"
+ }
+ Frame {
+ msec: 4080
+ hash: "20c8db7fb344c056465175ed0fa9518a"
+ }
+ Frame {
+ msec: 4096
+ hash: "8135c2cae0dcf8ee6eccbfdd7b711bc0"
+ }
+ Frame {
+ msec: 4112
+ hash: "659fc24d328058eb118be5613ea25257"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4128
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4144
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4160
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4176
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4192
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4208
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4224
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4240
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4256
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4272
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4288
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4304
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4320
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4336
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4352
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4368
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4384
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4400
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4416
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4432
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4448
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4464
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4480
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4496
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4512
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4528
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4544
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4560
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4576
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4592
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4608
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4624
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4640
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4656
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4672
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4688
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4704
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4720
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4736
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4752
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4768
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4784
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4800
+ image: "test3.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4832
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4848
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4864
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4880
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4896
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4912
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4928
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4944
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4960
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4976
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 4992
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 5008
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 5024
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 5040
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 5056
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 5072
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 5088
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Frame {
+ msec: 5104
+ hash: "ef9a34bf49c632be0f88f6658196dfe6"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5120
+ hash: "f01088d95d8409f98ae19b7970ecf3ad"
+ }
+ Frame {
+ msec: 5136
+ hash: "393987a9e22db77233465e3d08cfb244"
+ }
+ Frame {
+ msec: 5152
+ hash: "40e58eac132aa3b5f66f244ab7b189be"
+ }
+ Frame {
+ msec: 5168
+ hash: "d60c98c5fafe6bfa73a3d0c55f8f6716"
+ }
+ Frame {
+ msec: 5184
+ hash: "775733a71bb1d39f51b9fbc7e28d9ffe"
+ }
+ Frame {
+ msec: 5200
+ hash: "a343457f584c6e63aaec36b5db4fb7d0"
+ }
+ Frame {
+ msec: 5216
+ hash: "7c416bd1be54135056b037642026251f"
+ }
+ Frame {
+ msec: 5232
+ hash: "42813b6c3ef437a7b3ea8f03bb8b1894"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5248
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5264
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5280
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5296
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5312
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5328
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5344
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5360
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5376
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5392
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5408
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5424
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5440
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5456
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5472
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5488
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5504
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5520
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5536
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5552
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5568
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5584
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5600
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5616
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5632
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5648
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5664
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5680
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5696
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Frame {
+ msec: 5712
+ hash: "cc0ab553f98262662e52191e0b370486"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5728
+ hash: "b3af171ca40a5f081e2bfc984b8da551"
+ }
+ Frame {
+ msec: 5744
+ hash: "aadbc8c960fbe2e8aac184a99ba818bd"
+ }
+ Frame {
+ msec: 5760
+ image: "test3.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "99fc06589f09cd10cfdf748f032eacbd"
+ }
+ Frame {
+ msec: 5792
+ hash: "f7915b1a8b9f7188263180a97c8b355f"
+ }
+ Frame {
+ msec: 5808
+ hash: "7fb30728fb764b659bad5bb6c4e71e2c"
+ }
+ Frame {
+ msec: 5824
+ hash: "4882459350feffaed89c2296c74b839d"
+ }
+ Frame {
+ msec: 5840
+ hash: "917a368858e431bebcd8f2fda67401f8"
+ }
+ Frame {
+ msec: 5856
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5872
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 5888
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 5904
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 5920
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 5936
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 5952
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 5968
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 5984
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6000
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6016
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6032
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6048
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6064
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6080
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6096
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6112
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6128
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6144
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6160
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6176
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6192
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6208
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6224
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6240
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6256
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Frame {
+ msec: 6272
+ hash: "bfd0497c6505d42aefe6341adb850d89"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 6288
+ hash: "ada3c3558261701c705ecf79716df56a"
+ }
+ Frame {
+ msec: 6304
+ hash: "81c73fd3dd69eb767d8899a54c3088bb"
+ }
+ Frame {
+ msec: 6320
+ hash: "d54e7dd1e876666f64b5904240bf8764"
+ }
+ Frame {
+ msec: 6336
+ hash: "32bdeac66a43a967d549ca2ad8c59bbd"
+ }
+ Frame {
+ msec: 6352
+ hash: "04eec62cc40c8b31d989bead64909f9e"
+ }
+ Frame {
+ msec: 6368
+ hash: "cfffdd4edc35303ee260ed32956238b7"
+ }
+ Frame {
+ msec: 6384
+ hash: "fb562c38b9d2360517160f8a8ab29ced"
+ }
+ Frame {
+ msec: 6400
+ hash: "ba8ec8f0663bf1e62ff426b0c7d0d3b2"
+ }
+ Frame {
+ msec: 6416
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 6432
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6448
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6464
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6480
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6496
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6512
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6528
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6544
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6560
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6576
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6592
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6608
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6624
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6640
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6656
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6672
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6688
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6704
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6720
+ image: "test3.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6752
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6768
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6784
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6800
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6816
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6832
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Frame {
+ msec: 6848
+ hash: "e3b2de8a4e3229880971d2144e55de1b"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 6864
+ hash: "e6292a001405924f6d5f1a4051c3f6cb"
+ }
+ Frame {
+ msec: 6880
+ hash: "0d8a6b740cc7b33659aa0a1cc2bd2aa9"
+ }
+ Frame {
+ msec: 6896
+ hash: "07c4267ff499c46977420d4be7529e04"
+ }
+ Frame {
+ msec: 6912
+ hash: "f69cd14d97de3ca8d21ace1df1d5a523"
+ }
+ Frame {
+ msec: 6928
+ hash: "1572b31fd3ae917d5701d0b8f1d2a2bc"
+ }
+ Frame {
+ msec: 6944
+ hash: "e3953027fe269a5d4c6581717d516c65"
+ }
+ Frame {
+ msec: 6960
+ hash: "e35e8a5dfa7309696fa20c6f5480ac50"
+ }
+ Frame {
+ msec: 6976
+ hash: "77e75e66118f911c8fff084e1a825d77"
+ }
+ Frame {
+ msec: 6992
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7008
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7024
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7040
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7056
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7072
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7088
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7104
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7120
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7136
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7152
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7168
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7184
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7200
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7216
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7232
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7248
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7264
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7280
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7296
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7312
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7328
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7344
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7360
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7376
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7392
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7408
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7424
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Frame {
+ msec: 7440
+ hash: "e97f921f1c34246fc229c48a4b66466c"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7456
+ hash: "8588c30394737cebc5580fe024589b08"
+ }
+ Frame {
+ msec: 7472
+ hash: "ca150a32b22cad95696ecfbad0ed3e67"
+ }
+ Frame {
+ msec: 7488
+ hash: "7f980e0cf67927918b1244456c38c7c0"
+ }
+ Frame {
+ msec: 7504
+ hash: "2bc38fb34a6875aabddce0f460914612"
+ }
+ Frame {
+ msec: 7520
+ hash: "328257a4691f341db39ee5ca677693eb"
+ }
+ Frame {
+ msec: 7536
+ hash: "05e0d8c986ff81e23f253d56ebdef46e"
+ }
+ Frame {
+ msec: 7552
+ hash: "be95d74a42318c52ab73ce694436a58b"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7568
+ hash: "eba8512746494f3602d24dab86fb2559"
+ }
+ Frame {
+ msec: 7584
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7600
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7616
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7632
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7648
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7664
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7680
+ image: "test3.7.png"
+ }
+ Frame {
+ msec: 7696
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7712
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7728
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7744
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7760
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7776
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7792
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7808
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7824
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7840
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7856
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7872
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7888
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7904
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7920
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7936
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7952
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Frame {
+ msec: 7968
+ hash: "8f443766efd0f74e96e79ed3c267892c"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7984
+ hash: "7b2b3a84e9649370ce282383a820c39b"
+ }
+ Frame {
+ msec: 8000
+ hash: "08547adce7e02eec593fa636af004257"
+ }
+ Frame {
+ msec: 8016
+ hash: "29789cfbd1b648ce705cf17d03298ffe"
+ }
+ Frame {
+ msec: 8032
+ hash: "9e89ef84c86b1fc0531f0bd5ee530ba5"
+ }
+ Frame {
+ msec: 8048
+ hash: "21b437a318c5ef87c38f9199772eafa6"
+ }
+ Frame {
+ msec: 8064
+ hash: "70c8c8fbcf2d0331ca7ede8641a6068b"
+ }
+ Frame {
+ msec: 8080
+ hash: "c277e9d4f89e99d974d03dcfe41a1755"
+ }
+ Frame {
+ msec: 8096
+ hash: "54c7a72a3f814e707777c16ddd4532b8"
+ }
+ Frame {
+ msec: 8112
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 8128
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8144
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8160
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8176
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8192
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8208
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8224
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8240
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8256
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8272
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8288
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8304
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8320
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8336
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8352
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8368
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8384
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8400
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8416
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8432
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8448
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8464
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8480
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Frame {
+ msec: 8496
+ hash: "bdf37518633a43d8dc47245f5b68550b"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 8512
+ hash: "7992512c72fe530fdd92866c96de29a0"
+ }
+ Frame {
+ msec: 8528
+ hash: "ad29d3653790efb998ac137538b4ce09"
+ }
+ Frame {
+ msec: 8544
+ hash: "f6daf0ad7f7c970ece3dc1898ab9f092"
+ }
+ Frame {
+ msec: 8560
+ hash: "417143caa8ed86082ea4e40aca7ca26e"
+ }
+ Frame {
+ msec: 8576
+ hash: "5215943d1fbffd5ef7c16d4ca6587628"
+ }
+ Frame {
+ msec: 8592
+ hash: "d143c87d3cf7560f911e98869983efef"
+ }
+ Frame {
+ msec: 8608
+ hash: "1fcb9b3d3b4c888c65334b88e240d79c"
+ }
+ Frame {
+ msec: 8624
+ hash: "61cec1c227eafafe6c03a33591b1825e"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 8640
+ image: "test3.8.png"
+ }
+ Frame {
+ msec: 8656
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8672
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8688
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8704
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8720
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8736
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8752
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8768
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8784
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8800
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8816
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8832
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8848
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8864
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8880
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8896
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8912
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8928
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8944
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8960
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8976
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 8992
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 9008
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 9024
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 9040
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Frame {
+ msec: 9056
+ hash: "57e009de047c348d3ae14a6271b2e6f2"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 9072
+ hash: "fcbb907bcf41602a5c30e2843a4b1fff"
+ }
+ Frame {
+ msec: 9088
+ hash: "5fee95daaa629bbf0cec3e41cd693502"
+ }
+ Frame {
+ msec: 9104
+ hash: "b9d721d2a8b0867bab29817b99b8ec2d"
+ }
+ Frame {
+ msec: 9120
+ hash: "e518e9872a502d3b2ff74d209626c9ee"
+ }
+ Frame {
+ msec: 9136
+ hash: "9c535d7da59ed2f2ce116e70c3e165cf"
+ }
+ Frame {
+ msec: 9152
+ hash: "e54fbcb23e01d5842885b92d4493535b"
+ }
+ Frame {
+ msec: 9168
+ hash: "7ac2467f24cef06c8842460ffe813ee0"
+ }
+ Frame {
+ msec: 9184
+ hash: "276293e289db5c9c7cd9612c73ef7792"
+ }
+ Frame {
+ msec: 9200
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 9216
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9232
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9248
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9264
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9280
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9296
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9312
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9328
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9344
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9360
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9376
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9392
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9408
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9424
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9440
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9456
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9472
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9488
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9504
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9520
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9536
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9552
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9568
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9584
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9600
+ image: "test3.9.png"
+ }
+ Frame {
+ msec: 9616
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9632
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9648
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9664
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9680
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9696
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9712
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9728
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9744
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9760
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9776
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9792
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9808
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9824
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9840
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9856
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9872
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9888
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9904
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9920
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9936
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9952
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9968
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 9984
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10000
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10016
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10032
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10048
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10064
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10080
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10096
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10112
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10128
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10144
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10160
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10176
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10192
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10208
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10224
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10240
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10256
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10272
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10288
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10304
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10320
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10336
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10352
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10368
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 10384
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10400
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10416
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+ Frame {
+ msec: 10432
+ hash: "d38da3f61cd2944eec8bdfbef70c928f"
+ }
+}
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test.0.png b/tests/auto/declarative/visual/focusscope/data-X11/test.0.png
new file mode 100644
index 0000000..f68f7dc
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test.1.png b/tests/auto/declarative/visual/focusscope/data-X11/test.1.png
new file mode 100644
index 0000000..f68f7dc
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test.2.png b/tests/auto/declarative/visual/focusscope/data-X11/test.2.png
new file mode 100644
index 0000000..e26c028
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test.3.png b/tests/auto/declarative/visual/focusscope/data-X11/test.3.png
new file mode 100644
index 0000000..9c4b2f2
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test.4.png b/tests/auto/declarative/visual/focusscope/data-X11/test.4.png
new file mode 100644
index 0000000..9c4b2f2
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test.5.png b/tests/auto/declarative/visual/focusscope/data-X11/test.5.png
new file mode 100644
index 0000000..9c4b2f2
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test.qml b/tests/auto/declarative/visual/focusscope/data-X11/test.qml
new file mode 100644
index 0000000..93189fa
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test.qml
@@ -0,0 +1,1599 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 32
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 48
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 64
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 80
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 96
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 112
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 128
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 144
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 160
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 176
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 192
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 208
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 224
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 240
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 256
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 272
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 288
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 304
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 320
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 336
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 352
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 368
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 384
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 400
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 416
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 432
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 448
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 464
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 480
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 496
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 512
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 528
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 544
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 560
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 576
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 592
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 608
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 624
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 640
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 656
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 672
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 688
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 704
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 720
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 736
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 752
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 768
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 784
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 800
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 816
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 832
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 848
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 864
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 880
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 896
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 912
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 928
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 944
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 960
+ image: "test.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 992
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1008
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1024
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1040
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1056
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1072
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1088
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1104
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1120
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1136
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1152
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1168
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1184
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1200
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1216
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1232
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1248
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1264
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1280
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1296
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1312
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1328
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1344
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1360
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1376
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1392
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1408
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1424
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1440
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1456
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1472
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1488
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1504
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1520
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1536
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1552
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1568
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1584
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1600
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1616
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1632
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1648
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1664
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1680
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1696
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1712
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1728
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1744
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1760
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1776
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1792
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 1808
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1824
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1840
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1856
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1872
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1888
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1904
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1920
+ image: "test.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1952
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1968
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 1984
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2000
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2016
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2032
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2048
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2064
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2080
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2096
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2112
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2128
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2144
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2160
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2176
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2192
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2208
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2224
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2240
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2256
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2272
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2288
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2304
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2320
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2336
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 2352
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Key {
+ type: 6
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2368
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2384
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2400
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2416
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2432
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2448
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2464
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Key {
+ type: 7
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2480
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2496
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2512
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2528
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2544
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2560
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2576
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2592
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2608
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2624
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2640
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2656
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2672
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2688
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2704
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2720
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2736
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2752
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2768
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2784
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2800
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2816
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2832
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2848
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2864
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2880
+ image: "test.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2912
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2928
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2944
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2960
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 2976
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Key {
+ type: 6
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2992
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3008
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3024
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3040
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3056
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3072
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3088
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Key {
+ type: 7
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3104
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3120
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3136
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3152
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3168
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3184
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3200
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3216
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3232
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3248
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3264
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3280
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3296
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3312
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3328
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3344
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3360
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3376
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3392
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3408
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3424
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3440
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3456
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3472
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3488
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3504
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3520
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Frame {
+ msec: 3536
+ hash: "cd2aced96da9032ddd5e2cacf27d045d"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3552
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3568
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3584
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3600
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3616
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3632
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3648
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3664
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3680
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3696
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3712
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3728
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3744
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3760
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3776
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3792
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3808
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3824
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3840
+ image: "test.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3872
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3888
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3904
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3920
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3936
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3952
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3968
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 3984
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4000
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4016
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4032
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4048
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4064
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4080
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4096
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4112
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4128
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4144
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4160
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4176
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Key {
+ type: 6
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4192
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4208
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4224
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4240
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4256
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4272
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Key {
+ type: 7
+ key: 16777237
+ modifiers: 536870912
+ text: "1f"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4288
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4304
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4320
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4336
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4352
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4368
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4384
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4400
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4416
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4432
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4448
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4464
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4480
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4496
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4512
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4528
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4544
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4560
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4576
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4592
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4608
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4624
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4640
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4656
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4672
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4688
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4704
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4720
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4736
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4752
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4768
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Frame {
+ msec: 4784
+ hash: "9157e592069482e801a091aa69758d26"
+ }
+ Key {
+ type: 6
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4800
+ image: "test.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4832
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4848
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4864
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4880
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4896
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Key {
+ type: 7
+ key: 16777235
+ modifiers: 536870912
+ text: "1e"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4912
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4928
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4944
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4960
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4976
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 4992
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5008
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5024
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5040
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5056
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5072
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5088
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5104
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5120
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5136
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5152
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5168
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5184
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5200
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5216
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5232
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5248
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5264
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5280
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5296
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5312
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5328
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5344
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5360
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5376
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5392
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5408
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5424
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5440
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5456
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5472
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5488
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5504
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5520
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5536
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5552
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5568
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5584
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5600
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5616
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5632
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5648
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5664
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5680
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5696
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5712
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5728
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5744
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5760
+ image: "test.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5792
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5808
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5824
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5840
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5856
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5872
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+ Frame {
+ msec: 5888
+ hash: "0de58b2460574baf17912e90ba8a89b2"
+ }
+}
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test2.0.png b/tests/auto/declarative/visual/focusscope/data-X11/test2.0.png
new file mode 100644
index 0000000..6be7aef
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test2.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test2.1.png b/tests/auto/declarative/visual/focusscope/data-X11/test2.1.png
new file mode 100644
index 0000000..6be7aef
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test2.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test2.qml b/tests/auto/declarative/visual/focusscope/data-X11/test2.qml
new file mode 100644
index 0000000..7170907
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test2.qml
@@ -0,0 +1,607 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 32
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 48
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 64
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 80
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 96
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 112
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 128
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 144
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 160
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 176
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 192
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 208
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 224
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 240
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 256
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 272
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 288
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 304
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 320
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 336
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 352
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 368
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 384
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 400
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 416
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 432
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 448
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 464
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 480
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 496
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 512
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 528
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 544
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 560
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 576
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 592
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 608
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 624
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 640
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 656
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 672
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 688
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 704
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 720
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 736
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 752
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 768
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 784
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 800
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 816
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 832
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 848
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 864
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 880
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 896
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 912
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 928
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 944
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 960
+ image: "test2.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 992
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1008
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1024
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1040
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1056
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1072
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1088
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1104
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1120
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1136
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1152
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1168
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1184
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1200
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1216
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1232
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1248
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1264
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1280
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1296
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1312
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1328
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1344
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1360
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1376
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1392
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1408
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1424
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1440
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1456
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1472
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1488
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1504
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1520
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1536
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1552
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1568
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1584
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1600
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1616
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1632
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1648
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1664
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1680
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1696
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1712
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1728
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1744
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1760
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1776
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1792
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1808
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1824
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1840
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1856
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1872
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1888
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1904
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1920
+ image: "test2.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1952
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1968
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 1984
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2000
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2016
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2032
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2048
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2064
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2080
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2096
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2112
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2128
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2144
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2160
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2176
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2192
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2208
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2224
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2240
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2256
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 0
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2272
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2288
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2304
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2320
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2336
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2352
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+ Frame {
+ msec: 2368
+ hash: "529409797f67656145ea88544bb8cc9f"
+ }
+}
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.0.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.0.png
new file mode 100644
index 0000000..5f93c67
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.1.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.1.png
new file mode 100644
index 0000000..3b4e0e6
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.2.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.2.png
new file mode 100644
index 0000000..54a3934
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.3.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.3.png
new file mode 100644
index 0000000..4f08fd2
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.4.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.4.png
new file mode 100644
index 0000000..9aee1f8
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.5.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.5.png
new file mode 100644
index 0000000..04eb05c
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.6.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.6.png
new file mode 100644
index 0000000..54a3934
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.7.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.7.png
new file mode 100644
index 0000000..3b4e0e6
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.8.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.8.png
new file mode 100644
index 0000000..2df55df
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.9.png b/tests/auto/declarative/visual/focusscope/data-X11/test3.9.png
new file mode 100644
index 0000000..91816fd
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.9.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data-X11/test3.qml b/tests/auto/declarative/visual/focusscope/data-X11/test3.qml
new file mode 100644
index 0000000..b1f628f
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data-X11/test3.qml
@@ -0,0 +1,2879 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame {
+ msec: 0
+ }
+ Frame {
+ msec: 16
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 32
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 48
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 64
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 80
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 96
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 112
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 128
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 144
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 160
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 176
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 192
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 208
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 224
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 240
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 256
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 272
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 288
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 304
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 320
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 336
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 352
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 368
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 384
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 400
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 416
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 432
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 448
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 464
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 480
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 496
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 512
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 528
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 544
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 560
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 576
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 592
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 608
+ hash: "ed71dfbe146870d1a0869d60c35ff9d7"
+ }
+ Frame {
+ msec: 624
+ hash: "ed71dfbe146870d1a0869d60c35ff9d7"
+ }
+ Frame {
+ msec: 640
+ hash: "34796cef9feb92f7f0e2e8d837d87d34"
+ }
+ Frame {
+ msec: 656
+ hash: "64fa8f195b57077aa03ca264fec9554a"
+ }
+ Frame {
+ msec: 672
+ hash: "ae33318904415e937363787273ecb566"
+ }
+ Frame {
+ msec: 688
+ hash: "67c3e1c8c728e7677a3554aadd9795c9"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 704
+ hash: "1857db7aa9eefe429d50e5b2ad87064b"
+ }
+ Frame {
+ msec: 720
+ hash: "507883a03bef0bc20755da1474731fdf"
+ }
+ Frame {
+ msec: 736
+ hash: "dafe7464394460e04d482c1f7a1e9ad0"
+ }
+ Frame {
+ msec: 752
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 768
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 784
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 800
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 816
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 832
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 848
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 864
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 880
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 896
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 912
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 928
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 944
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 960
+ image: "test3.0.png"
+ }
+ Frame {
+ msec: 976
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 992
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 1008
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 1024
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 1040
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 1056
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 1072
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 1088
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1104
+ hash: "7fb8cb07b6bca30912706cec43984d92"
+ }
+ Frame {
+ msec: 1120
+ hash: "7fb8cb07b6bca30912706cec43984d92"
+ }
+ Frame {
+ msec: 1136
+ hash: "c1915978cda982f6062790b2a583211b"
+ }
+ Frame {
+ msec: 1152
+ hash: "afdb50d740b3dc7be44021d826be4302"
+ }
+ Frame {
+ msec: 1168
+ hash: "4682717b9375b4b02a70378ddca30885"
+ }
+ Frame {
+ msec: 1184
+ hash: "aede0eebb3948a4a764e255b892b09be"
+ }
+ Frame {
+ msec: 1200
+ hash: "b42a147daec14a3da2548fd4de3a9a44"
+ }
+ Frame {
+ msec: 1216
+ hash: "2ff70f916f78fe3c199eb96ceb44ce4e"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1232
+ hash: "707ac8e58d317b97113903b45a482f6b"
+ }
+ Frame {
+ msec: 1248
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1264
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1280
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1296
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1312
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1328
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1344
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1360
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1376
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1392
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1408
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1424
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1440
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1456
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1472
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1488
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1504
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 1520
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1536
+ hash: "91525556fe23764f58b3a3f38a29cd76"
+ }
+ Frame {
+ msec: 1552
+ hash: "91525556fe23764f58b3a3f38a29cd76"
+ }
+ Frame {
+ msec: 1568
+ hash: "d1dc625bbf46fc51aaf47969ad27a8a4"
+ }
+ Frame {
+ msec: 1584
+ hash: "7d868176c7a8363a79ef8b8f4da56867"
+ }
+ Frame {
+ msec: 1600
+ hash: "d239e0b0e118d351680c6b4b2bc5d3b2"
+ }
+ Frame {
+ msec: 1616
+ hash: "8f6d1640dbc655eb3b326c66fcb97d3c"
+ }
+ Frame {
+ msec: 1632
+ hash: "d52b623b8449d71734f72c7bd661a1c4"
+ }
+ Frame {
+ msec: 1648
+ hash: "f7c0c77f3b5ed71321edd6bc7b605512"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 1664
+ hash: "8b26397ff1a83baa894f82594a12a190"
+ }
+ Frame {
+ msec: 1680
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1696
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1712
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1728
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1744
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1760
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1776
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1792
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1808
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1824
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1840
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1856
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1872
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1888
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1904
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1920
+ image: "test3.1.png"
+ }
+ Frame {
+ msec: 1936
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1952
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1968
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 1984
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 2000
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2016
+ hash: "f63308a7cd48a8cb4d413d17120f5a26"
+ }
+ Frame {
+ msec: 2032
+ hash: "f63308a7cd48a8cb4d413d17120f5a26"
+ }
+ Frame {
+ msec: 2048
+ hash: "2e97db8ed93524dc197e76cc2d270999"
+ }
+ Frame {
+ msec: 2064
+ hash: "2b135d90684c0f94b8219c4b835b6da9"
+ }
+ Frame {
+ msec: 2080
+ hash: "c700a76932bb3bf72868b9e95d095db2"
+ }
+ Frame {
+ msec: 2096
+ hash: "08136d3c3de44ddab23d2d136ba1f310"
+ }
+ Frame {
+ msec: 2112
+ hash: "de701d641e004b61a3c0609556f52fe0"
+ }
+ Frame {
+ msec: 2128
+ hash: "4f7acd87f4de119ad88a53d2c9881037"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2144
+ hash: "deaf3c8a4680ef6f52cb4674a97e0767"
+ }
+ Frame {
+ msec: 2160
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2176
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2192
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2208
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2224
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2240
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2256
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2272
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2288
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2304
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2320
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2336
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2352
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2368
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2384
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2400
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2416
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2432
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2448
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2464
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2480
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2496
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 2512
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2528
+ hash: "fe67b3a48a8a074377be64f619d5922a"
+ }
+ Frame {
+ msec: 2544
+ hash: "fe67b3a48a8a074377be64f619d5922a"
+ }
+ Frame {
+ msec: 2560
+ hash: "088691f4f46f7a8c9a3b8ea766d9a437"
+ }
+ Frame {
+ msec: 2576
+ hash: "bd747ea04c3b36378374f8ea1031458f"
+ }
+ Frame {
+ msec: 2592
+ hash: "2ebd0e3373eb75a3ad986e203952f78a"
+ }
+ Frame {
+ msec: 2608
+ hash: "b4d89e4f3aef9f351facd13bd83f3022"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2624
+ hash: "091de1bd1719e1fa6d914cf9708f4ac6"
+ }
+ Frame {
+ msec: 2640
+ hash: "0097d8ed156cb0c78c48dfacc557cba8"
+ }
+ Frame {
+ msec: 2656
+ hash: "faeb379e01283cb21ea695e96727918d"
+ }
+ Frame {
+ msec: 2672
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2688
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2704
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2720
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2736
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2752
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2768
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2784
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2800
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2816
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2832
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2848
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2864
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2880
+ image: "test3.2.png"
+ }
+ Frame {
+ msec: 2896
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2912
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2928
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2944
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2960
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 2976
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 2992
+ hash: "b00a29d67edc26e75f5298b2836d4e47"
+ }
+ Frame {
+ msec: 3008
+ hash: "b00a29d67edc26e75f5298b2836d4e47"
+ }
+ Frame {
+ msec: 3024
+ hash: "6e47c87b5063877a609e8d23ddf2d314"
+ }
+ Frame {
+ msec: 3040
+ hash: "06f147a69c3e903905376ef1229290bf"
+ }
+ Frame {
+ msec: 3056
+ hash: "5f02ff1a1207f17efd224ccc800b0057"
+ }
+ Frame {
+ msec: 3072
+ hash: "6c0860fdb216bb79fd2da4647792628d"
+ }
+ Frame {
+ msec: 3088
+ hash: "eb579f67620adb762722428d44a1d841"
+ }
+ Frame {
+ msec: 3104
+ hash: "c579017a82e34a471a95f8a116a20b9e"
+ }
+ Frame {
+ msec: 3120
+ hash: "bb5c08ff104b230829579dfb8015bdcc"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3136
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3152
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3168
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3184
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3200
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3216
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3232
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3248
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3264
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3280
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3296
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3312
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3328
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3344
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3360
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3376
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3392
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3408
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3424
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3440
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3456
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3472
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 3488
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3504
+ hash: "5aa664f268433f2724a1ab2cea1d6d25"
+ }
+ Frame {
+ msec: 3520
+ hash: "5aa664f268433f2724a1ab2cea1d6d25"
+ }
+ Frame {
+ msec: 3536
+ hash: "9e4854fd0c533efa75aec7d9a8bc41dd"
+ }
+ Frame {
+ msec: 3552
+ hash: "c4eee4eca804007dca6e6d9379cbfb1b"
+ }
+ Frame {
+ msec: 3568
+ hash: "c59774f00d54c0353b41202a39fc0dbd"
+ }
+ Frame {
+ msec: 3584
+ hash: "910e6b5b05530c60874eee00df0d62cf"
+ }
+ Frame {
+ msec: 3600
+ hash: "5b606a7a697c6d53fbe42e33333f96cc"
+ }
+ Frame {
+ msec: 3616
+ hash: "e1fce42312e8a31d74add4a447dd3df9"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 3632
+ hash: "6250cb9ea51309922cf0a6647593bfee"
+ }
+ Frame {
+ msec: 3648
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3664
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3680
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3696
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3712
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3728
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3744
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3760
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3776
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3792
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3808
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3824
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3840
+ image: "test3.3.png"
+ }
+ Frame {
+ msec: 3856
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3872
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3888
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3904
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3920
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3936
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3952
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3968
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 3984
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Key {
+ type: 6
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4000
+ hash: "d6eecfb695deacae4bb2fe5adb2d5c3d"
+ }
+ Frame {
+ msec: 4016
+ hash: "d6eecfb695deacae4bb2fe5adb2d5c3d"
+ }
+ Frame {
+ msec: 4032
+ hash: "b48f481a8149c03139e29b619dbb3f3c"
+ }
+ Frame {
+ msec: 4048
+ hash: "994ba7fc208bbf081d54384d82d0fc07"
+ }
+ Frame {
+ msec: 4064
+ hash: "05d30293c12eb6a3e21cebd42bb1f383"
+ }
+ Frame {
+ msec: 4080
+ hash: "f2b4140a5d26f241a27e2a3027785559"
+ }
+ Frame {
+ msec: 4096
+ hash: "1189e519fd1611c5603e598fbcadca44"
+ }
+ Frame {
+ msec: 4112
+ hash: "ee98893d95e55cb76966c0cfe29d237b"
+ }
+ Key {
+ type: 7
+ key: 16777236
+ modifiers: 536870912
+ text: "1d"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 4128
+ hash: "9ff3010efeb8707c864def782405ad4c"
+ }
+ Frame {
+ msec: 4144
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4160
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4176
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4192
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4208
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4224
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4240
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4256
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4272
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4288
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4304
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4320
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4336
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4352
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4368
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4384
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4400
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4416
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4432
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4448
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4464
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4480
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4496
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4512
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4528
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4544
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4560
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4576
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4592
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4608
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4624
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4640
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4656
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4672
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4688
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4704
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4720
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4736
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4752
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4768
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4784
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4800
+ image: "test3.4.png"
+ }
+ Frame {
+ msec: 4816
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4832
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4848
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4864
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4880
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4896
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4912
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4928
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4944
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4960
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4976
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 4992
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 5008
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 5024
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 5040
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 5056
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 5072
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 5088
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Frame {
+ msec: 5104
+ hash: "c842d544f87332bc133833e8966240ee"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5120
+ hash: "a857238777462319fcedd4f359ce1a04"
+ }
+ Frame {
+ msec: 5136
+ hash: "a857238777462319fcedd4f359ce1a04"
+ }
+ Frame {
+ msec: 5152
+ hash: "d9248d1257bf0232dcdf29fca7536ad1"
+ }
+ Frame {
+ msec: 5168
+ hash: "0405e029cc4b2fa80761c06fb8898b0d"
+ }
+ Frame {
+ msec: 5184
+ hash: "a36fb7e32e6aafbb84b62ef56be3cf70"
+ }
+ Frame {
+ msec: 5200
+ hash: "9846c73bbe57277bd36bbca1c489e644"
+ }
+ Frame {
+ msec: 5216
+ hash: "8f4840715082c48d520ddb55501cf8eb"
+ }
+ Frame {
+ msec: 5232
+ hash: "478fde3a6fd8cecc222b8c16743d231f"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5248
+ hash: "b2bb760c93d26c6db21ce6beccd36b66"
+ }
+ Frame {
+ msec: 5264
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5280
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5296
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5312
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5328
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5344
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5360
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5376
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5392
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5408
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5424
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5440
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5456
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5472
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5488
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5504
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5520
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5536
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5552
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5568
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5584
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5600
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5616
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5632
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5648
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5664
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5680
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5696
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Frame {
+ msec: 5712
+ hash: "1ef605e1a68ff993f4f971a85a6bee97"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5728
+ hash: "4780d8094833831f27d1aff3e0f9689f"
+ }
+ Frame {
+ msec: 5744
+ hash: "4780d8094833831f27d1aff3e0f9689f"
+ }
+ Frame {
+ msec: 5760
+ image: "test3.5.png"
+ }
+ Frame {
+ msec: 5776
+ hash: "93c8d7980de378a055b7ca824882ae4e"
+ }
+ Frame {
+ msec: 5792
+ hash: "e0abe402f89c5d84e5a02f0e4bcbd5e3"
+ }
+ Frame {
+ msec: 5808
+ hash: "067ca20bcfab459a28af7e8dc2830032"
+ }
+ Frame {
+ msec: 5824
+ hash: "d27dc1a08c66cf5f4a84efe3be522ec3"
+ }
+ Frame {
+ msec: 5840
+ hash: "639f7555adc7958e807c2e774694fe25"
+ }
+ Frame {
+ msec: 5856
+ hash: "b55f5fcbc2284736695049b2cdc9c8ce"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 5872
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 5888
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 5904
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 5920
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 5936
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 5952
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 5968
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 5984
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6000
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6016
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6032
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6048
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6064
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6080
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6096
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6112
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6128
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6144
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6160
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6176
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6192
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6208
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6224
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6240
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6256
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Frame {
+ msec: 6272
+ hash: "f209867bbf74dbe0385655a522e322f1"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 6288
+ hash: "48910947dd160b33251c54ff45f6a0db"
+ }
+ Frame {
+ msec: 6304
+ hash: "48910947dd160b33251c54ff45f6a0db"
+ }
+ Frame {
+ msec: 6320
+ hash: "20b0f988a1517d67a0d3c78ae8af4e5a"
+ }
+ Frame {
+ msec: 6336
+ hash: "355b5b161176c31bcbae198b1581f59b"
+ }
+ Frame {
+ msec: 6352
+ hash: "19cbb853a93bd062a53d7908df54bfbd"
+ }
+ Frame {
+ msec: 6368
+ hash: "13fbe723f288cffd09f0a86b71457161"
+ }
+ Frame {
+ msec: 6384
+ hash: "0014ed3b1a868cf75bfffedb52674c5c"
+ }
+ Frame {
+ msec: 6400
+ hash: "a1c444be02b90e69319096b8a508947d"
+ }
+ Frame {
+ msec: 6416
+ hash: "b88a3f2f3290e4262757b1f5741cb5ce"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 6432
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6448
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6464
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6480
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6496
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6512
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6528
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6544
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6560
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6576
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6592
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6608
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6624
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6640
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6656
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6672
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6688
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6704
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6720
+ image: "test3.6.png"
+ }
+ Frame {
+ msec: 6736
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6752
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6768
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6784
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6800
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6816
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6832
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Frame {
+ msec: 6848
+ hash: "dc708a762ba7f1120eb14105571943f8"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 6864
+ hash: "a44bb76233c69780c178dddd79cc1968"
+ }
+ Frame {
+ msec: 6880
+ hash: "a44bb76233c69780c178dddd79cc1968"
+ }
+ Frame {
+ msec: 6896
+ hash: "154b11fd0468aa18d1ef1895f2e2923c"
+ }
+ Frame {
+ msec: 6912
+ hash: "fe7ecb02e63fbb7584405e7162f0ee21"
+ }
+ Frame {
+ msec: 6928
+ hash: "90b6fea69d106c628a9c7ff23a97e6c2"
+ }
+ Frame {
+ msec: 6944
+ hash: "3e233e837e24976d441b6cabc3b74098"
+ }
+ Frame {
+ msec: 6960
+ hash: "7a490f7be5c4c0ae09421f884e9adadb"
+ }
+ Frame {
+ msec: 6976
+ hash: "462d44603dd661ccf126c81197608056"
+ }
+ Frame {
+ msec: 6992
+ hash: "0b7ca73497c37255bccad6787d690236"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7008
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7024
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7040
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7056
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7072
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7088
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7104
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7120
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7136
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7152
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7168
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7184
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7200
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7216
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7232
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7248
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7264
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7280
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7296
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7312
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7328
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7344
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7360
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7376
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7392
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7408
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7424
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Frame {
+ msec: 7440
+ hash: "224ade5c942415100b5418a11d043611"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7456
+ hash: "95ff2a535a13fcdded94229d53848f7c"
+ }
+ Frame {
+ msec: 7472
+ hash: "95ff2a535a13fcdded94229d53848f7c"
+ }
+ Frame {
+ msec: 7488
+ hash: "d2386e4137632f15aa5ba9dd1a138a67"
+ }
+ Frame {
+ msec: 7504
+ hash: "9f2c40191c1a81f37543f5bfcb852bdf"
+ }
+ Frame {
+ msec: 7520
+ hash: "5facdbcc9d7ab0adfcb2ca9d1812a3f5"
+ }
+ Frame {
+ msec: 7536
+ hash: "7bbb08470e4f3eeabe710e0ea327c467"
+ }
+ Frame {
+ msec: 7552
+ hash: "630abf60d09d3a685d79e6da627b3aa2"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7568
+ hash: "d8aed706508814cdbd1ef0984f112b94"
+ }
+ Frame {
+ msec: 7584
+ hash: "d191c2dc3e2edd05bfd649dcfa51029e"
+ }
+ Frame {
+ msec: 7600
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7616
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7632
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7648
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7664
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7680
+ image: "test3.7.png"
+ }
+ Frame {
+ msec: 7696
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7712
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7728
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7744
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7760
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7776
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7792
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7808
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7824
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7840
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7856
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7872
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7888
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7904
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7920
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7936
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7952
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Frame {
+ msec: 7968
+ hash: "7ee37281a3f5788305f779bdd33852e5"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 7984
+ hash: "fb386abfd73a3feb05b573d16ffa93f9"
+ }
+ Frame {
+ msec: 8000
+ hash: "fb386abfd73a3feb05b573d16ffa93f9"
+ }
+ Frame {
+ msec: 8016
+ hash: "fa1374155fc5427c72bd09ec5a315172"
+ }
+ Frame {
+ msec: 8032
+ hash: "ee35a3edf91865e28b16b9fcab8b4c1c"
+ }
+ Frame {
+ msec: 8048
+ hash: "10f2677f7c8efe9f64e401940dec3ef7"
+ }
+ Frame {
+ msec: 8064
+ hash: "b2c53bb14a8a6643e69cad2bbb4aacf4"
+ }
+ Frame {
+ msec: 8080
+ hash: "7b7c7d167aca55464d1874ed726ec646"
+ }
+ Frame {
+ msec: 8096
+ hash: "19a828ca70133801f1f470f6e348857b"
+ }
+ Frame {
+ msec: 8112
+ hash: "bc829873ea3cf8ca8484d990d4b80aa2"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 8128
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8144
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8160
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8176
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8192
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8208
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8224
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8240
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8256
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8272
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8288
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8304
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8320
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8336
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8352
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8368
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8384
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8400
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8416
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8432
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8448
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8464
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8480
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Frame {
+ msec: 8496
+ hash: "201b90bc27073e945bb00c85501f4dc8"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 8512
+ hash: "d0d487fd66bcf4177188d4862bd74bc0"
+ }
+ Frame {
+ msec: 8528
+ hash: "d0d487fd66bcf4177188d4862bd74bc0"
+ }
+ Frame {
+ msec: 8544
+ hash: "4a4c2e49e4852748916a4d68710e4ae6"
+ }
+ Frame {
+ msec: 8560
+ hash: "0135092d8a296b7121495cc3994a0f9d"
+ }
+ Frame {
+ msec: 8576
+ hash: "7e004aae70236568d635ba929e085b2b"
+ }
+ Frame {
+ msec: 8592
+ hash: "3e6a4f60a57515a6bfe4d803c7c22da8"
+ }
+ Frame {
+ msec: 8608
+ hash: "142b866861f539837b0bdabaf48028e7"
+ }
+ Frame {
+ msec: 8624
+ hash: "32a4757602c923366566d9005c78f6cf"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 8640
+ image: "test3.8.png"
+ }
+ Frame {
+ msec: 8656
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8672
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8688
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8704
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8720
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8736
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8752
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8768
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8784
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8800
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8816
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8832
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8848
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8864
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8880
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8896
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8912
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8928
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8944
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8960
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8976
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 8992
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 9008
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 9024
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 9040
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Frame {
+ msec: 9056
+ hash: "358a3fbfa70526a40f2179cb2fd100d4"
+ }
+ Key {
+ type: 6
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 9072
+ hash: "b1dc330f31b064f1e3ff4e913773cde8"
+ }
+ Frame {
+ msec: 9088
+ hash: "b1dc330f31b064f1e3ff4e913773cde8"
+ }
+ Frame {
+ msec: 9104
+ hash: "a0419dede71451f36c93960c8ef8c00c"
+ }
+ Frame {
+ msec: 9120
+ hash: "b8141758fc93aa1b286fd60f91e6fa7e"
+ }
+ Frame {
+ msec: 9136
+ hash: "8b0d786f239c545be3f51622c336f1e1"
+ }
+ Frame {
+ msec: 9152
+ hash: "25ec52efac83de4f8cade8f257b93b8e"
+ }
+ Frame {
+ msec: 9168
+ hash: "5a1476841b9aaa0e85c397c0447be352"
+ }
+ Frame {
+ msec: 9184
+ hash: "d648b0911e6ab78e53121fde8b66b50b"
+ }
+ Frame {
+ msec: 9200
+ hash: "f552863ff4b76286d03240409c0a928b"
+ }
+ Key {
+ type: 7
+ key: 16777234
+ modifiers: 536870912
+ text: "1c"
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 9216
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9232
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9248
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9264
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9280
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9296
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9312
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9328
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9344
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9360
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9376
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9392
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9408
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9424
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9440
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9456
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9472
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9488
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9504
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9520
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9536
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9552
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9568
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9584
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9600
+ image: "test3.9.png"
+ }
+ Frame {
+ msec: 9616
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9632
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9648
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9664
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9680
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9696
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9712
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9728
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9744
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9760
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9776
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9792
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9808
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9824
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9840
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9856
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9872
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9888
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9904
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9920
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9936
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9952
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9968
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 9984
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10000
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10016
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10032
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10048
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10064
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10080
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10096
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10112
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10128
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10144
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10160
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10176
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10192
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10208
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10224
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10240
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10256
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10272
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10288
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10304
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10320
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10336
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10352
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10368
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Key {
+ type: 6
+ key: 16777249
+ modifiers: 67108864
+ text: ""
+ autorep: false
+ count: 1
+ }
+ Frame {
+ msec: 10384
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10400
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10416
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+ Frame {
+ msec: 10432
+ hash: "f3b4cab7975190f756c923f16ce4c298"
+ }
+}
diff --git a/tests/auto/declarative/visual/focusscope/data/test.0.png b/tests/auto/declarative/visual/focusscope/data/test.0.png
new file mode 100644
index 0000000..67b99e0
--- /dev/null
+++ b/tests/auto/declarative/visual/focusscope/data/test.0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/focusscope/data/test.1.png b/tests/auto/declarative/visual/focusscope/data/test.1.png
new file mode 100644